import {
    AlertTriangle,
    ArrowRight,
    CalendarDays,
    Droplets,
    GraduationCap,
    Landmark,
    Scale,
    Sparkles,
    Target,
    ThumbsUp,
    TrendingUp,
} from 'lucide-react';
import { useState } from 'react';
import { GrowthScoreRadial } from '@/components/growth-score/growth-score-charts';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import { Spinner } from '@/components/ui/spinner';
import { csrfToken } from '@/lib/csrf';
import { GRADE_LABELS, GRADE_STYLES, isGrowthGrade } from '@/lib/growth-grade';
import { cn } from '@/lib/utils';
import {
    client as generateClientAdvice,
    mine as generateMyAdvice,
} from '@/routes/growth-score/advice';
import type {
    AdvisorActionItem,
    AdvisorAdvice,
    AdvisorImpact,
    GradeProjection,
    GrowthAnalysis,
    RatioScore,
    SavedAdvisorAdvice,
} from '@/types/growth-score';

type Props = {
    analysis: GrowthAnalysis;
    savedAdvice?: SavedAdvisorAdvice | null;
    externalCompany?: {
        id: string;
        accountType: string;
        name: string;
    };
};

const IMPACT_STYLES: Record<AdvisorImpact, string> = {
    high: 'border-red-500/40 bg-red-500/15 text-red-800 dark:text-red-300',
    medium: 'border-amber-500/40 bg-amber-500/15 text-amber-800 dark:text-amber-300',
    low: 'border-emerald-500/40 bg-emerald-500/15 text-emerald-800 dark:text-emerald-300',
};

const RATIO_META = [
    {
        key: 'profitability' as const,
        label: 'Profitability',
        icon: TrendingUp,
    },
    {
        key: 'liquidity' as const,
        label: 'Liquidity',
        icon: Droplets,
    },
    {
        key: 'solvency' as const,
        label: 'Solvency',
        icon: Landmark,
    },
    {
        key: 'efficiency' as const,
        label: 'Efficiency',
        icon: Scale,
    },
];

function isAdvisorAdvice(value: unknown): value is AdvisorAdvice {
    if (typeof value !== 'object' || value === null) {
        return false;
    }

    const advice = value as Record<string, unknown>;
    const plan = advice.three_month_plan;
    const projection = advice.next_grade_projection;
    const upskill = advice.upskill_recommendation;

    return (
        Array.isArray(advice.critical_must_do) &&
        Array.isArray(advice.areas_needing_focus) &&
        Array.isArray(advice.good_to_have) &&
        typeof plan === 'object' &&
        plan !== null &&
        typeof projection === 'object' &&
        projection !== null &&
        typeof upskill === 'object' &&
        upskill !== null
    );
}

function extractAdvice(payload: unknown): AdvisorAdvice | null {
    if (!isAdvisorAdvice(payload)) {
        return null;
    }

    return {
        critical_must_do: payload.critical_must_do,
        areas_needing_focus: payload.areas_needing_focus,
        good_to_have: payload.good_to_have,
        three_month_plan: payload.three_month_plan,
        next_grade_projection: payload.next_grade_projection,
        upskill_recommendation: payload.upskill_recommendation,
    };
}

function scoreBarColor(score: number | null): string {
    if (score === null) {
        return 'bg-muted-foreground/40';
    }

    if (score >= 80) {
        return 'bg-emerald-500';
    }

    if (score >= 65) {
        return 'bg-lime-500';
    }

    if (score >= 50) {
        return 'bg-amber-500';
    }

    return 'bg-red-500';
}

function impactStyle(impact: string): string {
    if (impact === 'high' || impact === 'medium' || impact === 'low') {
        return IMPACT_STYLES[impact];
    }

    return 'border-border bg-muted text-muted-foreground';
}

function ActionItemCard({ item }: { item: AdvisorActionItem }) {
    return (
        <div className="flex flex-col gap-2 rounded-xl border bg-card/80 p-3">
            <div className="flex items-start justify-between gap-2">
                <h4 className="text-sm leading-snug font-semibold">
                    {item.title}
                </h4>
                <Badge
                    variant="outline"
                    className={cn(
                        'shrink-0 text-[10px] font-semibold tracking-wide uppercase',
                        impactStyle(item.impact),
                    )}
                >
                    {item.impact} impact
                </Badge>
            </div>
            <p className="text-sm leading-relaxed text-muted-foreground">
                {item.description}
            </p>
        </div>
    );
}

