"use client";

import { useEffect, useState } from "react";
import Link from "next/link";
import { AppShell } from "@/components/AppShell";
import {
  EXPIRY_WINDOW_DAYS,
  getBankStats,
  getBillingStats,
  getPolicyStats,
  getPropertyStats,
  getStats,
  listBankAccounts,
} from "@/lib/api";
import { useAuth } from "@/lib/abilities";
import {
  balancePhrase,
  formatDate,
  formatMoney,
  formatNumber,
  policyStatusLabel,
  trustStatusLabel,
} from "@/lib/labels";
import type {
  BankAccount,
  BankStats,
  BillingStats,
  CustomerStats,
  PolicyStats,
  PropertyStats,
} from "@/lib/types";

export default function InicioPage() {
  return (
    <AppShell>
      <HomeDashboard />
    </AppShell>
  );
}

interface DashboardData {
  customers: CustomerStats | null;
  policies: PolicyStats | null;
  properties: PropertyStats | null;
  billing: BillingStats | null;
  /** Figures for ONE chequera — see `bankAccount` for which. */
  bank: BankStats | null;
  /**
   * The chequera the card above is reading. The office keeps more than one, in
   * different currencies, so this card shows the default account rather than a
   * cross-account total, which would be a figure that never existed.
   */
  bankAccount: BankAccount | null;
  bankAccountCount: number;
}

/** Same default as /banco, so the two screens agree on which chequera opens. */
function defaultAccount(accounts: BankAccount[]): BankAccount | null {
  const remembered =
    typeof window !== "undefined"
      ? window.localStorage.getItem("banco.bankAccountId")
      : null;
  return (
    accounts.find((a) => a.id === remembered) ??
    accounts.find((a) => a.active) ??
    accounts[0] ??
    null
  );
}

