import {DotsVerticalIcon, TrashIcon} from '@heroicons/react/solid'
import React, {useEffect, useState} from 'react'
import {useQuery} from '@tanstack/react-query'

import useApiUrlStore from '../../../app/store/apiStore'
import useBacktestStore from '../../../app/store/backtestStore'
import type {
    Backtest,
    MoneyManagement,
    StartBotRequest,
    TradingBotConfig,
    TradingBotConfigRequest
} from '../../../generated/ManagingApi'
import {BacktestClient, BotClient, MoneyManagementClient} from '../../../generated/ManagingApi'
import MoneyManagementModal from '../../../pages/settingsPage/moneymanagement/moneyManagementModal'
import {CardPosition, CardText, Toast} from '../../mollecules'
import CardPositionItem from '../Trading/CardPositionItem'
import TradeChart from '../Trading/TradeChart/TradeChart'
import {BotNameModal} from '../index'

function baseBadgeClass(isOutlined = false) {
    let classes = 'text-xs badge '

    if (isOutlined) {
        classes += 'badge-outline '
    }
    return classes
}

function botStatusResult(
    growthPercentage: number | undefined,
    hodlPercentage: number | undefined
) {
    if (growthPercentage != undefined && hodlPercentage != undefined) {
        const isWinning = growthPercentage > hodlPercentage
        const classes =
            baseBadgeClass() + (isWinning ? 'badge-success' : 'badge-content')
        return <div className={classes}>{isWinning ? 'Winning' : 'Losing'}</div>
    }
}

// function that return the number of day between a date and today
function daysBetween(date: Date) {
    const oneDay = 24 * 60 * 60 * 1000 // hours*minutes*seconds*milliseconds
    const firstDate = new Date(date)
    const secondDate = new Date()
    const diffDays = Math.round(
        Math.abs((firstDate.getTime() - secondDate.getTime()) / oneDay)
    )
    return diffDays
}

interface BacktestCardsProps {
    list: Backtest[] | undefined
}

