"use client";

import { useEffect, useMemo, useState } from "react";
import demoTransactions from "@/data/demo-transactions.json";
import demoConfig from "@/data/demo-config.json";
import { categorySpend, categoryTemplates, formatEUR, lifestyleSummary, monthSpend, transactionBudgetAmount } from "@/lib/finance";
import { demoMode, hasSupabase, supabaseBrowser } from "@/lib/supabase";
import type { Budget, Profile, Transaction } from "@/lib/types";
import { Icon } from "./icons";

type Tab = "home" | "transactions" | "budget" | "stats" | "more";
type SourceMode = "loading" | "demo" | "supabase" | "setup";

const demoSeed = demoTransactions as Transaction[];
const defaultProfile: Profile = { firstName: "", monthlyIncome: 0, salaryDay: null, savingsTarget: 0, safetyReserve: 0 };

function statusFor(pct: number) {
  if (pct > 100) return "danger";
  if (pct >= 80) return "warning";
  return "success";
}

function categoryIcon(category: string) {
  const map: Record<string,string> = {
    "Wohnen":"⌂","Energie":"ϟ","Versicherungen":"◇","Telekom":"▣","Internet":"◉",
    "Lebensmittel & Haushalt":"♜","Gastronomie & Ausgehen":"●","Trafik":"✤","Mobilität":"↗",
    "Abos":"∞","Shopping":"▰","Freizeit":"✦","Sparen & Investieren":"$","Puffer":"+"
  };
  return map[category] ?? "•";
}

function budgetGroup(value: unknown): Budget["group"] {
  return value === "Lifestyle" || value === "Sparen" ? value : "Fixkosten";
}