function HomeDashboard() {
  const user = useAuth();
  const [data, setData] = useState<DashboardData>({
    customers: null,
    policies: null,
    properties: null,
    billing: null,
    bank: null,
    bankAccount: null,
    bankAccountCount: 0,
  });
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let alive = true;
    // The chequera figures need an account id, so that read is a two-step:
    // list the accounts, then ask the default one for its stats.
    const bank = listBankAccounts().then(async (accounts) => {
      const account = defaultAccount(accounts);
      if (!account) return { account: null, stats: null, count: 0 };
      return {
        account,
        stats: await getBankStats(account.id),
        count: accounts.length,
      };
    });

    Promise.allSettled([
      getStats(),
      getPolicyStats(),
      getPropertyStats(),
      getBillingStats(),
      bank,
    ]).then((results) => {
      if (!alive) return;
      const bankResult = results[4].status === "fulfilled" ? results[4].value : null;
      setData({
        customers: results[0].status === "fulfilled" ? results[0].value : null,
        policies: results[1].status === "fulfilled" ? results[1].value : null,
        properties: results[2].status === "fulfilled" ? results[2].value : null,
        billing: results[3].status === "fulfilled" ? results[3].value : null,
        bank: bankResult?.stats ?? null,
        bankAccount: bankResult?.account ?? null,
        bankAccountCount: bankResult?.count ?? 0,
      });
      setLoading(false);
    });
    return () => {
      alive = false;
    };
  }, []);

  const greeting = greetingFor(user?.name);
  const lastBillingMovement = data.billing?.lastMovement ?? null;
  const lastBankMovement = data.bank?.lastMovement ?? null;

  return (
    <div className="home rise">
      <div className="page-head">
        <p className="eyebrow">Resumen general</p>
        <h1 className="page-title">{greeting}</h1>
        <p className="muted" style={{ marginTop: 6, maxWidth: 640 }}>
          Vista rápida del estado de la cartera de clientes, las pólizas
          activas, los fideicomisos y los movimientos recientes.
        </p>
        <LastSeenLine
          billing={lastBillingMovement}
          bank={lastBankMovement}
          loading={loading}
        />
      </div>

      <section aria-label="Indicadores principales" className="home-section">
        <KpiCard
          href="/clientes"
          label="Clientes"
          loading={loading}
          primary={data.customers ? formatNumber(data.customers.customers) : "—"}
          sub={
            data.customers
              ? [
                  `${formatNumber(data.customers.withUtilities)} con servicios`,
                  `${formatNumber(data.customers.withInsurance)} con seguros`,
                  `${formatNumber(data.customers.bothLines)} en ambos ramos`,
                ]
              : []
          }
        />
        <KpiCard
          href="/servicios"
          label="Propiedades"
          loading={loading}
          primary={data.properties ? formatNumber(data.properties.properties) : "—"}
          sub={
            data.properties
              ? [
                  `${formatNumber(data.properties.services)} servicios`,
                  `${formatNumber(data.properties.trusts)} fideicomisos`,
                  `${formatNumber(data.properties.trustExpiring)} por vencer`,
                ]
              : []
          }
        />
        <KpiCard
          href="/polizas"
          label="Pólizas"
          loading={loading}
          primary={data.policies ? formatNumber(data.policies.total) : "—"}
          sub={
            data.policies
              ? [
                  `${formatNumber(data.policies.active)} vigentes`,
                  `${formatNumber(data.policies.expiring)} por vencer (${EXPIRY_WINDOW_DAYS} d)`,
                  `${formatNumber(data.policies.expired + data.policies.undated)} vencidas o sin fecha`,
                ]
              : []
          }
        />
        <KpiCard
          href="/estado-cuenta"
          label="Movimientos"
          loading={loading}
          primary={data.billing ? formatNumber(data.billing.movements) : "—"}
          sub={
            data.billing
              ? [
                  `${formatNumber(data.billing.ledgerCustomers)} clientes con cargo`,
                  `${formatNumber(data.billing.crossLineCustomers)} con ambos ramos`,
                  lastBillingMovement
                    ? `Último: ${formatDate(lastBillingMovement)}`
                    : "Sin movimientos",
                ]
              : []
          }
        />
      </section>

      <section aria-label="Atención" className="home-section">
        <div className="section-head">
          <h2 className="section-title">Atención</h2>
          <span className="section-sub">
            Lo que conviene revisar antes de cerrar el día
          </span>
        </div>

        <div className="attention-grid">
          <AttentionCard
            href="/polizas?status=expiring"
            tone="warn"
            loading={loading}
            title="Pólizas por vencer"
            primary={
              data.policies ? formatNumber(data.policies.expiring) : "—"
            }
            sub={
              data.policies
                ? `En los próximos ${EXPIRY_WINDOW_DAYS} días — ventana: ${policyStatusLabel("expiring")}`
                : undefined
            }
            meta={
              data.policies
                ? `${formatNumber(data.policies.active)} vigentes · ${formatNumber(data.policies.expired)} vencidas`
                : undefined
            }
          />
          <AttentionCard
            href="/servicios?trust=expiring"
            tone="warn"
            loading={loading}
            title="Fideicomisos por vencer"
            primary={
              data.properties ? formatNumber(data.properties.trustExpiring) : "—"
            }
            sub={
              data.properties
                ? `Renueva en los próximos ${EXPIRY_WINDOW_DAYS} días (${trustStatusLabel("expiring")})`
                : undefined
            }
            meta={
              data.properties
                ? `${formatNumber(data.properties.trusts)} fideicomisos en cartera`
                : undefined
            }
          />
          <AttentionCard
            href="/polizas?status=undated"
            tone="muted"
            loading={loading}
            title="Pólizas sin vigencia"
            primary={data.policies ? formatNumber(data.policies.undated) : "—"}
            sub={
              data.policies
                ? "Sin fecha de fin registrada — revisar y completar"
                : undefined
            }
            meta={
              data.policies
                ? `${formatNumber(data.policies.liquidated)} liquidadas`
                : undefined
            }
          />
          <AttentionCard
            href="/estado-cuenta"
            tone="info"
            loading={loading}
            title="Clientes con adeudo"
            primary={
              data.billing ? (
                <CurrencyTotals
                  totals={data.billing.byCurrency}
                  field="owing"
                />
              ) : (
                "—"
              )
            }
            sub={
              data.billing
                ? `En ${formatNumber(data.billing.ledgerCustomers)} expedientes con cargo`
                : undefined
            }
            meta={
              data.billing
                ? `${formatNumber(data.billing.crossLineCustomers)} clientes con cargo en ambos ramos`
                : undefined
            }
          />
          <AttentionCard
            href="/banco"
            tone="info"
            loading={loading}
            title="Chequera del despacho"
            primary={
              data.bank && data.bankAccount ? (
                <span className={data.bank.net.startsWith("-") ? "money-neg" : "money-pos"}>
                  {formatMoney(data.bank.net, data.bankAccount.currency)}
                </span>
              ) : (
                "—"
              )
            }
            // Names the account, because this is one chequera's figure and the
            // office has more than one — they are never added together.
            sub={
              data.bank && data.bankAccount
                ? `${data.bankAccount.label} · ${balancePhrase(data.bank.net)}`
                : undefined
            }
            meta={
              data.bank
                ? `${formatNumber(data.bank.movements)} movimientos · ${formatNumber(data.bank.pending)} pendientes` +
                  (data.bankAccountCount > 1
                    ? ` · ${formatNumber(data.bankAccountCount)} cuentas en total`
                    : "")
                : undefined
            }
          />
        </div>
      </section>

      <section aria-label="Accesos rápidos" className="home-section">
        <div className="section-head">
          <h2 className="section-title">Accesos rápidos</h2>
          <span className="section-sub">
            Ir directo a cada módulo
          </span>
        </div>
        <div className="quick-grid">
          <QuickLink href="/clientes" label="Clientes" sub="Directorio unificado" />
          <QuickLink href="/servicios" label="Propiedades" sub="Servicios y fideicomisos" />
          <QuickLink href="/polizas" label="Pólizas" sub="Vigencias y liquidaciones" />
          <QuickLink href="/estado-cuenta" label="Estado de cuenta" sub="Cargos y abonos" />
          <QuickLink href="/banco" label="Chequera" sub="Ingresos y egresos" />
        </div>
      </section>
    </div>
  );
}