const BacktestCards: React.FC<BacktestCardsProps> = ({list}) => {
    console.log(list)
    const {apiUrl} = useApiUrlStore()
    const {addBacktest, removeBacktest} = useBacktestStore()
    const [showMoneyManagementModal, setShowMoneyManagementModal] =
        React.useState(false)
    const [selectedMoneyManagement, setSelectedMoneyManagement] =
        React.useState<MoneyManagement>()
    const [showBotNameModal, setShowBotNameModal] = useState(false)
    const [isForWatchOnly, setIsForWatchOnly] = useState(false)
    const [currentBacktest, setCurrentBacktest] = useState<Backtest | null>(null)
    const [selectedMoneyManagementName, setSelectedMoneyManagementName] = useState<string>('')

    // Fetch money managements
    const {data: moneyManagements} = useQuery({
        queryFn: async () => {
            const moneyManagementClient = new MoneyManagementClient({}, apiUrl)
            return await moneyManagementClient.moneyManagement_GetMoneyManagements()
        },
        queryKey: ['moneyManagements'],
    })

    // Set the first money management as default when the data is loaded
    useEffect(() => {
        if (moneyManagements && moneyManagements.length > 0) {
            setSelectedMoneyManagementName(moneyManagements[0].name)
        }
    }, [moneyManagements])

    async function runBot(botName: string, backtest: Backtest, isForWatchOnly: boolean, moneyManagementName: string, initialTradingBalance: number) {
        const t = new Toast('Bot is starting')
        const client = new BotClient({}, apiUrl)

        // Check if the money management name is "custom" or contains "custom"
        const isCustomMoneyManagement =
            !moneyManagementName ||
            moneyManagementName.toLowerCase() === 'custom' ||
            moneyManagementName.toLowerCase().includes('custom');

        // Create TradingBotConfig from the backtest configuration
        const tradingBotConfig: TradingBotConfig = {
            accountName: backtest.config.accountName,
            ticker: backtest.config.ticker,
            scenarioName: backtest.config.scenarioName,
            timeframe: backtest.config.timeframe,
            isForWatchingOnly: isForWatchOnly,
            isForBacktest: false, // This is for running a live bot
            cooldownPeriod: backtest.config.cooldownPeriod,
            maxLossStreak: backtest.config.maxLossStreak,
            maxPositionTimeHours: backtest.config.maxPositionTimeHours,
            flipOnlyWhenInProfit: backtest.config.flipOnlyWhenInProfit,
            flipPosition: backtest.config.flipPosition,
            name: botName,
            botTradingBalance: initialTradingBalance,
            // Use the optimized or original money management from backtest if it's custom
            moneyManagement: isCustomMoneyManagement ?
                (backtest.optimizedMoneyManagement || backtest.config.moneyManagement || {
                    name: 'default',
                    leverage: 1,
                    stopLoss: 0.01,
                    takeProfit: 0.02,
                    timeframe: backtest.config.timeframe
                }) :
                backtest.config.moneyManagement, // Always provide a valid MoneyManagement object
            closeEarlyWhenProfitable: backtest.config.closeEarlyWhenProfitable || false
        };

        const request: StartBotRequest = {
            config: tradingBotConfig as unknown as TradingBotConfigRequest,
        }

        await client
            .bot_Start(request)
            .then((botStatus: string) => {
                t.update('info', 'Bot status: ' + botStatus)
            })
            .catch((err) => {
                t.update('error', 'Error: ' + err)
            })
    }

    const handleOpenBotNameModal = (backtest: Backtest, isForWatchOnly: boolean) => {
        setCurrentBacktest(backtest)
        setIsForWatchOnly(isForWatchOnly)
        setShowBotNameModal(true)
    }

    const handleCloseBotNameModal = () => {
        setShowBotNameModal(false)
    }

    const handleSubmitBotName = (botName: string, backtest: Backtest, isForWatchOnly: boolean, moneyManagementName: string, initialTradingBalance: number) => {
        runBot(botName, backtest, isForWatchOnly, moneyManagementName, initialTradingBalance)
        setShowBotNameModal(false)
    }

    async function deleteBacktest(id: string) {
        const t = new Toast('Deleting backtest')
        const client = new BacktestClient({}, apiUrl)

        await client
            .backtest_DeleteBacktest(id)
            .then(() => {
                t.update('success', 'Backtest deleted')
                // Remove the deleted backtest from the store
                removeBacktest(id)
            })
            .catch((err) => {
                t.update('error', err)
            })
    }

    function saveMoneyManagement(moneyManagement: MoneyManagement) {
        setSelectedMoneyManagement(moneyManagement)
        setShowMoneyManagementModal(true)
    }

    return (
        <div className="flex flex-wrap m-4 -mx-4">
            {list?.map((backtest: Backtest, index: number) => (
                <div
                    key={index.toString()}
                    className="sm:w-1/2 md:w-1/2 xl:w-1/2 w-full p-2"
                >
                    <div className="indicator">
                        <div className="indicator-item indicator-top">
                            <div className="tooltip" data-tip="Delete backtest">
                                <button 
                                    className="btn btn-primary h-5 min-h-0 px-2 mr-5 rounded-full"
                                    onClick={() => deleteBacktest(backtest.id ?? '')}
                                >
                                    <TrashIcon width={15}></TrashIcon>
                                </button>
                            </div>
                        </div>

                        <div className="card bg-base-300 shadow-xl">
                            <figure className="z-0">
                                {
                                    <TradeChart
                                        candles={backtest.candles}
                                        positions={backtest.positions}
                                        walletBalances={backtest.walletBalances}
                                        signals={backtest.signals}
                                        indicatorsValues={backtest.indicatorsValues}
                                        width={720}
                                        height={512}
                                    ></TradeChart>
                                }
                            </figure>

                            <div className="card-body">
                                <h2 className="card-title text-sm">
                                    <div className="dropdown">
                                        <label
                                            htmlFor={index.toString()}
                                            tabIndex={index}
                                            className=""
                                        >
                                            <DotsVerticalIcon className="text-primary w-5 h-5"/>
                                        </label>
                                        <ul
                                            id={index.toString()}
                                            className="dropdown-content menu bg-base-100 rounded-box w-52 p-2 shadow"
                                        >
                                            <li>
                                                <button
                                                    className="text-xs"
                                                    onClick={() => handleOpenBotNameModal(backtest, false)}
                                                >
                                                    Run bot
                                                </button>
                                            </li>
                                            <li>
                                                <button
                                                    className="text-xs"
                                                    onClick={() => handleOpenBotNameModal(backtest, true)}
                                                >
                                                    Run watcher
                                                </button>
                                            </li>
                                            <li>
                                                <button
                                                    className="text-xs"
                                                    onClick={() =>
                                                        saveMoneyManagement(backtest.config.moneyManagement)
                                                    }
                                                >
                                                    Save money management
                                                </button>
                                            </li>
                                        </ul>
                                    </div>
                                    {backtest.config.ticker}
                                    {botStatusResult(
                                        backtest.growthPercentage,
                                        backtest.hodlPercentage
                                    )}
                                </h2>
                                <div className="columns-4 mb-2">
                                    <div>
                                        <CardText
                                            title="Ticker"
                                            content={backtest.config.ticker}
                                        ></CardText>
                                        <CardText
                                            title="Account"
                                            content={backtest.config.accountName}
                                        ></CardText>
                                        <CardText
                                            title="Scenario"
                                            content={backtest.config.scenarioName ?? backtest.config.scenario?.name}
                                        ></CardText>
                                        <CardText
                                            title="Timeframe"
                                            content={backtest.config.timeframe?.toString()}
                                        ></CardText>
                                    </div>
                                </div>
                                <div className="columns-4 mb-2">
                                    <CardPosition
                                        positivePosition={true}
                                        positions={backtest.positions.filter((p) => {
                                            const realized = p.profitAndLoss?.realized ?? 0
                                            return realized > 0 ? p : null
                                        })}
                                    ></CardPosition>
                                    <CardPosition
                                        positivePosition={false}
                                        positions={backtest.positions.filter((p) => {
                                            const realized = p.profitAndLoss?.realized ?? 0
                                            return realized <= 0 ? p : null
                                        })}
                                    ></CardPosition>
                                    <CardPositionItem
                                        positions={backtest.positions}
                                    ></CardPositionItem>
                                </div>

                                <div className="columns-4 mb-2">
                                    <div>
                                        <CardText
                                            title="Max Drowdown"
                                            content={
                                                backtest.statistics.maxDrawdown?.toFixed(4).toString() +
                                                '$'
                                            }
                                        ></CardText>
                                        <CardText
                                            title="PNL"
                                            content={backtest.finalPnl?.toFixed(4).toString() + '$'}
                                        ></CardText>
                                        <CardText
                                            title="Sharpe Ratio"
                                            content={
                                                (backtest.statistics.sharpeRatio
                                                        ? backtest.statistics.sharpeRatio * 100
                                                        : 0
                                                )
                                                    .toFixed(4)
                                                    .toString() + '%'
                                            }
                                        ></CardText>
                                        <CardText
                                            title="%Hodl"
                                            content={
                                                backtest.hodlPercentage?.toFixed(2).toString() + '%'
                                            }
                                        ></CardText>
                                    </div>
                                </div>
                                <div className="card-actions justify-center pt-2 text-sm">
                                    <div className={baseBadgeClass(true)}>
                                        WR {backtest.winRate?.toFixed(2).toString()} %
                                    </div>
                                    <div className={baseBadgeClass(true)}>
                                        PNL {backtest.growthPercentage?.toFixed(2).toString()} %
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            ))}

            <MoneyManagementModal
                showModal={showMoneyManagementModal}
                moneyManagement={selectedMoneyManagement}
                onClose={() => setShowMoneyManagementModal(false)}
            />

            {showBotNameModal && currentBacktest && moneyManagements && (
                <BotNameModal
                    showModal={showBotNameModal}
                    onClose={handleCloseBotNameModal}
                    backtest={currentBacktest}
                    isForWatchOnly={isForWatchOnly}
                    onSubmitBotName={(botName, backtest, isForWatchOnly, moneyManagementName, initialTradingBalance) =>
                        handleSubmitBotName(botName, backtest, isForWatchOnly, moneyManagementName, initialTradingBalance)
                    }
                    moneyManagements={moneyManagements}
                    selectedMoneyManagement={selectedMoneyManagementName}
                    setSelectedMoneyManagement={setSelectedMoneyManagementName}
                />
            )}
        </div>
    )
}

export default BacktestCards