function RatioBreakdownCard({
    label,
    icon: Icon,
    ratio,
}: {
    label: string;
    icon: typeof TrendingUp;
    ratio?: RatioScore;
}) {
    const score = ratio?.score ?? null;

    return (
        <div className="flex flex-col gap-2 rounded-xl border bg-card/80 p-3">
            <div className="flex items-center gap-2">
                <Icon className="size-4 text-muted-foreground" />
                <p className="text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                    {label}
                </p>
            </div>
            <div className="flex items-end justify-between gap-2">
                <p className="text-2xl font-bold tracking-tight">
                    {score === null ? '—' : Math.round(score)}
                </p>
                <p className="text-xs text-muted-foreground">
                    {ratio?.label ?? 'Unavailable'}
                </p>
            </div>
            <div className="h-1.5 overflow-hidden rounded-full bg-muted">
                <div
                    className={cn('h-full rounded-full', scoreBarColor(score))}
                    style={{ width: `${score === null ? 0 : score}%` }}
                />
            </div>
        </div>
    );
}

function GradeChip({
    grade,
    score,
    caption,
}: {
    grade: string | null;
    score?: number | null;
    caption: string;
}) {
    const validGrade = isGrowthGrade(grade) ? grade : null;

    return (
        <div className="flex min-w-0 flex-1 flex-col items-center gap-2 text-center">
            <div
                className={cn(
                    'flex size-14 items-center justify-center rounded-full border text-xl font-bold',
                    validGrade
                        ? GRADE_STYLES[validGrade]
                        : 'border-border bg-muted text-muted-foreground',
                )}
            >
                {validGrade ?? '—'}
            </div>
            <div>
                <p className="text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                    {caption}
                </p>
                {validGrade && (
                    <p className="text-sm font-medium">
                        {GRADE_LABELS[validGrade]}
                    </p>
                )}
                {score !== null && score !== undefined && (
                    <p className="text-xs text-muted-foreground">
                        {score}/100
                    </p>
                )}
            </div>
        </div>
    );
}

function GradeProgression({
    currentGrade,
    currentScore,
    months3,
    months6,
}: {
    currentGrade: string | null;
    currentScore: number | null;
    months3?: GradeProjection;
    months6?: GradeProjection;
}) {
    return (
        <div className="flex flex-col gap-4 rounded-xl border bg-card/80 p-4 md:flex-row md:items-center">
            <GradeChip
                grade={currentGrade}
                score={currentScore === null ? null : Math.round(currentScore)}
                caption="Current"
            />
            <ArrowRight className="mx-auto hidden size-5 text-muted-foreground md:block" />
            <GradeChip
                grade={months3?.grade ?? null}
                score={months3?.score}
                caption="After 3 months"
            />
            <ArrowRight className="mx-auto hidden size-5 text-muted-foreground md:block" />
            <GradeChip
                grade={months6?.grade ?? null}
                score={months6?.score}
                caption="After 6 months"
            />
        </div>
    );
}