export default function LeftyApp() {
  const [tab, setTab] = useState<Tab>("home");
  const [activeMonth, setActiveMonth] = useState(() => monthKey(new Date()));
  const [transactions, setTransactions] = useState<Transaction[]>([]);
  const [activeBudgets, setActiveBudgets] = useState<Budget[]>(categoryTemplates);
  const [profile, setProfile] = useState<Profile>(defaultProfile);
  const [search, setSearch] = useState("");
  const [budgetFilter, setBudgetFilter] = useState("Alle");
  const [showAdd, setShowAdd] = useState(false);
  const [sourceMode, setSourceMode] = useState<SourceMode>("loading");
  const [syncNote, setSyncNote] = useState("Lefty wird geladen …");
  const [errorMessage, setErrorMessage] = useState("");

  useEffect(() => {
    let cancelled = false;
    async function load() {
      if (hasSupabase) {
        const sb = supabaseBrowser()!;
        const { data: { user }, error: userError } = await sb.auth.getUser();
        if (userError) {
          if (!cancelled) { setErrorMessage(userError.message); setSourceMode("setup"); }
          return;
        }
        if (!user) { window.location.replace("/auth/"); return; }

        const [txResult, profileResult, budgetResult] = await Promise.all([
          sb.from("transactions").select("*").order("date", { ascending: false }),
          sb.from("profiles").select("first_name,monthly_net_income,salary_day,savings_target,safety_reserve").maybeSingle(),
          sb.from("budgets").select("category_name,amount").eq("month", `${activeMonth}-01`).order("category_name")
        ]);
        if (cancelled) return;
        if (txResult.error) { setErrorMessage(txResult.error.message); setSourceMode("setup"); return; }

        const mapped: Transaction[] = (txResult.data ?? []).map((r:any) => ({
          id:r.id, date:r.date, merchant:r.merchant, amount:Number(r.amount), account:r.account_name ?? "",
          category:r.category_name ?? "Sonstiges", cost_type:r.cost_type ?? "variabel", necessity:r.necessity ?? "freiwillig",
          source:r.source ?? "", note:r.note ?? "", month:String(r.date).slice(0,7), split:null, trip:null,
          is_internal_transfer:Boolean(r.is_internal_transfer), is_refund:Boolean(r.is_refund)
        }));
        setTransactions(mapped);

        if (!profileResult.error && profileResult.data) {
          const p = profileResult.data;
          setProfile({
            firstName: p.first_name ?? "",
            monthlyIncome: Number(p.monthly_net_income ?? 0),
            salaryDay: p.salary_day ?? null,
            savingsTarget: Number(p.savings_target ?? 0),
            safetyReserve: Number(p.safety_reserve ?? 0),
          });
        }
        if (!budgetResult.error && budgetResult.data?.length) {
          const defaults = new Map(categoryTemplates.map(b => [b.category, b]));
          setActiveBudgets(budgetResult.data.map((b:any) => ({
            category: b.category_name,
            amount: Number(b.amount),
            group: budgetGroup(defaults.get(b.category_name)?.group)
          })));
        }
        setSourceMode("supabase");
        setSyncNote("Supabase verbunden · persistente Daten aktiv");
        return;
      }

      if (demoMode) {
        const local = localStorage.getItem("lefty-demo-transactions");
        setTransactions(local ? safeParseTransactions(local, demoSeed) : demoSeed);
        setProfile(demoConfig.profile as Profile);
        setActiveBudgets(demoConfig.budgets as Budget[]);
        setSourceMode("demo");
        setSyncNote("Lokaler Demo-Modus · keine echten Finanzdaten");
        return;
      }

      setSourceMode("setup");
      setSyncNote("Supabase-Konfiguration fehlt");
    }
    void load();
    return () => { cancelled = true; };
  }, [activeMonth]);

  const currentSpend = monthSpend(transactions, activeMonth);
  const lifestyle = lifestyleSummary(transactions, activeMonth, activeBudgets);
  const fixedBudget = activeBudgets.filter(b=>b.group==="Fixkosten").reduce((s,b)=>s+b.amount,0);
  const available = Math.max(0, profile.monthlyIncome - currentSpend);

  async function addTransaction(input: Omit<Transaction,"id"|"month">) {
    const tx: Transaction = { ...input, id: crypto.randomUUID(), month: input.date.slice(0,7) };
    if (sourceMode === "demo") {
      const next = [tx, ...transactions];
      setTransactions(next);
      localStorage.setItem("lefty-demo-transactions", JSON.stringify(next));
      setShowAdd(false);
      return;
    }
    if (sourceMode !== "supabase") return;

    const sb = supabaseBrowser()!;
    const { data, error } = await sb.from("transactions").insert({
      date:tx.date, merchant:tx.merchant, amount:Math.abs(tx.amount), account_name:tx.account,
      category_name:tx.category, cost_type:tx.cost_type, necessity:tx.necessity, note:tx.note, source:"Manuell"
    }).select("*").single();
    if (error) { setErrorMessage(error.message); return; }
    setTransactions(prev => [{ ...tx, id:data.id }, ...prev]);
    setShowAdd(false);
  }

  if (sourceMode === "loading") return <LoadingScreen />;
  if (sourceMode === "setup") return <SetupScreen errorMessage={errorMessage} />;

  return <div className="app-shell">
    <aside className="sidebar">
      <img src="/lefty-logo-lockup.png" className="side-logo" alt="lefty" />
      <nav>{[
        ["home","Dashboard","home"],["transactions","Transaktionen","list"],["budget","Budgets","wallet"],["stats","Statistiken","chart"],["more","Mehr","more"]
      ].map(([id,label,icon])=><button key={id} className={tab===id?"active":""} onClick={()=>setTab(id as Tab)}><Icon name={icon}/><span>{label}</span></button>)}</nav>
      <div className="side-footer"><span className={`sync-dot ${sourceMode}`}></span>{syncNote}</div>
    </aside>

    <main className="content">
      {errorMessage && <div className="inline-error" role="status">{errorMessage}<button onClick={()=>setErrorMessage("")} aria-label="Meldung schließen">×</button></div>}
      {tab === "home" && <HomeView activeMonth={activeMonth} currentSpend={currentSpend} available={available} fixedBudget={fixedBudget} lifestyle={lifestyle} profile={profile} transactions={transactions} />}
      {tab === "transactions" && <TransactionsView transactions={transactions} search={search} setSearch={setSearch} />}
      {tab === "budget" && <BudgetView activeMonth={activeMonth} setActiveMonth={setActiveMonth} transactions={transactions} budgets={activeBudgets} filter={budgetFilter} setFilter={setBudgetFilter} />}
      {tab === "stats" && <StatsView activeMonth={activeMonth} transactions={transactions} budgets={activeBudgets} />}
      {tab === "more" && <MoreView transactions={transactions} profile={profile} sourceMode={sourceMode} />}
    </main>

    <button className="fab" aria-label="Neue Ausgabe" onClick={()=>setShowAdd(true)}><Icon name="plus"/></button>
    <BottomNav tab={tab} setTab={setTab} />
    {showAdd && <AddTransaction budgets={activeBudgets} onClose={()=>setShowAdd(false)} onAdd={addTransaction} />}
  </div>;
}

