"use client";

import Link from "next/link";
import { useEffect, useMemo, useState } from "react";

import { getCategoryLabel } from "@/lib/categories";
import { getCurrentMonthKey, getMonthLabel } from "@/lib/date";
import { formatCurrencyFromCents, formatPercent } from "@/lib/money";

type DashboardSnapshot = {
  month: string;
  insight: {
    summary: string;
    recommendations: string;
    generatedAt: string;
  } | null;
  totals: {
    expensesCents: number;
    paychecksCents: number;
    netCashFlowCents: number;
    averageDailySpendCents: number;
    paycheckCoverageRatio: number | null;
  };
  comparisons: {
    highestCategory: { category: string; amountCents: number } | null;
    largestExpense: { title: string; amountCents: number; date: string; category: string } | null;
  };
  categoryBreakdown: Array<{ category: string; amountCents: number }>;
  recentExpenses: Array<{ id: string; title: string; amountCents: number; date: string; category: string }>;
  chart: Array<{ date: string; expensesCents: number; paychecksCents: number }>;
};

type OllamaStatus = {
  available: boolean;
  configuredModel: string;
  configuredUrl: string;
  installedModels: string[];
  modelReady: boolean;
  message: string;
};

export function HomeDashboard() {
  const [selectedMonth, setSelectedMonth] = useState(getCurrentMonthKey());
  const [snapshot, setSnapshot] = useState<DashboardSnapshot | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [insightBusy, setInsightBusy] = useState(false);
  const [ollamaBusy, setOllamaBusy] = useState(false);
  const [ollamaStatus, setOllamaStatus] = useState<OllamaStatus | null>(null);

  async function loadDashboard(month: string) {
    const response = await fetch(`/dashboard?month=${month}`, { cache: "no-store" });
    const payload = (await response.json()) as DashboardSnapshot & { error?: string };

    if (!response.ok) {
      setError(payload.error ?? "Could not load the dashboard.");
      return;
    }

    setError(null);
    setSnapshot(payload);
  }

  async function loadOllamaStatus() {
    const response = await fetch("/ollama/status", { cache: "no-store" });
    const payload = (await response.json()) as OllamaStatus;
    setOllamaStatus(payload);
  }

  useEffect(() => {
    const timeoutId = window.setTimeout(() => {
      void loadDashboard(selectedMonth);
    }, 0);

    return () => window.clearTimeout(timeoutId);
  }, [selectedMonth]);

  useEffect(() => {
    const timeoutId = window.setTimeout(async () => {
      await loadOllamaStatus();
    }, 0);

    return () => window.clearTimeout(timeoutId);
  }, []);

  const topCategoryLabel = useMemo(() => {
    if (!snapshot?.comparisons.highestCategory) {
      return "No category leader yet";
    }

    return `${getCategoryLabel(snapshot.comparisons.highestCategory.category as never)} · ${formatCurrencyFromCents(snapshot.comparisons.highestCategory.amountCents)}`;
  }, [snapshot]);

  const coverageLabel =
    snapshot?.totals.paycheckCoverageRatio == null
      ? "No spend yet"
      : formatPercent(snapshot.totals.paycheckCoverageRatio);

  async function handleGenerateInsights() {
    setInsightBusy(true);

    const response = await fetch(`/insights/generate?month=${selectedMonth}`, { method: "POST" });
    const payload = (await response.json().catch(() => null)) as { error?: string } | null;

    setInsightBusy(false);

    if (!response.ok) {
      setError(payload?.error ?? "Could not generate insights.");
      return;
    }

    await loadDashboard(selectedMonth);
  }

  async function handlePullModel() {
    setOllamaBusy(true);

    const response = await fetch("/ollama/pull", { method: "POST" });
    const payload = (await response.json().catch(() => null)) as { error?: string; message?: string } | null;

    setOllamaBusy(false);

    if (!response.ok) {
      setError(payload?.error ?? "Could not pull the configured model.");
      return;
    }

    setError(payload?.message ?? null);
    await loadOllamaStatus();
  }

  return (
    <div className="space-y-10">
      <section className="grid gap-6 rounded-[2rem] border border-stone-200 bg-[radial-gradient(circle_at_top_left,_rgba(251,191,36,0.26),_transparent_32%),linear-gradient(135deg,#fffaf2,#f3efe7)] p-8 shadow-[0_28px_70px_rgba(120,90,50,0.10)] lg:grid-cols-[1.2fr_0.8fr]">
        <div className="space-y-5">
          <p className="text-sm font-semibold uppercase tracking-[0.28em] text-amber-700">Monthly Expense Tracker</p>
          <h1 className="max-w-3xl text-5xl font-semibold leading-tight text-stone-950">
            A calm local-first home for everyday spending.
          </h1>
          <p className="max-w-2xl text-lg leading-8 text-stone-600">
            Track expenses and paycheck timing together so the month-to-date picture stays honest.
          </p>
          <div className="flex flex-wrap gap-3">
            <Link href="/add-expense" className="rounded-full bg-stone-950 px-5 py-3 text-sm font-semibold text-white transition hover:bg-stone-800">
              Add an expense
            </Link>
            <Link href="/income" className="rounded-full border border-stone-300 bg-white px-5 py-3 text-sm font-semibold text-stone-800 transition hover:border-stone-900">
              Track paychecks
            </Link>
          </div>
        </div>

        <div className="rounded-[1.75rem] border border-white/80 bg-white/90 p-6">
          <div className="flex items-center justify-between gap-3">
            <div>
              <p className="text-sm font-semibold uppercase tracking-[0.24em] text-stone-500">Month to date</p>
              <h2 className="mt-2 text-3xl font-semibold text-stone-950">
                {snapshot ? getMonthLabel(snapshot.month) : getMonthLabel(selectedMonth)}
              </h2>
            </div>
            <input
              type="month"
              value={selectedMonth}
              onChange={(event) => setSelectedMonth(event.target.value)}
              className="rounded-2xl border border-stone-300 bg-stone-50 px-3 py-2 text-sm font-medium text-stone-700 outline-none transition focus:border-stone-900"
            />
          </div>

          <div className="mt-6 grid gap-4 sm:grid-cols-2">
            <article className="rounded-3xl bg-stone-950 px-4 py-5 text-white">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-300">Total spent</p>
              <p className="mt-3 text-3xl font-semibold">{formatCurrencyFromCents(snapshot?.totals.expensesCents ?? 0)}</p>
            </article>
            <article className="rounded-3xl bg-emerald-50 px-4 py-5 text-stone-950">
              <p className="text-xs uppercase tracking-[0.2em] text-emerald-700">Paychecks tracked</p>
              <p className="mt-3 text-3xl font-semibold">{formatCurrencyFromCents(snapshot?.totals.paychecksCents ?? 0)}</p>
            </article>
            <article className="rounded-3xl bg-amber-50 px-4 py-5 text-stone-950">
              <p className="text-xs uppercase tracking-[0.2em] text-amber-700">Net cash flow</p>
              <p className="mt-3 text-3xl font-semibold">{formatCurrencyFromCents(snapshot?.totals.netCashFlowCents ?? 0)}</p>
            </article>
            <article className="rounded-3xl bg-stone-100 px-4 py-5 text-stone-950">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-600">Average daily spend</p>
              <p className="mt-3 text-3xl font-semibold">{formatCurrencyFromCents(snapshot?.totals.averageDailySpendCents ?? 0)}</p>
            </article>
          </div>
          {error ? <p className="mt-4 text-sm text-rose-700">{error}</p> : null}
        </div>
      </section>

      <section className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-[0_24px_60px_rgba(120,90,50,0.08)]">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div>
            <p className="text-sm font-semibold uppercase tracking-[0.24em] text-stone-500">Private monthly insight</p>
            <h2 className="mt-2 text-3xl font-semibold text-stone-950">Offline guidance for this month</h2>
          </div>
          <button
            type="button"
            onClick={() => void handleGenerateInsights()}
            disabled={insightBusy}
            className="rounded-full bg-stone-950 px-5 py-3 text-sm font-semibold text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:bg-stone-400"
          >
            {insightBusy ? "Generating..." : "Generate insights"}
          </button>
        </div>

        <div className="mt-6 rounded-3xl border border-stone-200 bg-stone-50 px-5 py-4">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <p className="text-xs uppercase tracking-[0.2em] text-stone-500">Ollama runtime</p>
              <p className="mt-2 text-sm font-medium text-stone-700">
                {ollamaStatus?.message ?? "Checking local runtime status..."}
              </p>
            </div>
            <div className="rounded-full px-3 py-2 text-xs font-semibold uppercase tracking-[0.2em] text-white "
              data-ready={ollamaStatus?.available && ollamaStatus?.modelReady ? "true" : "false"}
            >
              <span
                className={
                  ollamaStatus?.available && ollamaStatus?.modelReady
                    ? "rounded-full bg-emerald-600 px-3 py-2"
                    : "rounded-full bg-stone-500 px-3 py-2"
                }
              >
                {ollamaStatus?.available && ollamaStatus?.modelReady ? "Ready" : "Needs attention"}
              </span>
            </div>
          </div>
          <div className="mt-4 grid gap-3 text-sm text-stone-600 sm:grid-cols-2">
            <p>
              Model: <span className="font-semibold text-stone-900">{ollamaStatus?.configuredModel ?? "-"}</span>
            </p>
            <p>
              URL: <span className="font-semibold text-stone-900">{ollamaStatus?.configuredUrl ?? "-"}</span>
            </p>
          </div>
          <div className="mt-4 flex flex-wrap gap-3">
            <button
              type="button"
              onClick={() => void loadOllamaStatus()}
              className="rounded-full border border-stone-300 px-4 py-2 text-xs font-semibold uppercase tracking-[0.2em] text-stone-700 transition hover:border-stone-900"
            >
              Refresh status
            </button>
            {ollamaStatus?.available && !ollamaStatus.modelReady ? (
              <button
                type="button"
                onClick={() => void handlePullModel()}
                disabled={ollamaBusy}
                className="rounded-full bg-stone-950 px-4 py-2 text-xs font-semibold uppercase tracking-[0.2em] text-white transition hover:bg-stone-800 disabled:cursor-not-allowed disabled:bg-stone-400"
              >
                {ollamaBusy ? "Pulling model..." : "Pull configured model"}
              </button>
            ) : null}
            <a
              href="/backup/database"
              className="rounded-full border border-stone-300 px-4 py-2 text-xs font-semibold uppercase tracking-[0.2em] text-stone-700 transition hover:border-stone-900"
            >
              Download backup
            </a>
          </div>
        </div>

        {snapshot?.insight ? (
          <div className="mt-6 grid gap-4 lg:grid-cols-[1.2fr_0.8fr]">
            <article className="rounded-3xl border border-stone-200 bg-[#fffcf7] px-5 py-5">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-500">Summary</p>
              <p className="mt-3 text-base leading-7 text-stone-700">{snapshot.insight.summary}</p>
            </article>
            <article className="rounded-3xl border border-stone-200 bg-[#f8faf7] px-5 py-5">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-500">Next month guidance</p>
              <p className="mt-3 text-base leading-7 text-stone-700">{snapshot.insight.recommendations}</p>
              <p className="mt-4 text-xs uppercase tracking-[0.2em] text-stone-400">
                Generated {new Date(snapshot.insight.generatedAt).toLocaleString()}
              </p>
            </article>
          </div>
        ) : (
          <div className="mt-6 rounded-3xl border border-dashed border-stone-300 px-5 py-8 text-stone-600">
            No saved insight for this month yet. Generate one to get a private offline summary.
          </div>
        )}
      </section>

      <section className="grid gap-6 lg:grid-cols-[1.1fr_0.9fr]">
        <div className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-[0_24px_60px_rgba(120,90,50,0.08)]">
          <div className="flex items-center justify-between gap-4">
            <div>
              <p className="text-sm font-semibold uppercase tracking-[0.24em] text-stone-500">Comparisons</p>
              <h2 className="mt-2 text-3xl font-semibold text-stone-950">What stands out this month</h2>
            </div>
            <Link href="/add-expense" className="text-sm font-semibold text-amber-800 transition hover:text-stone-950">
              Manage expenses
            </Link>
          </div>

          <div className="mt-6 grid gap-4 sm:grid-cols-2">
            <article className="rounded-3xl border border-stone-200 bg-[#fffcf7] px-4 py-5">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-500">Highest category</p>
              <p className="mt-3 text-lg font-semibold text-stone-950">{topCategoryLabel}</p>
            </article>
            <article className="rounded-3xl border border-stone-200 bg-[#f8faf7] px-4 py-5">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-500">Paycheck coverage</p>
              <p className="mt-3 text-lg font-semibold text-stone-950">{coverageLabel}</p>
            </article>
            <article className="rounded-3xl border border-stone-200 bg-white px-4 py-5 sm:col-span-2">
              <p className="text-xs uppercase tracking-[0.2em] text-stone-500">Largest expense</p>
              {snapshot?.comparisons.largestExpense ? (
                <div className="mt-3 flex flex-wrap items-center justify-between gap-3">
                  <div>
                    <p className="text-lg font-semibold text-stone-950">{snapshot.comparisons.largestExpense.title}</p>
                    <p className="text-sm text-stone-600">
                      {snapshot.comparisons.largestExpense.date} · {getCategoryLabel(snapshot.comparisons.largestExpense.category as never)}
                    </p>
                  </div>
                  <p className="text-xl font-semibold text-stone-950">
                    {formatCurrencyFromCents(snapshot.comparisons.largestExpense.amountCents)}
                  </p>
                </div>
              ) : (
                <p className="mt-3 text-sm text-stone-600">No expense data for this month yet.</p>
              )}
            </article>
          </div>
        </div>

        <div className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-[0_24px_60px_rgba(120,90,50,0.08)]">
          <p className="text-sm font-semibold uppercase tracking-[0.24em] text-stone-500">Category breakdown</p>
          <h2 className="mt-2 text-3xl font-semibold text-stone-950">Where the month is going</h2>
          <div className="mt-6 space-y-3">
            {snapshot?.categoryBreakdown.length ? (
              snapshot.categoryBreakdown.map((item) => (
                <article key={item.category} className="rounded-3xl border border-stone-200 bg-stone-50 px-4 py-4">
                  <div className="flex items-center justify-between gap-4">
                    <p className="font-semibold text-stone-950">{getCategoryLabel(item.category as never)}</p>
                    <p className="font-semibold text-stone-950">{formatCurrencyFromCents(item.amountCents)}</p>
                  </div>
                </article>
              ))
            ) : (
              <div className="rounded-3xl border border-dashed border-stone-300 px-4 py-8 text-sm text-stone-600">
                No category totals yet for this month.
              </div>
            )}
          </div>
        </div>
      </section>

      <section className="rounded-[2rem] border border-stone-200 bg-white p-8 shadow-[0_24px_60px_rgba(120,90,50,0.08)]">
        <div className="flex items-center justify-between gap-4">
          <div>
            <p className="text-sm font-semibold uppercase tracking-[0.24em] text-stone-500">Recent expense pulse</p>
            <h2 className="mt-2 text-3xl font-semibold text-stone-950">Latest entries</h2>
          </div>
          <Link href="/income" className="text-sm font-semibold text-emerald-800 transition hover:text-stone-950">
            Manage paychecks
          </Link>
        </div>

        <div className="mt-6 grid gap-3 md:grid-cols-2">
          {snapshot?.recentExpenses.length ? (
            snapshot.recentExpenses.map((expense) => (
              <article key={expense.id} className="flex flex-wrap items-center justify-between gap-3 rounded-3xl border border-stone-200 bg-[#fffcf7] px-4 py-4">
                <div>
                  <p className="font-semibold text-stone-950">{expense.title}</p>
                  <p className="mt-1 text-sm text-stone-600">
                    {expense.date} · {getCategoryLabel(expense.category as never)}
                  </p>
                </div>
                <p className="font-semibold text-stone-950">{formatCurrencyFromCents(expense.amountCents)}</p>
              </article>
            ))
          ) : (
            <div className="rounded-3xl border border-dashed border-stone-300 px-4 py-10 text-center text-stone-600 md:col-span-2">
              No expenses recorded yet. Start with one quick entry.
            </div>
          )}
        </div>
      </section>
    </div>
  );
}