function greetingFor(name?: string): string {
  const hour = new Date().getHours();
  const partOfDay =
    hour < 12 ? "Buenos días" : hour < 19 ? "Buenas tardes" : "Buenas noches";
  const display = (name ?? "").trim().split(/\s+/)[0];
  return display ? `${partOfDay}, ${display}` : partOfDay;
}

function LastSeenLine({
  billing,
  bank,
  loading,
}: {
  billing: string | null;
  bank: string | null;
  loading: boolean;
}) {
  if (loading) {
    return (
      <p className="muted home-last-seen" aria-hidden="true">
        <span className="skeleton" style={{ display: "inline-block", width: 220, height: 12 }} />
      </p>
    );
  }
  if (!billing && !bank) return null;
  return (
    <p className="muted home-last-seen">
      {billing && <>Último movimiento de cartera: <strong>{formatDate(billing)}</strong></>}
      {billing && bank && <span aria-hidden="true"> · </span>}
      {bank && <>Último movimiento de chequera: <strong>{formatDate(bank)}</strong></>}
    </p>
  );
}

function KpiCard({
  href,
  label,
  primary,
  sub,
  loading,
}: {
  href: string;
  label: string;
  primary: React.ReactNode;
  sub: string[];
  loading: boolean;
}) {
  return (
    <Link href={href} className="kpi-card card">
      <div className="kpi-label">{label}</div>
      <div className="kpi-primary">
        {loading ? (
          <span
            className="skeleton"
            style={{ display: "inline-block", width: 90, height: 30 }}
          />
        ) : (
          primary
        )}
      </div>
      <ul className="kpi-sub">
        {loading
          ? Array.from({ length: 3 }).map((_, i) => (
              <li key={i} className="skeleton" style={{ height: 10 }} />
            ))
          : sub.map((line) => <li key={line}>{line}</li>)}
      </ul>
      <span className="kpi-cta" aria-hidden="true">
        Ver módulo →
      </span>
    </Link>
  );
}

function AttentionCard({
  href,
  tone,
  title,
  primary,
  sub,
  meta,
  loading,
}: {
  href: string;
  tone: "warn" | "info" | "muted";
  title: string;
  primary: React.ReactNode;
  sub?: string;
  meta?: string;
  loading: boolean;
}) {
  return (
    <Link href={href} className={`attention-card tone-${tone} card`}>
      <div className="attention-head">
        <span className="attention-title">{title}</span>
        <span className="attention-arrow" aria-hidden="true">→</span>
      </div>
      <div className="attention-primary">
        {loading ? (
          <span
            className="skeleton"
            style={{ display: "inline-block", width: 70, height: 28 }}
          />
        ) : (
          primary
        )}
      </div>
      {sub && !loading && <div className="attention-sub">{sub}</div>}
      {meta && !loading && <div className="attention-meta">{meta}</div>}
    </Link>
  );
}

function QuickLink({
  href,
  label,
  sub,
}: {
  href: string;
  label: string;
  sub: string;
}) {
  return (
    <Link href={href} className="quick-link card">
      <span className="quick-label">{label}</span>
      <span className="quick-sub">{sub}</span>
      <span className="quick-arrow" aria-hidden="true">→</span>
    </Link>
  );
}

function CurrencyTotals({
  totals,
  field,
}: {
  totals: BillingStats["byCurrency"];
  field: "owing" | "inCredit";
}) {
  if (!totals || totals.length === 0) return <>—</>;
  return (
    <span className="home-currency-totals">
      {totals.map((c) => (
        <span key={c.currency} className="home-currency-totals-row">
          <span className="badge badge-count">{c.currency}</span>
          <span className="home-currency-totals-num">
            {formatNumber(c[field])}
          </span>
        </span>
      ))}
    </span>
  );
}