function monthKey(date: Date) {
  return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,"0")}`;
}

function shiftMonth(month: string, delta: number) {
  const [year, m] = month.split("-").map(Number);
  return monthKey(new Date(year, m - 1 + delta, 1));
}

function monthLabel(month: string) {
  const [year, m] = month.split("-").map(Number);
  return new Intl.DateTimeFormat("de-AT", { month:"long", year:"numeric" }).format(new Date(year, m-1, 1));
}

function shortMonthLabel(month: string) {
  const [year, m] = month.split("-").map(Number);
  return new Intl.DateTimeFormat("de-AT", { month:"short" }).format(new Date(year, m-1, 1));
}

function safeParseTransactions(value: string, fallback: Transaction[]) {
  try {
    const parsed = JSON.parse(value);
    return Array.isArray(parsed) ? parsed as Transaction[] : fallback;
  } catch { return fallback; }
}

function LoadingScreen() {
  return <main className="auth-shell"><section className="auth-card loading-card"><img src="/lefty-logo-lockup.png" alt="lefty" className="auth-logo"/><div className="loader"/><p>Lefty wird geladen …</p></section></main>;
}

function SetupScreen({errorMessage}:{errorMessage:string}) {
  return <main className="auth-shell"><section className="auth-card"><img src="/lefty-logo-lockup.png" alt="lefty" className="auth-logo"/><h1>Bereit für die Verbindung</h1><p>Für die produktive Version müssen die Supabase-Umgebungsvariablen gesetzt werden. Aus Sicherheitsgründen werden ohne Datenbankverbindung keine persönlichen Finanzdaten ausgeliefert.</p>{errorMessage && <p className="auth-message">{errorMessage}</p>}<p className="muted">Benötigt: NEXT_PUBLIC_SUPABASE_URL und NEXT_PUBLIC_SUPABASE_ANON_KEY.</p></section></main>;
}

function TopBar({title}:{title:string}) {
  return <header className="topbar"><div className="brand-mobile"><img src="/lefty-logo-lockup.png" alt="lefty" /></div><div><h1>{title}</h1></div><div className="avatar">L</div></header>;
}

function HomeView({activeMonth,currentSpend,available,fixedBudget,lifestyle,profile,transactions}:{activeMonth:string;currentSpend:number;available:number;fixedBudget:number;lifestyle:{total:number;used:number;remaining:number};profile:Profile;transactions:Transaction[]}) {
  const name = profile.firstName ? `, ${profile.firstName}` : "";
  const days = daysUntilSalary(profile.salaryDay);
  const daily = days ? available / days : null;
  const monthTransactions = transactions.filter(t => t.month === activeMonth);
  const latestDate = monthTransactions.length ? [...monthTransactions].sort((a,b)=>b.date.localeCompare(a.date))[0].date : null;
  return <>
    <TopBar title="" />
    <section className="greeting"><h2>Guten Morgen{name} 👋</h2><p>Schön, dass du da bist.</p></section>
    <section className="hero-card"><div><p>Diesen Monat noch verfügbar</p><strong>{formatEUR(available)}</strong><small>{latestDate ? `Datenstand ${new Date(latestDate+"T12:00:00").toLocaleDateString("de-AT")}` : "Noch keine Buchungen in diesem Konto"}</small></div><span className="hero-mark">L</span></section>
    <section className="metric-grid">
      <Metric icon="arrow" label="Einnahmen" value={formatEUR(profile.monthlyIncome)} tone="green" />
      <Metric icon="arrow" label="Ausgaben" value={formatEUR(currentSpend)} tone="red" down />
      <Metric icon="home" label="Fixkosten-Budget" value={formatEUR(fixedBudget)} tone="orange" />
      <Metric icon="pig" label="Sparziel" value={formatEUR(profile.savingsTarget)} tone="green" />
    </section>
    <section className="panel lifestyle-panel">
      <div className="panel-row"><span className="circle-icon orange">✦</span><div><small>Ohne schlechtes Gewissen</small><h3>{formatEUR(lifestyle.remaining)} übrig</h3></div><span>›</span></div>
      <Progress value={lifestyle.total ? lifestyle.used/lifestyle.total*100 : 0} />
      <p className="muted">{formatEUR(lifestyle.used)} von {formatEUR(lifestyle.total)} verwendet</p>
    </section>
    <section className="panel salary-panel"><div className="panel-row"><span className="circle-icon blue"><Icon name="calendar"/></span><div><small>Nächster Gehaltseingang</small><h3>{days ? `Noch ${days} ${days === 1 ? "Tag" : "Tage"}` : "Gehaltstag konfigurieren"}</h3><p className="muted">{daily !== null ? `ca. ${formatEUR(daily)} pro Tag verfügbar` : "Safe-to-Spend pro Tag wird danach berechnet."}</p></div><span>›</span></div></section>
    <section className="data-note"><strong>{monthLabel(activeMonth)}</strong><span>{monthTransactions.length} Buchungen in diesem Monat</span></section>
  </>;
}

function daysUntilSalary(salaryDay: number | null) {
  if (!salaryDay) return null;
  const now = new Date();
  const next = new Date(now.getFullYear(), now.getMonth(), Math.min(salaryDay, new Date(now.getFullYear(), now.getMonth()+1, 0).getDate()));
  if (next <= now) next.setMonth(next.getMonth()+1);
  const lastDay = new Date(next.getFullYear(), next.getMonth()+1, 0).getDate();
  next.setDate(Math.min(salaryDay, lastDay));
  return Math.max(1, Math.ceil((next.getTime()-now.getTime())/86400000));
}

function Metric({icon,label,value,tone,down}:{icon:string;label:string;value:string;tone:string;down?:boolean}) {
  return <div className="metric"><span className={`circle-icon ${tone} ${down?"rotate":""}`}><Icon name={icon}/></span><div><small>{label}</small><strong>{value}</strong></div></div>;
}

function Progress({value}:{value:number}) {
  const v=Math.min(100,Math.max(0,value)); const status=statusFor(value);
  return <div className="progress" aria-label={`${Math.round(value)} Prozent`}><span className={status} style={{width:`${v}%`}} /></div>;
}

function TransactionsView({transactions,search,setSearch}:{transactions:Transaction[];search:string;setSearch:(s:string)=>void}) {
  const filtered = transactions.filter(t => `${t.merchant} ${t.category} ${t.account}`.toLowerCase().includes(search.toLowerCase())).slice(0,120);
  return <><TopBar title="Transaktionen"/><div className="page-head"><div><h2>Transaktionen</h2><p>Suche über Händler, Kategorie und Konto.</p></div><div className="amount-pill">{transactions.length} Buchungen</div></div>
    <div className="search"><span>⌕</span><input value={search} onChange={e=>setSearch(e.target.value)} placeholder="z. B. BILLA" aria-label="Transaktionen suchen" /></div>
    <div className="transaction-list">{filtered.map(t=><article className="transaction" key={t.id}><div className="tx-icon">{categoryIcon(t.category)}</div><div className="tx-main"><strong>{t.merchant}</strong><span>{new Date(t.date+"T12:00:00").toLocaleDateString("de-AT")} · {t.category}</span></div><div className="tx-money"><strong>{t.is_refund ? "+" : "-"}{formatEUR(Math.abs(t.amount))}</strong><span>{t.account}</span></div></article>)}</div>
  </>;
}

function BudgetView({activeMonth,setActiveMonth,transactions,budgets,filter,setFilter}:{activeMonth:string;setActiveMonth:(m:string)=>void;transactions:Transaction[];budgets:Budget[];filter:string;setFilter:(s:string)=>void}) {
  const filtered = budgets.filter(b=>filter==="Alle" || b.group===filter);
  return <><TopBar title="Budgets"/><div className="page-head"><div><h2>Budgets</h2><p>{monthLabel(activeMonth)}</p></div></div>
    <div className="month-switch"><button aria-label="Vorheriger Monat" onClick={()=>setActiveMonth(shiftMonth(activeMonth,-1))}>‹</button><strong>{monthLabel(activeMonth)}</strong><button aria-label="Nächster Monat" onClick={()=>setActiveMonth(shiftMonth(activeMonth,1))}>›</button></div>
    <div className="chips">{["Alle","Fixkosten","Lifestyle","Sparen"].map(x=><button className={filter===x?"active":""} onClick={()=>setFilter(x)} key={x}>{x}</button>)}</div>
    <section className="budget-list">{filtered.map(b=>{const spent=categorySpend(transactions,activeMonth,b.category); const pct=b.amount?spent/b.amount*100:0; return <article className="budget-row" key={b.category}>
      <span className={`category-bubble ${statusFor(pct)}`}>{categoryIcon(b.category)}</span><div className="budget-main"><div className="budget-title"><strong>{b.category}</strong><span className={statusFor(pct)}>{Math.round(pct)} %</span></div><small>{formatEUR(spent)} von {formatEUR(b.amount)}</small><Progress value={pct}/></div>
    </article>})}</section>
  </>;
}

function StatsView({activeMonth,transactions,budgets}:{activeMonth:string;transactions:Transaction[];budgets:Budget[]}) {
  const monthOrder=[-3,-2,-1,0].map(offset=>shiftMonth(activeMonth,offset));
  const values=monthOrder.map(m=>monthSpend(transactions,m)); const max=Math.max(...values,1);
  const necessary=transactions.reduce((s,t)=>s+(t.necessity==="notwendig"?transactionBudgetAmount(t):0),0);
  const voluntary=transactions.reduce((s,t)=>s+(t.necessity==="freiwillig"?transactionBudgetAmount(t):0),0);
  const cats=useMemo(()=>budgets.map(b=>[b.category,transactions.filter(t=>t.category===b.category).reduce((s,t)=>s+transactionBudgetAmount(t),0)] as const).sort((a,b)=>b[1]-a[1]).slice(0,6),[budgets,transactions]);
  return <><TopBar title="Statistiken"/><div className="page-head"><div><h2>Statistiken</h2><p>Letzte vier Monate bis {monthLabel(activeMonth)}</p></div></div>
    <section className="panel chart-card"><h3>Ausgaben pro Monat</h3><div className="bars">{values.map((v,i)=><div className="bar-col" key={monthOrder[i]}><strong>{formatEUR(v)}</strong><div className="bar-track"><span style={{height:`${v/max*100}%`}}/></div><small>{shortMonthLabel(monthOrder[i])}</small></div>)}</div></section>
    <section className="two-col"><div className="panel"><h3>Notwendig</h3><strong className="big-number">{formatEUR(necessary)}</strong></div><div className="panel"><h3>Freiwillig</h3><strong className="big-number">{formatEUR(voluntary)}</strong></div></section>
    <section className="panel"><h3>Größte Kategorien</h3>{cats.map(([c,v])=><div className="rank-row" key={c}><span>{c}</span><strong>{formatEUR(v)}</strong></div>)}</section>
  </>;
}

function MoreView({transactions,profile,sourceMode}:{transactions:Transaction[];profile:Profile;sourceMode:SourceMode}) {
  const fixed = transactions.filter(t=>t.cost_type==="fix").reduce((s,t)=>s+transactionBudgetAmount(t),0);
  const subs = transactions.filter(t=>t.category==="Abos").reduce((s,t)=>s+transactionBudgetAmount(t),0);
  async function logout() {
    if (sourceMode !== "supabase") return;
    await supabaseBrowser()!.auth.signOut();
    window.location.replace("/auth/");
  }
  return <><TopBar title="Mehr"/><div className="page-head"><div><h2>Mehr</h2><p>Weitere Lefty-Bereiche</p></div></div>
    <div className="feature-grid">
      <Feature title="Fixkosten" text={`${formatEUR(fixed)} im geladenen Zeitraum`} icon="home"/>
      <Feature title="Abos" text={`${formatEUR(subs)} im geladenen Zeitraum`} icon="wallet"/>
      <Feature title="Sparen & Vermögen" text={`Monatliches Sparziel: ${formatEUR(profile.savingsTarget)}`} icon="pig"/>
      <Feature title="Reisen" text="Reiseausgaben separat analysieren" icon="arrow"/>
      <Feature title="Geteilt" text="Forderungen, Rückzahlungen & Splits" icon="split"/>
      <Feature title="Kommende Ausgaben" text="Geplante Kosten für Safe-to-Spend" icon="calendar"/>
    </div>
    {sourceMode === "supabase" && <section className="panel implementation"><h3>Konto</h3><p>Deine Finanzdaten werden über dein angemeldetes Supabase-Konto geladen.</p><button className="secondary" onClick={() => void logout()}>Ausloggen</button></section>}
    {sourceMode === "demo" && <section className="panel implementation"><h3>Demo-Modus</h3><p>Diese Ansicht verwendet ausschließlich anonymisierte Beispieldaten und ist nicht für die produktive Nutzung gedacht.</p></section>}
  </>;
}

function Feature({title,text,icon}:{title:string;text:string;icon:string}) { return <article className="feature"><span className="feature-icon"><Icon name={icon}/></span><div><strong>{title}</strong><span>{text}</span></div><b>›</b></article>; }

function BottomNav({tab,setTab}:{tab:Tab;setTab:(t:Tab)=>void}) {
  const items:Array<[Tab,string,string]>=[["home","Home","home"],["transactions","Transaktionen","list"],["budget","Budgets","wallet"],["stats","Statistiken","chart"],["more","Mehr","more"]];
  return <nav className="bottom-nav">{items.map(([id,label,icon])=><button key={id} className={tab===id?"active":""} onClick={()=>setTab(id)}><Icon name={icon}/><span>{label}</span></button>)}</nav>;
}

function AddTransaction({budgets,onClose,onAdd}:{budgets:Budget[];onClose:()=>void;onAdd:(t:Omit<Transaction,"id"|"month">)=>Promise<void>}) {
  const [amount,setAmount]=useState(""); const [merchant,setMerchant]=useState(""); const [category,setCategory]=useState("Lebensmittel & Haushalt");
  async function submit(e:React.FormEvent){e.preventDefault(); const n=Number(amount); if (!Number.isFinite(n) || n<=0) return; await onAdd({date:new Date().toISOString().slice(0,10),merchant:merchant.trim(),amount:n,account:"Manuell",category,cost_type:"variabel",necessity:"freiwillig",source:"Manuell",note:"",split:null,trip:null});}
  return <div className="modal-backdrop" onMouseDown={onClose}><form className="modal" onSubmit={(e)=>void submit(e)} onMouseDown={e=>e.stopPropagation()}><div className="modal-head"><h2>Neue Ausgabe</h2><button type="button" onClick={onClose}>×</button></div><label>Betrag (€)<input autoFocus inputMode="decimal" value={amount} onChange={e=>setAmount(e.target.value.replace(",","."))} required /></label><label>Händler<input value={merchant} onChange={e=>setMerchant(e.target.value)} required /></label><label>Kategorie<select value={category} onChange={e=>setCategory(e.target.value)}>{budgets.filter(b=>b.category!=="Puffer").map(b=><option key={b.category}>{b.category}</option>)}</select></label><button className="primary" type="submit">Ausgabe speichern</button></form></div>;
}
