'use client';
import { useState, useMemo } from 'react'
import useSWR from 'swr'
import Alert from '@/components/ui/Alert'
import Avatar from '@/components/ui/Avatar'
import Button from '@/components/ui/Button'
import Card from '@/components/ui/Card'
import Dialog from '@/components/ui/Dialog'
import Input from '@/components/ui/Input'
import InputGroup from '@/components/ui/InputGroup'
import Select from '@/components/ui/Select'
import toast from '@/components/ui/toast'
import Notification from '@/components/ui/Notification'
import Loading from '@/components/shared/Loading'
import { useAssetsStore } from '../store/assetsStore'
import {
    apiGetMarketData,
    apiGetAvailableNetworks,
    apiGetDepositAddress,
    apiGetPortfolioAssets,
} from '@/services/client/CryptoService'
import SelectInputWithPrefix from '@/components/shared/SelectInputWithPrefix'
import SelectOptionWithPrefix from '@/components/shared/SelectOptionWithPrefix'
import IconFrame from '@/components/shared/IconFrame'
import { LiMoneyRecive, LiCross, LiChevronRight } from '@/icons'

const DepositDialog = () => {
    const { modals, closeAllModals, tableState } = useAssetsStore()
    const [selectedCrypto, setSelectedCrypto] = useState(undefined)
    const [selectedNetwork, setSelectedNetwork] = useState(undefined)
    const [walletAddress, setWalletAddress] = useState('')
    const [isLoadingAddress, setIsLoadingAddress] = useState(false)

    const { data: marketDataResponse, isLoading: loadingMarketData } = useSWR(modals.deposit ? '/api/crypto/market/data' : null, () =>
        apiGetMarketData({
            pageIndex: 1,
            pageSize: 100,
            sortKey: 'marketCap',
            sortOrder: 'desc',
        }), { revalidateOnFocus: false })

    const { data: assetsResponse } = useSWR(modals.deposit
        ? ['/api/crypto/portfolio/assets/deposit', tableState.assets]
        : null, ([, ts]) =>
        apiGetPortfolioAssets({
            pageIndex: ts.pageIndex,
            pageSize: ts.pageSize,
            sortKey: ts.sortKey,
            sortOrder: ts.sortOrder,
            query: ts.query,
        }), { revalidateOnFocus: false })

    const marketData = useMemo(() => marketDataResponse?.data || [], [marketDataResponse?.data])
    const assetsData = assetsResponse?.data

    const { data: networksResponse, isLoading: loadingNetworks } = useSWR(
        selectedCrypto ? '/api/crypto/networks' : null,
        () => apiGetAvailableNetworks(),
        { revalidateOnFocus: false }
    )

    const networks = useMemo(() => networksResponse?.data || [], [networksResponse?.data])

    const cryptoOptions = useMemo(() => {
        const ownedAssets = (assetsData || []).filter((a) => a.balance > 0)
        const ownedSymbols = new Set(ownedAssets.map((a) => a.symbol))
        const popularCryptos = marketData.slice(0, 20)
        const allCryptos = new Map()

        popularCryptos.forEach((crypto) =>
            allCryptos.set(crypto.symbol, crypto))
        ownedAssets.forEach((asset) => {
            if (!allCryptos.has(asset.symbol)) {
                allCryptos.set(asset.symbol, {
                    id: asset.id,
                    symbol: asset.symbol,
                    name: asset.name,
                    image: asset.icon,
                    price: asset.value / asset.balance,
                    priceChange24h: 0,
                    priceChangePercentage24h: asset.priceChangePercentage24h,
                    priceChangePercentage30d: 0,
                    marketCap: 0,
                    volume24h: 0,
                    circulatingSupply: 0,
                    sparklineData: [],
                    marketType: "spot",
                    rank: 999,
                })
            }
        })

        return Array.from(allCryptos.values()).map((crypto) => (({
            value: crypto.symbol,
            label: crypto.name,
            symbol: crypto.symbol,
            icon: crypto.image,
            isOwned: ownedSymbols.has(crypto.symbol),
        })));
    }, [marketData, assetsData])

    const networkOptions = useMemo(() =>
        networks.map((network) => (({
            value: network.id,
            label: network.name,
            symbol: network.symbol,
            fee: network.fee,
        }))), [networks])

    const loadWalletAddress = async () => {
        if (!selectedCrypto || !selectedNetwork) return
        setIsLoadingAddress(true)
        setWalletAddress('')
        try {
            const response = await apiGetDepositAddress(selectedNetwork.value)
            setWalletAddress(response.address)
        } catch {
            toast.push(<Notification type="danger" title="Error">
                Failed to generate wallet address
            </Notification>)
        } finally {
            setIsLoadingAddress(false)
        }
    }

    useMemo(() => {
        if (selectedCrypto && selectedNetwork) {
            loadWalletAddress()
        }
    }, [selectedCrypto, selectedNetwork]) // eslint-disable-line react-hooks/exhaustive-deps

    const copyAddress = () => {
        if (walletAddress) {
            navigator.clipboard.writeText(walletAddress)
            toast.push(<Notification type="success" title="Copied">
                Wallet address copied to clipboard
            </Notification>)
        }
    }

    const generateQRCode = () =>
        `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(walletAddress)}`

    const selectedNetworkData = networks.find((n) => n.id === selectedNetwork?.value)

    return (
        <Dialog
            isOpen={modals.deposit}
            onClose={closeAllModals}
            width={600}
            className="p-0"
            closable={false}>
            <div
                className="border-b border-gray-200 dark:border-gray-700 p-4 flex items-center justify-between gap-2">
                <div className="flex items-center gap-4">
                    <IconFrame variant="layered">
                        <LiMoneyRecive className="heading-text text-xl" />
                    </IconFrame>
                    <div>
                        <h5>Deposit Crypto</h5>
                        <p className="pr-12">
                            Select cryptocurrency and network to generate
                            deposit address
                        </p>
                    </div>
                </div>
                <Button
                    variant="subtle"
                    size="sm"
                    icon={<LiCross className="text-2xl" />}
                    type="button"
                    onClick={() => closeAllModals()} />
            </div>

            <div className="space-y-6 p-4">
                <div>
                    <label className="block text-sm font-medium mb-2">
                        Select Crypto
                    </label>
                    <Select
                        value={selectedCrypto}
                        onChange={(value) => {
                            setSelectedCrypto(value)
                            setSelectedNetwork(undefined)
                            setWalletAddress('')
                        }}
                        options={cryptoOptions}
                        isLoading={loadingMarketData}
                        placeholder={
                            loadingMarketData
                                ? 'Loading cryptocurrencies...'
                                : 'Select cryptocurrency'
                        }
                        customInputDisplay={(selectedItem) => {
                            const cryptoItem = selectedItem
                            return (
                                <SelectInputWithPrefix
                                    label={
                                        cryptoItem ? (
                                            <span className="font-medium heading-text">
                                                {cryptoItem.symbol}
                                            </span>
                                        ) : (
                                            ''
                                        )
                                    }
                                    prefix={
                                        cryptoItem && (
                                            <Avatar
                                                size="sm"
                                                src={cryptoItem.icon}
                                                alt={cryptoItem.symbol}
                                                className="w-5 h-5 border-0 bg-transparent" />
                                        )
                                    } />
                            );
                        }}
                        customOption={({ option, selected, CheckIcon }) => {
                            const cryptoOption =
                                option
                            return (
                                <SelectOptionWithPrefix
                                    selected={selected}
                                    checkIcon={CheckIcon}
                                    label={
                                        <>
                                            <span className="font-medium">
                                                {cryptoOption.symbol}
                                            </span>
                                            <span className="text-xs text-gray-500 dark:text-gray-400 font-normal">
                                                {cryptoOption.label}
                                            </span>
                                        </>
                                    }
                                    prefix={
                                        <Avatar
                                            size="sm"
                                            src={cryptoOption.icon}
                                            alt={cryptoOption.symbol}
                                            className="w-5 h-5 border-0 bg-transparent" />
                                    } />
                            );
                        }} />
                </div>

                {selectedCrypto && (
                    <div>
                        <label className="block text-sm font-medium mb-2">
                            Network
                        </label>
                        <Select
                            value={selectedNetwork}
                            onChange={(value) => {
                                setSelectedNetwork(value)
                                setWalletAddress('')
                            }}
                            options={networkOptions}
                            isLoading={loadingNetworks}
                            placeholder={
                                loadingNetworks
                                    ? 'Loading networks...'
                                    : 'Select network'
                            }
                            customInputDisplay={(selectedItem) => {
                                const networkItem = selectedItem
                                return <>
                                    {networkItem ? (
                                        <span className="flex items-center gap-1">
                                            <span className="heading-text font-medium">
                                                {networkItem.symbol}
                                            </span>
                                            -
                                            <span className="font-normal">
                                                {networkItem.label}
                                            </span>
                                        </span>
                                    ) : (
                                        ''
                                    )}
                                </>;
                            }}
                            customOption={({ option, selected, CheckIcon }) => {
                                const networkOption =
                                    option
                                return <>
                                    <div className="flex flex-col">
                                        <span className="heading-text font-medium">
                                            {networkOption.symbol}
                                        </span>
                                        <span className="text-xs">
                                            {networkOption.label}
                                        </span>
                                    </div>
                                    {selected && CheckIcon}
                                </>;
                            }} />
                    </div>
                )}

                {selectedCrypto && selectedNetwork && (
                    <div>
                        <div className="flex items-center justify-between mb-2">
                            <span className="font-medium">Deposit Address</span>
                        </div>

                        {isLoadingAddress ? (
                            <div className="flex items-center justify-center p-8">
                                <Loading loading />
                            </div>
                        ) : walletAddress ? (
                            <div className="space-y-4">
                                <Card bodyClass="flex items-center gap-4">
                                    <div className="flex-shrink-0">
                                        {/* eslint-disable-next-line @next/next/no-img-element */}
                                        <img
                                            src={generateQRCode()}
                                            alt="Deposit QR Code"
                                            className="w-24 h-24 rounded-lg" />
                                    </div>
                                    <div className="flex-1 space-y-2">
                                        <p className="mb-1">
                                            {selectedNetworkData?.name} (
                                            {selectedNetworkData?.symbol})
                                            Address
                                        </p>
                                        <InputGroup>
                                            <Input value={walletAddress} readOnly />
                                            <Button variant="solid" onClick={copyAddress}>
                                                Copy
                                            </Button>
                                        </InputGroup>
                                    </div>
                                </Card>
                                <div className="space-y-2 text-sm">
                                    <div className="flex justify-between">
                                        <span>Minimum deposit amount</span>
                                        <span className="heading-text">
                                            0 {selectedCrypto.value}
                                        </span>
                                    </div>
                                    <div className="flex justify-between">
                                        <span>Deposit Account</span>
                                        <span className="heading-text">
                                            Spot Account
                                        </span>
                                    </div>
                                    <div className="flex justify-between">
                                        <span>Pre-crediting</span>
                                        <span className="heading-text">
                                            15 network confirmations
                                        </span>
                                    </div>
                                    <div className="flex justify-between">
                                        <span>Credited Successfully</span>
                                        <span className="heading-text">
                                            61 network confirmations
                                        </span>
                                    </div>
                                    <div className="flex justify-between">
                                        <span>Contract Address</span>
                                        <button className="text-primary hover:underline flex items-center gap-1">
                                            <span>97955</span>
                                            <LiChevronRight />
                                        </button>
                                    </div>
                                </div>
                            </div>
                        ) : null}
                    </div>
                )}

                {selectedCrypto && selectedNetwork && walletAddress && (
                    <Alert type="info" showIcon title="Important Information">
                        <ul className="space-y-1 list-disc">
                            <li>
                                Only send {selectedCrypto.value} to this address
                                via {selectedNetworkData?.name} network
                            </li>
                            <li>
                                Sending any other cryptocurrency or using wrong
                                network will result in permanent loss
                            </li>
                            <li>Minimum deposit amount applies</li>
                            <li>Network fees are deducted from your deposit</li>
                        </ul>
                    </Alert>
                )}

                <Button block variant="subtle" onClick={closeAllModals}>
                    Close
                </Button>
            </div>
        </Dialog>
    );
}

export default DepositDialog
