"use client";

import { useState, useRef, useEffect, useCallback } from "react";
import {
  Bot,
  Send,
  Trash2,
  Sparkles,
  TrendingUp,
  TrendingDown,
  Wallet,
  RefreshCw,
  User,
  AlertCircle,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
import { getCurrency } from "@/lib/utils/currency";
import { useBankAccounts } from "@/hooks/use-bank-accounts";
import { useLoans } from "@/hooks/use-loans";
import { useRecurring } from "@/hooks/use-recurring";
import { useTransactions } from "@/hooks/use-transactions";

// ── Types ──────────────────────────────────────────────────────────────────

type Role = "user" | "assistant";

interface Message {
  role: Role;
  content: string;
}

// ── Helpers ────────────────────────────────────────────────────────────────

function fmt(cents: number) {
  return new Intl.NumberFormat("en-US", {
    style: "currency",
    currency: getCurrency(),
    maximumFractionDigits: 0,
  }).format(cents / 100);
}

function escHtml(str: string) {
  return str
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

function inlineFmt(raw: string): string {
  const safe = escHtml(raw);
  return safe
    .replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
    .replace(
      /`(.+?)`/g,
      '<code class="bg-slate-700 px-1 py-0.5 rounded text-xs font-mono text-emerald-300">$1</code>'
    );
}

function MarkdownMessage({ text }: { text: string }) {
  const lines = text.split("\n");
  const elements: React.ReactNode[] = [];
  let listItems: string[] = [];
  let codeBlock: string[] = [];
  let inCode = false;

  function flushList() {
    if (!listItems.length) return;
    elements.push(
      <ul key={`list-${elements.length}`} className="my-1 space-y-0.5">
        {listItems.map((item, i) => (
          <li key={i} className="flex gap-2 text-sm leading-relaxed">
            <span className="text-emerald-400 mt-0.5 shrink-0 text-xs">•</span>
            <span
              dangerouslySetInnerHTML={{ __html: inlineFmt(item) }}
            />
          </li>
        ))}
      </ul>
    );
    listItems = [];
  }

  function flushCode() {
    if (!codeBlock.length) return;
    elements.push(
      <pre
        key={`code-${elements.length}`}
        className="my-2 bg-slate-800 rounded-lg p-3 text-xs font-mono text-slate-300 overflow-x-auto"
      >
        {codeBlock.join("\n")}
      </pre>
    );
    codeBlock = [];
  }

  for (let idx = 0; idx < lines.length; idx++) {
    const line = lines[idx];

    if (line.startsWith("```")) {
      if (inCode) {
        flushCode();
        inCode = false;
      } else {
        flushList();
        inCode = true;
      }
      continue;
    }

    if (inCode) {
      codeBlock.push(line);
      continue;
    }

    if (line.startsWith("### ")) {
      flushList();
      elements.push(
        <h3
          key={`h3-${idx}`}
          className="text-sm font-semibold text-slate-100 mt-3 mb-1"
          dangerouslySetInnerHTML={{ __html: inlineFmt(line.slice(4)) }}
        />
      );
    } else if (line.startsWith("## ")) {
      flushList();
      elements.push(
        <h2
          key={`h2-${idx}`}
          className="text-base font-bold text-slate-100 mt-4 mb-1"
          dangerouslySetInnerHTML={{ __html: inlineFmt(line.slice(3)) }}
        />
      );
    } else if (line.startsWith("# ")) {
      flushList();
      elements.push(
        <h1
          key={`h1-${idx}`}
          className="text-lg font-bold text-emerald-400 mt-4 mb-2"
          dangerouslySetInnerHTML={{ __html: inlineFmt(line.slice(2)) }}
        />
      );
    } else if (/^[-*] /.test(line)) {
      listItems.push(line.slice(2));
    } else if (line.trim() === "") {
      flushList();
    } else {
      flushList();
      elements.push(
        <p
          key={`p-${idx}`}
          className="text-sm leading-relaxed"
          dangerouslySetInnerHTML={{ __html: inlineFmt(line) }}
        />
      );
    }
  }

  flushList();
  flushCode();

  return <div className="space-y-1">{elements}</div>;
}

// ── Quick prompts ──────────────────────────────────────────────────────────

const QUICK_PROMPTS = [
  { label: "How is my cash flow?", icon: TrendingUp },
  { label: "Where am I overspending?", icon: TrendingDown },
  { label: "How can I save more?", icon: Sparkles },
  { label: "Debt repayment strategy", icon: Wallet },
  { label: "Review my subscriptions", icon: RefreshCw },
  { label: "Set a savings goal", icon: TrendingUp },
  { label: "Analyse my finances", icon: Bot },
];

// ── Main Page ──────────────────────────────────────────────────────────────

export default function AdvisorPage() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState("");
  const [streaming, setStreaming] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const messagesEndRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLTextAreaElement>(null);
  const abortRef = useRef<AbortController | null>(null);

  // Financial data for snapshot cards
  const { data: accounts } = useBankAccounts();
  const { data: loansData } = useLoans();
  const { data: recurringData } = useRecurring();
  const { data: txnData } = useTransactions({
    from: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)
      .toISOString()
      .split("T")[0],
    to: new Date().toISOString().split("T")[0],
  });

  // Derived stats
  const totalBalance = (accounts ?? []).reduce(
    (s, a) => s + a.balanceCents,
    0
  );
  const totalLoans = (loansData ?? []).reduce(
    (s: number, l: { outstandingCents: number }) => s + l.outstandingCents,
    0
  );

  const freqMultipliers: Record<string, number> = {
    DAILY: 30,
    WEEKLY: 4.33,
    BIWEEKLY: 2.17,
    MONTHLY: 1,
    QUARTERLY: 1 / 3,
    YEARLY: 1 / 12,
  };
  const monthlyRecurring = (recurringData ?? [])
    .filter((r: { type: string; isActive: boolean }) => r.type === "EXPENSE" && r.isActive)
    .reduce(
      (s: number, r: { amountCents: number; frequency: string }) =>
        s + Math.round(r.amountCents * (freqMultipliers[r.frequency] ?? 1)),
      0
    );

  const income30d = (txnData?.transactions ?? [])
    .filter((t) => t.type === "INCOME")
    .reduce((s, t) => s + t.amountCents, 0);
  const expenses30d = (txnData?.transactions ?? [])
    .filter((t) => t.type === "EXPENSE")
    .reduce((s, t) => s + t.amountCents, 0);
  const savings30d = income30d - expenses30d;

  // Auto-scroll on new content
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  const sendMessage = useCallback(
    async (content: string) => {
      if (!content.trim() || streaming) return;
      setError(null);

      const userMessage: Message = { role: "user", content: content.trim() };
      const newHistory = [...messages, userMessage];
      setMessages(newHistory);
      setInput("");
      setStreaming(true);

      const ctrl = new AbortController();
      abortRef.current = ctrl;

      // Add empty assistant slot for streaming
      setMessages((prev) => [
        ...prev,
        { role: "assistant", content: "" },
      ]);

      try {
        const res = await fetch("/api/ai/chat", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            messages: newHistory.map((m) => ({
              role: m.role,
              content: m.content,
            })),
          }),
          signal: ctrl.signal,
        });

        if (!res.ok) {
          const text = await res.text();
          throw new Error(text || `HTTP ${res.status}`);
        }

        const reader = res.body!.getReader();
        const decoder = new TextDecoder();

        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          const chunk = decoder.decode(value, { stream: true });
          setMessages((prev) => {
            const last = prev[prev.length - 1];
            if (last?.role === "assistant") {
              return [
                ...prev.slice(0, -1),
                { ...last, content: last.content + chunk },
              ];
            }
            return prev;
          });
        }
      } catch (err) {
        if ((err as Error).name === "AbortError") return;
        const msg =
          err instanceof Error ? err.message : "Something went wrong";
        setError(msg);
        // Remove the empty assistant slot on error
        setMessages((prev) =>
          prev[prev.length - 1]?.content === ""
            ? prev.slice(0, -1)
            : prev
        );
      } finally {
        setStreaming(false);
        abortRef.current = null;
        inputRef.current?.focus();
      }
    },
    [messages, streaming]
  );

  function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      sendMessage(input);
    }
  }

  function clearChat() {
    abortRef.current?.abort();
    setMessages([]);
    setError(null);
    setStreaming(false);
  }

  // ── Snapshot cards ─────────────────────────────────────────────────────
  const snapshotCards = [
    {
      label: "Total Balance",
      value: fmt(totalBalance),
      sub: `${(accounts ?? []).length} account${(accounts ?? []).length !== 1 ? "s" : ""}`,
      icon: Wallet,
      color: "text-emerald-400",
      bg: "bg-emerald-500/10",
    },
    {
      label: "30-Day Savings",
      value: fmt(Math.abs(savings30d)),
      sub: savings30d >= 0 ? "surplus" : "deficit",
      icon: savings30d >= 0 ? TrendingUp : TrendingDown,
      color: savings30d >= 0 ? "text-emerald-400" : "text-red-400",
      bg: savings30d >= 0 ? "bg-emerald-500/10" : "bg-red-500/10",
    },
    {
      label: "Monthly Fixed",
      value: fmt(monthlyRecurring),
      sub: `${(recurringData ?? []).filter((r: { isActive: boolean }) => r.isActive).length} subscriptions`,
      icon: RefreshCw,
      color: "text-amber-400",
      bg: "bg-amber-500/10",
    },
    {
      label: "Loan Debt",
      value: fmt(totalLoans),
      sub: `${(loansData ?? []).length} active loan${(loansData ?? []).length !== 1 ? "s" : ""}`,
      icon: TrendingDown,
      color: "text-red-400",
      bg: "bg-red-500/10",
    },
  ];

  return (
    <div className="h-full flex flex-col gap-4">
      {/* Header */}
      <div className="shrink-0 flex items-center justify-between">
        <div className="flex items-center gap-3">
          <div className="w-10 h-10 rounded-xl bg-emerald-500/15 border border-emerald-500/30 flex items-center justify-center">
            <Bot className="h-5 w-5 text-emerald-400" />
          </div>
          <div>
            <h1 className="text-lg font-bold text-slate-100">
              AI Financial Adviser
            </h1>
            <p className="text-xs text-slate-500">
              Powered by Claude · Analyses your real financial data
            </p>
          </div>
        </div>
        {messages.length > 0 && (
          <Button
            variant="ghost"
            size="sm"
            onClick={clearChat}
            className="text-slate-500 hover:text-slate-300"
          >
            <Trash2 className="h-4 w-4 mr-1.5" />
            Clear
          </Button>
        )}
      </div>

      {/* Snapshot cards */}
      <div className="shrink-0 grid grid-cols-2 md:grid-cols-4 gap-3">
        {snapshotCards.map((card) => (
          <div
            key={card.label}
            className="rounded-xl border border-slate-700/50 bg-slate-900/60 p-3 flex items-start gap-3"
          >
            <div
              className={cn(
                "w-8 h-8 rounded-lg flex items-center justify-center shrink-0",
                card.bg
              )}
            >
              <card.icon className={cn("h-4 w-4", card.color)} />
            </div>
            <div className="min-w-0">
              <p className="text-xs text-slate-500 truncate">{card.label}</p>
              <p className={cn("text-sm font-bold", card.color)}>
                {card.value}
              </p>
              <p className="text-[10px] text-slate-600">{card.sub}</p>
            </div>
          </div>
        ))}
      </div>

      {/* Chat container */}
      <div className="flex-1 min-h-0 flex flex-col rounded-xl border border-slate-700/50 bg-slate-900/40 overflow-hidden">
        {/* Messages */}
        <div className="flex-1 overflow-y-auto p-4 space-y-5">
          {messages.length === 0 && (
            <div className="flex flex-col items-center justify-center h-full gap-6 py-8">
              <div className="w-16 h-16 rounded-2xl bg-emerald-500/10 border border-emerald-500/20 flex items-center justify-center">
                <Sparkles className="h-8 w-8 text-emerald-400" />
              </div>
              <div className="text-center max-w-sm">
                <h2 className="text-base font-semibold text-slate-200 mb-1">
                  Your personal financial adviser
                </h2>
                <p className="text-sm text-slate-500">
                  Ask me anything about your money. I have access to your
                  accounts, transactions, budgets, loans, and subscriptions.
                </p>
              </div>
              <div className="flex flex-wrap gap-2 justify-center max-w-md">
                {QUICK_PROMPTS.map((p) => (
                  <button
                    key={p.label}
                    onClick={() => sendMessage(p.label)}
                    className="flex items-center gap-1.5 px-3 py-1.5 rounded-full bg-slate-800 border border-slate-700 text-xs text-slate-300 hover:bg-slate-700 hover:border-emerald-500/50 hover:text-emerald-300 transition-all"
                  >
                    <p.icon className="h-3 w-3" />
                    {p.label}
                  </button>
                ))}
              </div>
            </div>
          )}

          {messages.map((msg, idx) => (
            <div
              key={idx}
              className={cn(
                "flex gap-3",
                msg.role === "user" ? "justify-end" : "justify-start"
              )}
            >
              {msg.role === "assistant" && (
                <div className="w-7 h-7 rounded-lg bg-emerald-500/15 border border-emerald-500/30 flex items-center justify-center shrink-0 mt-0.5">
                  <Bot className="h-3.5 w-3.5 text-emerald-400" />
                </div>
              )}

              <div
                className={cn(
                  "max-w-[85%] rounded-2xl px-4 py-3",
                  msg.role === "user"
                    ? "bg-emerald-600/20 border border-emerald-500/30 text-slate-100 rounded-tr-sm"
                    : "bg-slate-800/80 border border-slate-700/50 text-slate-200 rounded-tl-sm"
                )}
              >
                {msg.role === "user" ? (
                  <p className="text-sm leading-relaxed whitespace-pre-wrap">
                    {msg.content}
                  </p>
                ) : msg.content === "" && streaming ? (
                  <div className="flex items-center gap-1.5 py-1">
                    <div className="flex gap-1">
                      <span
                        className="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-bounce"
                        style={{ animationDelay: "0ms" }}
                      />
                      <span
                        className="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-bounce"
                        style={{ animationDelay: "150ms" }}
                      />
                      <span
                        className="w-1.5 h-1.5 rounded-full bg-emerald-400 animate-bounce"
                        style={{ animationDelay: "300ms" }}
                      />
                    </div>
                    <span className="text-xs text-slate-500">Thinking…</span>
                  </div>
                ) : (
                  <MarkdownMessage text={msg.content} />
                )}
              </div>

              {msg.role === "user" && (
                <div className="w-7 h-7 rounded-lg bg-slate-700/50 flex items-center justify-center shrink-0 mt-0.5">
                  <User className="h-3.5 w-3.5 text-slate-400" />
                </div>
              )}
            </div>
          ))}

          {/* Error */}
          {error && (
            <div className="flex gap-2 items-start p-3 rounded-xl bg-red-500/10 border border-red-500/30 text-red-400">
              <AlertCircle className="h-4 w-4 shrink-0 mt-0.5" />
              <div>
                <p className="text-sm font-medium">Error</p>
                <p className="text-xs text-red-400/80 mt-0.5">{error}</p>
              </div>
            </div>
          )}

          <div ref={messagesEndRef} />
        </div>

        {/* Quick prompts when conversation started (compact row) */}
        {messages.length > 0 && !streaming && (
          <div className="shrink-0 px-4 pb-2 flex flex-wrap gap-1.5 overflow-x-auto">
            {QUICK_PROMPTS.slice(0, 4).map((p) => (
              <button
                key={p.label}
                onClick={() => sendMessage(p.label)}
                className="flex items-center gap-1 px-2.5 py-1 rounded-full bg-slate-800 border border-slate-700 text-[11px] text-slate-400 hover:bg-slate-700 hover:text-emerald-300 hover:border-emerald-500/40 transition-all whitespace-nowrap shrink-0"
              >
                <p.icon className="h-2.5 w-2.5" />
                {p.label}
              </button>
            ))}
          </div>
        )}

        {/* Input area */}
        <div className="shrink-0 border-t border-slate-700/50 p-3">
          <div className="flex gap-2 items-end">
            <textarea
              ref={inputRef}
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={handleKeyDown}
              disabled={streaming}
              placeholder="Ask about your finances… (Enter to send, Shift+Enter for newline)"
              rows={1}
              className={cn(
                "flex-1 resize-none rounded-xl bg-slate-800 border border-slate-700 text-slate-100 placeholder-slate-500",
                "px-4 py-3 text-sm outline-none focus:border-emerald-500/60 focus:ring-1 focus:ring-emerald-500/30",
                "transition-all min-h-[44px] max-h-32 overflow-y-auto",
                "disabled:opacity-50 disabled:cursor-not-allowed"
              )}
              style={{ height: "auto" }}
              onInput={(e) => {
                const el = e.currentTarget;
                el.style.height = "auto";
                el.style.height = Math.min(el.scrollHeight, 128) + "px";
              }}
            />
            <Button
              onClick={() => sendMessage(input)}
              disabled={streaming || !input.trim()}
              className="h-11 w-11 p-0 rounded-xl bg-emerald-600 hover:bg-emerald-500 disabled:opacity-40 shrink-0"
            >
              {streaming ? (
                <RefreshCw className="h-4 w-4 animate-spin" />
              ) : (
                <Send className="h-4 w-4" />
              )}
            </Button>
          </div>
          <p className="text-[10px] text-slate-600 mt-1.5 text-center">
            AI responses are based on your FinPulse data and for guidance only
          </p>
        </div>
      </div>
    </div>
  );
}
