import { Head, Link, usePage } from '@inertiajs/react';
import { useEffect, useMemo, useState } from 'react';
import { AppInvestPageFrame } from '@/components/app-page';
import { Separator } from '@/components/ui/separator';
import InvestmentConfigCard from '@/pages/investments/components/investment-config-card';
import InvestmentConfirmation from '@/pages/investments/components/investment-confirmation';
import InvestmentDetailsCard from '@/pages/investments/components/investment-details-card';
import InvestmentPaymentInfo from '@/pages/investments/components/investment-payment-info';
import type {
    InvestmentDuration,
    InvestmentSetting,
} from '@/pages/investments/types';
import { calculateProjection } from '@/pages/investments/utils';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';

const REINVEST_MIN = 0.01;

type Props = {
    settings: InvestmentSetting;
    durations: InvestmentDuration[];
    withdrawable_balance_usd: string;
    reinvest_mode?: boolean;
};

export default function InvestmentIndex({
    settings,
    durations,
    withdrawable_balance_usd,
    reinvest_mode: reinvestModeProp = false,
}: Props) {
    const page = usePage<{
        kyc?: {
            investor_portal_unlocked?: boolean;
            require_kyc_for_invest?: boolean;
        };
    }>();
    const unlocked = page.props.kyc?.investor_portal_unlocked === true;
    const requireInvestKyc = page.props.kyc?.require_kyc_for_invest ?? true;
    const canTransact = unlocked || !requireInvestKyc;

    const isReinvestMode = reinvestModeProp;

    const withdrawableNum = useMemo(
        () => Number.parseFloat(withdrawable_balance_usd.replace(',', '.')) || 0,
        [withdrawable_balance_usd],
    );

    const minAmount = Number(settings.min_amount);
    const maxAmount = Number(settings.max_amount);
    const monthlyReturn = Number(settings.monthly_return);

    const effectiveMinAmount = isReinvestMode ? REINVEST_MIN : minAmount;
    const effectiveMaxAmount = useMemo(() => {
        if (!isReinvestMode) {
            return maxAmount;
        }

        return Math.min(maxAmount, withdrawableNum);
    }, [isReinvestMode, maxAmount, withdrawableNum]);

    const canReinvestConfigure = !isReinvestMode || withdrawableNum >= REINVEST_MIN;

    const [amount, setAmount] = useState(minAmount);
    const [durationMonths, setDurationMonths] = useState(
        durations[0]?.months ?? 1,
    );
    const [isConfirming, setIsConfirming] = useState(false);
    const [copied, setCopied] = useState(false);
    const [fundingSource, setFundingSource] = useState<'blockchain' | 'balance'>('blockchain');

    const investmentAmount = useMemo(() => {
        const rounded = Math.round(amount * 100) / 100;

        return Math.min(effectiveMaxAmount, Math.max(effectiveMinAmount, rounded));
    }, [amount, effectiveMaxAmount, effectiveMinAmount]);

    const projection = useMemo(
        () =>
            calculateProjection({
                amount: investmentAmount,
                durationMonths,
                durations,
                monthlyReturn,
            }),
        [investmentAmount, durationMonths, durations, monthlyReturn],
    );

    useEffect(() => {
        if (isReinvestMode && withdrawableNum >= REINVEST_MIN) {
            setAmount(Math.round(effectiveMaxAmount * 100) / 100);

            return;
        }

        setAmount((prev) => {
            const rounded = Math.round(prev * 100) / 100;

            return Math.min(effectiveMaxAmount, Math.max(effectiveMinAmount, rounded));
        });
    }, [effectiveMinAmount, effectiveMaxAmount, isReinvestMode, withdrawableNum]);

    useEffect(() => {
        if (!canTransact) {
            setIsConfirming(false);
        }
    }, [canTransact]);

    useEffect(() => {
        if (!isConfirming) {
            setFundingSource('blockchain');
        }
    }, [isConfirming]);

    useEffect(() => {
        if (isConfirming && isReinvestMode) {
            setFundingSource('balance');
        }
    }, [isConfirming, isReinvestMode]);

    function patchAmount(next: number) {
        const rounded = Math.round(next * 100) / 100;
        setAmount(Math.min(effectiveMaxAmount, Math.max(effectiveMinAmount, rounded)));
    }

    function copyPaymentAddress() {
        void navigator.clipboard.writeText(settings.payment_address.trim());
        setCopied(true);
        window.setTimeout(() => setCopied(false), 2000);
    }

    return (
        <>
            <Head title={isConfirming ? 'Confirmar inversión' : 'Invertir'} />

            <AppInvestPageFrame>
                    <div className="mx-auto w-full max-w-2xl lg:mx-0 lg:pr-6">
                        {isReinvestMode && !canReinvestConfigure ? (
                            <div className="mb-4 rounded-xl border border-amber-500/40 bg-amber-500/10 px-4 py-3 text-sm text-amber-950 dark:text-amber-50">
                                Para <strong className="font-medium">reinvertir</strong> necesitas al menos{' '}
                                {REINVEST_MIN.toFixed(2)} US$ de saldo retirable. Revisa en{' '}
                                <Link className="font-medium underline" href="/balances">
                                    Mis balances
                                </Link>
                                .
                            </div>
                        ) : null}
                        {isConfirming ? (
                            <InvestmentConfirmation
                                canSubmitInvestment={canTransact}
                                projection={projection}
                                fundingSource={fundingSource}
                                minInvestmentAmount={isReinvestMode ? REINVEST_MIN : minAmount}
                                reinvestMode={isReinvestMode}
                                onCancel={() => setIsConfirming(false)}
                                onFundingSourceChange={setFundingSource}
                                withdrawableBalanceUsd={withdrawable_balance_usd}
                            />
                        ) : (
                            <InvestmentConfigCard
                                amount={investmentAmount}
                                canStartInvestment={canTransact && canReinvestConfigure}
                                durationMonths={durationMonths}
                                durations={durations}
                                maxAmount={Math.max(effectiveMinAmount, effectiveMaxAmount)}
                                minAmount={effectiveMinAmount}
                                projection={projection}
                                reinvestMode={isReinvestMode}
                                onAmountChange={patchAmount}
                                onDurationChange={setDurationMonths}
                                onInvest={() => setIsConfirming(true)}
                            />
                        )}
                    </div>

                    <Separator className="my-4 lg:hidden" />

                    <Separator
                        className="hidden self-stretch lg:block"
                        orientation="vertical"
                    />

                    <div className="w-full min-w-0 pt-4 lg:w-[400px] lg:shrink-0 lg:pl-6 lg:pt-0">
                        {isConfirming ? (
                            fundingSource === 'blockchain' ? (
                                <InvestmentPaymentInfo
                                    copied={copied}
                                    settings={settings}
                                    onCopyPaymentAddress={copyPaymentAddress}
                                />
                            ) : (
                                <Card className="w-full overflow-hidden border-primary/20 bg-card">
                                    <CardHeader className="space-y-1 p-5 pb-2">
                                        <CardTitle className="text-lg">Pago con saldo retirable</CardTitle>
                                        <CardDescription>
                                            No necesitas QR ni TXID para esta opción. El capital se mueve igual que cuando
                                            se aprueba un retiro desde tu libro: debe haber suficiente saldo retirable{' '}
                                            <strong className="text-foreground">
                                                libre dentro de tus contratos vigentes,
                                            </strong>{' '}
                                            no sólo valor contable invertido pendiente de vencer.
                                        </CardDescription>
                                    </CardHeader>
                                    <CardContent className="text-muted-foreground space-y-2 p-5 pt-0 text-xs">
                                        <p>
                                            La inversión queda{' '}
                                            <strong className="text-foreground">activa al instante</strong> después de
                                            enviar — no aparece pendiente por validación blockchain.
                                        </p>
                                        <p>
                                            Tu saldo retirable disponible ahora{' '}
                                            <span className="font-medium tabular-nums text-foreground">
                                                {withdrawable_balance_usd} US$
                                            </span>{' '}
                                            (consulta también en Balances si lo deseas antes de invertir).
                                        </p>
                                    </CardContent>
                                </Card>
                            )
                        ) : (
                            <InvestmentDetailsCard
                                durations={durations}
                                maxAmount={Math.max(effectiveMinAmount, effectiveMaxAmount)}
                                minAmount={effectiveMinAmount}
                                monthlyReturn={monthlyReturn}
                            />
                        )}
                    </div>
            </AppInvestPageFrame>
        </>
    );
}

InvestmentIndex.layout = {
    breadcrumbs: [
        {
            title: 'Invertir',
            href: '/invertir',
        },
    ],
};