export function FinancialAdvisorCard({
    analysis,
    externalCompany,
    savedAdvice,
}: Props) {
    const [advice, setAdvice] = useState<AdvisorAdvice | null>(
        savedAdvice ? extractAdvice(savedAdvice) : null,
    );
    const [generatedAt, setGeneratedAt] = useState<string | null>(
        savedAdvice?.generated_at ?? null,
    );
    const [isStale, setIsStale] = useState(savedAdvice?.is_stale ?? false);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);

    const canGenerate = analysis.years.length > 0;
    const grade = isGrowthGrade(analysis.grade) ? analysis.grade : null;
    const ratios = analysis.ratios ?? {};
    const scoreColor =
        analysis.trend === 'declining'
            ? 'var(--destructive)'
            : analysis.trend === 'improving'
              ? 'var(--chart-2)'
              : 'var(--chart-1)';

    async function generateAdvice(): Promise<void> {
        setLoading(true);
        setError(null);

        try {
            const url = externalCompany
                ? generateClientAdvice.url(externalCompany.id)
                : generateMyAdvice.url();

            const response = await fetch(url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    Accept: 'application/json',
                    'X-XSRF-TOKEN': csrfToken(),
                    'X-Requested-With': 'XMLHttpRequest',
                },
                credentials: 'same-origin',
                body: JSON.stringify(
                    externalCompany
                        ? { account_type: externalCompany.accountType }
                        : {},
                ),
            });

            const payload = (await response.json()) as Record<string, unknown> & {
                message?: string;
                errors?: Record<string, string[]>;
                generated_at?: string;
                is_stale?: boolean;
            };

            if (!response.ok) {
                throw new Error(
                    payload.message ??
                        Object.values(payload.errors ?? {})[0]?.[0] ??
                        'Advice could not be generated. Please try again.',
                );
            }

            const nextAdvice = extractAdvice(payload);

            if (nextAdvice === null) {
                throw new Error(
                    'The advisor returned an empty response. Please try again.',
                );
            }

            setAdvice(nextAdvice);
            setGeneratedAt(payload.generated_at ?? null);
            setIsStale(payload.is_stale ?? false);
        } catch (caught) {
            setError(
                caught instanceof Error
                    ? caught.message
                    : 'Advice could not be generated. Please try again.',
            );
        } finally {
            setLoading(false);
        }
    }

    return (
        <Card className="border-primary/20 bg-gradient-to-br from-primary/5 via-card to-card">
            <CardHeader className="flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between">
                <div className="space-y-1.5">
                    <CardTitle className="flex items-center gap-2 text-xl font-bold tracking-tight md:text-2xl">
                        <Sparkles className="size-6 text-primary" />
                        Financial Advisor
                    </CardTitle>
                    <CardDescription className="max-w-2xl text-sm">
                        Score breakdown, projected grades, and categorized
                        actions grounded in profitability, liquidity, solvency,
                        and efficiency.
                        {generatedAt && (
                            <span className="mt-1 block text-xs">
                                Generated{' '}
                                {new Intl.DateTimeFormat(undefined, {
                                    dateStyle: 'medium',
                                    timeStyle: 'short',
                                }).format(new Date(generatedAt))}
                            </span>
                        )}
                    </CardDescription>
                </div>
                <div className="flex flex-wrap items-center justify-end gap-2">
                    {isStale && (
                        <Badge
                            variant="outline"
                            className="text-amber-700 dark:text-amber-300"
                        >
                            Based on an earlier sync
                        </Badge>
                    )}
                    <Button
                        type="button"
                        onClick={() => void generateAdvice()}
                        disabled={loading || !canGenerate}
                    >
                        {loading ? <Spinner /> : <Sparkles />}
                        {loading
                            ? 'Generating…'
                            : advice
                              ? 'Regenerate Advice'
                              : 'Generate Advice'}
                    </Button>
                </div>
            </CardHeader>
            <CardContent className="space-y-6">
                {error && (
                    <p className="text-sm text-destructive" role="alert">
                        {error}
                    </p>
                )}

                {!canGenerate && (
                    <p className="text-sm text-muted-foreground">
                        Sync at least one year of financial history before
                        generating advice.
                    </p>
                )}

                <div className="grid gap-4 xl:grid-cols-4">
                    <div className="rounded-xl border bg-card p-4">
                        <p className="text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                            Overall financial score
                        </p>
                        <GrowthScoreRadial
                            score={analysis.growth_score}
                            color={scoreColor}
                        />
                        <p className="mt-2 text-center text-sm font-medium">
                            {grade
                                ? GRADE_LABELS[grade]
                                : 'Score not available'}
                        </p>
                    </div>

                    <div className="rounded-xl border bg-card p-4 xl:col-span-1">
                        <p className="mb-3 text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                            Score breakdown
                        </p>
                        <div className="grid gap-3 sm:grid-cols-2">
                            {RATIO_META.map((item) => (
                                <RatioBreakdownCard
                                    key={item.key}
                                    label={item.label}
                                    icon={item.icon}
                                    ratio={ratios[item.key]}
                                />
                            ))}
                        </div>
                    </div>

                    <div className="flex flex-col items-center justify-center gap-3 rounded-xl border bg-card p-4">
                        <p className="text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                            Current grade
                        </p>
                        <div
                            className={cn(
                                'flex size-20 items-center justify-center rounded-full border text-4xl font-bold',
                                grade
                                    ? GRADE_STYLES[grade]
                                    : 'border-border bg-muted text-muted-foreground',
                            )}
                        >
                            {grade ?? '—'}
                        </div>
                        <p className="text-sm font-medium">
                            {grade ? GRADE_LABELS[grade] : 'Not graded yet'}
                        </p>
                        <p className="text-center text-xs text-muted-foreground">
                            Keep improving to reach the next grade.
                        </p>
                    </div>

                    <div className="rounded-xl border bg-card p-4">
                        <p className="mb-4 text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                            Next grade projection
                        </p>
                        {advice ? (
                            <div className="flex items-center justify-between gap-3">
                                <GradeChip
                                    grade={
                                        advice.next_grade_projection.months_3
                                            .grade
                                    }
                                    score={
                                        advice.next_grade_projection.months_3
                                            .score
                                    }
                                    caption="3 months"
                                />
                                <ArrowRight className="size-4 shrink-0 text-muted-foreground" />
                                <GradeChip
                                    grade={
                                        advice.next_grade_projection.months_6
                                            .grade
                                    }
                                    score={
                                        advice.next_grade_projection.months_6
                                            .score
                                    }
                                    caption="6 months"
                                />
                            </div>
                        ) : (
                            <p className="text-sm text-muted-foreground">
                                Generate advice to project the next grade
                                milestones.
                            </p>
                        )}
                    </div>
                </div>

                {loading && advice === null && (
                    <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
                        {['critical', 'focus', 'good', 'plan'].map((key) => (
                            <div
                                key={key}
                                className="h-56 animate-pulse rounded-xl border bg-muted/60"
                            />
                        ))}
                    </div>
                )}

                {advice && (
                    <>
                        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
                            <div className="flex flex-col gap-3 rounded-xl border border-red-500/20 bg-red-500/5 p-4">
                                <div className="flex items-center gap-2">
                                    <AlertTriangle className="size-4 text-red-600 dark:text-red-400" />
                                    <h3 className="text-sm font-semibold">
                                        Critical Must-Do
                                    </h3>
                                </div>
                                <p className="text-xs text-muted-foreground">
                                    High impact areas to address first.
                                </p>
                                {advice.critical_must_do.map((item) => (
                                    <ActionItemCard
                                        key={item.title}
                                        item={item}
                                    />
                                ))}
                            </div>

                            <div className="flex flex-col gap-3 rounded-xl border border-amber-500/20 bg-amber-500/5 p-4">
                                <div className="flex items-center gap-2">
                                    <Target className="size-4 text-amber-600 dark:text-amber-400" />
                                    <h3 className="text-sm font-semibold">
                                        Areas Needing Focus
                                    </h3>
                                </div>
                                <p className="text-xs text-muted-foreground">
                                    Consistent improvement opportunities.
                                </p>
                                {advice.areas_needing_focus.map((item) => (
                                    <ActionItemCard
                                        key={item.title}
                                        item={item}
                                    />
                                ))}
                            </div>

                            <div className="flex flex-col gap-3 rounded-xl border border-emerald-500/20 bg-emerald-500/5 p-4">
                                <div className="flex items-center gap-2">
                                    <ThumbsUp className="size-4 text-emerald-600 dark:text-emerald-400" />
                                    <h3 className="text-sm font-semibold">
                                        Good to Have
                                    </h3>
                                </div>
                                <p className="text-xs text-muted-foreground">
                                    Value-adding improvements.
                                </p>
                                {advice.good_to_have.map((item) => (
                                    <ActionItemCard
                                        key={item.title}
                                        item={item}
                                    />
                                ))}
                            </div>

                            <div className="flex flex-col gap-3 rounded-xl border border-primary/20 bg-primary/5 p-4">
                                <div className="flex items-center gap-2">
                                    <CalendarDays className="size-4 text-primary" />
                                    <h3 className="text-sm font-semibold">
                                        3-Month Action Plan
                                    </h3>
                                </div>
                                <p className="text-xs text-muted-foreground">
                                    A sequenced roadmap for the next quarter.
                                </p>
                                {(
                                    [
                                        ['Month 1', advice.three_month_plan.month_1],
                                        ['Month 2', advice.three_month_plan.month_2],
                                        ['Month 3', advice.three_month_plan.month_3],
                                    ] as const
                                ).map(([label, items]) => (
                                    <div
                                        key={label}
                                        className="rounded-xl border bg-card/80 p-3"
                                    >
                                        <p className="text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                                            {label}
                                        </p>
                                        <ul className="mt-2 space-y-2 text-sm">
                                            {items.map((item) => (
                                                <li
                                                    key={item}
                                                    className="flex gap-2"
                                                >
                                                    <span className="mt-2 size-1.5 shrink-0 rounded-full bg-primary" />
                                                    <span>{item}</span>
                                                </li>
                                            ))}
                                        </ul>
                                    </div>
                                ))}
                            </div>
                        </div>

                        <div className="space-y-2">
                            <p className="text-xs font-semibold tracking-wide text-muted-foreground uppercase">
                                Grade progression projection
                            </p>
                            <GradeProgression
                                currentGrade={grade}
                                currentScore={analysis.growth_score}
                                months3={advice.next_grade_projection.months_3}
                                months6={advice.next_grade_projection.months_6}
                            />
                        </div>

                        <div className="flex flex-col gap-3 rounded-xl border border-violet-500/20 bg-violet-500/10 p-4 sm:flex-row sm:items-center sm:justify-between">
                            <div className="flex items-start gap-3">
                                <GraduationCap className="mt-0.5 size-5 text-violet-700 dark:text-violet-300" />
                                <div>
                                    <p className="text-xs font-semibold tracking-wide text-violet-800 uppercase dark:text-violet-300">
                                        Upskill recommendation
                                    </p>
                                    <p className="mt-1 text-sm font-semibold">
                                        {advice.upskill_recommendation.title}
                                    </p>
                                    <p className="mt-1 text-sm text-muted-foreground">
                                        {
                                            advice.upskill_recommendation
                                                .description
                                        }
                                    </p>
                                </div>
                            </div>
                            <Button variant="outline" type="button" disabled>
                                Explore learning resources
                            </Button>
                        </div>
                    </>
                )}
            </CardContent>
        </Card>
    );
}
