"use client";

import * as React from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useSession } from "next-auth/react";
import { ArrowUp, ArrowDown, Minus, Pencil, Wallet, Printer } from "lucide-react";
import { apiGet, apiSend } from "@/lib/api";
import type { ExecutiveDTO, ExecCompanyRow, ExecMetrics } from "@/lib/types";
import { isManagerTier, can } from "@/lib/rbac";
import { KPI_CATEGORY_LABEL } from "@/lib/labels";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select } from "@/components/ui/select";
import { Badge } from "@/components/ui/badge";
import { Progress } from "@/components/ui/progress";
import { Dialog, DialogHeader, DialogBody, DialogFooter } from "@/components/ui/dialog";
import { InfoHint } from "@/components/ui/info-hint";
import { PageHeader, Spinner, EmptyState } from "@/components/common";

const MONTHS = [
  "January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December",
];

const rm = (n: number | null) =>
  n === null ? "—" : "RM " + n.toLocaleString(undefined, { maximumFractionDigits: 2 });
const num = (n: number | null) => (n === null ? "—" : n.toLocaleString());
const pct = (n: number | null) => (n === null ? "—" : `${n}%`);
const x = (n: number | null) => (n === null ? "—" : `${n}×`);

function ragText(value: number | null, good: number, ok: number, higherBetter = true): string {
  if (value === null) return "text-foreground";
  const pass = higherBetter ? value >= good : value <= good;
  const mid = higherBetter ? value >= ok : value <= ok;
  if (pass) return "text-success";
  if (mid) return "text-warning";
  return "text-destructive";
}

export function ExecutiveView() {
  const { data: session } = useSession();
  const manager = isManagerTier(session?.user?.role);
  const canEdit = can(session?.user?.role, "financials:write");

  const today = new Date();
  const [year, setYear] = React.useState(today.getFullYear());
  const [month, setMonth] = React.useState(today.getMonth() + 1);
  const years = [today.getFullYear() - 1, today.getFullYear(), today.getFullYear() + 1];
  const [editing, setEditing] = React.useState<ExecCompanyRow | null>(null);

  const q = useQuery({
    queryKey: ["executive", year, month],
    queryFn: () => apiGet<ExecutiveDTO>(`/api/dashboard/executive?year=${year}&month=${month}`),
    enabled: manager,
  });

  if (!manager) {
    return (
      <EmptyState
        title="Manager access required"
        description="The executive dashboard is available to Manager, Admin and Super Admin roles."
      />
    );
  }

  const d = q.data;

  // The company with the weakest lead→enrollment conversion (needs 2+ companies
  // with data for a comparison to be meaningful).
  const weakestCompanyId = React.useMemo(() => {
    if (!d) return null;
    const withConv = d.companies.filter((c) => c.leadToEnroll !== null);
    if (withConv.length < 2) return null;
    return withConv.reduce((a, b) => ((b.leadToEnroll ?? 0) < (a.leadToEnroll ?? 0) ? b : a)).id;
  }, [d]);

  return (
    <div>
      <PageHeader title="Executive Dashboard" subtitle="Marketing performance at a glance — money, growth & efficiency">
        <Select className="no-print h-8 w-auto text-xs" value={String(month)} onChange={(e) => setMonth(Number(e.target.value))}>
          {MONTHS.map((m, i) => (
            <option key={m} value={i + 1}>{m}</option>
          ))}
        </Select>
        <Select className="no-print h-8 w-auto text-xs" value={String(year)} onChange={(e) => setYear(Number(e.target.value))}>
          {years.map((y) => (
            <option key={y} value={y}>{y}</option>
          ))}
        </Select>
        <Button variant="secondary" className="no-print" onClick={() => window.print()}>
          <Printer className="size-4" /> Print
        </Button>
      </PageHeader>

      {q.isLoading || !d ? (
        <Spinner />
      ) : (
        <div className="print-area space-y-6">
          <div className="hidden print:block">
            <h1 className="text-2xl font-bold">Executive Dashboard</h1>
            <p className="text-sm">{MONTHS[month - 1]} {year}</p>
            <hr className="my-3" />
          </div>

          {/* Headline scorecards */}
          <div className="grid grid-cols-2 gap-3 md:grid-cols-3 xl:grid-cols-5">
            <MetricCard label="Revenue" value={rm(d.overall.revenue)} delta={d.deltas.revenue} goodWhenUp
              info="Total marketing-sourced revenue entered for this month, across all companies." />
            <MetricCard label="ROAS" value={x(d.overall.roas)} delta={d.deltas.roas} goodWhenUp
              rag={ragText(d.overall.roas, 4, 2)} hint="revenue ÷ spend"
              info="Return On Ad Spend = revenue ÷ ad spend. E.g. 4× means every RM1 spent returned RM4. Higher is better." />
            <MetricCard label="ROI" value={pct(d.overall.roi)} delta={d.deltas.roi} goodWhenUp
              rag={ragText(d.overall.roi, 100, 0)}
              info="Return On Investment = (revenue − ad spend) ÷ ad spend, as a %. Shows profit relative to spend; 100% means you doubled your money." />
            <MetricCard label="New Enrollments" value={num(d.overall.enrollments)} delta={d.deltas.enrollments} goodWhenUp
              info="Number of new paying customers/enrolments recorded this month." />
            <MetricCard label="Leads" value={num(d.overall.leads)} delta={d.deltas.leads} goodWhenUp
              info="Number of new leads (enquiries) captured this month — the top of the acquisition funnel." />
            <MetricCard label="Ad Spend" value={rm(d.overall.adSpend)} delta={d.deltas.adSpend} goodWhenUp={false} hint="vs last month"
              info="Actual marketing money spent this month. Lower isn't always better — read it alongside ROAS and enrolments." />
            <MetricCard label="Cost / Enrollment" value={rm(d.overall.cac)} delta={d.deltas.cac} goodWhenUp={false} hint="CAC"
              info="Customer Acquisition Cost = ad spend ÷ new enrolments. The average cost to win one paying customer. Lower is better." />
            <MetricCard label="Cost / Lead" value={rm(d.overall.cpl)} delta={d.deltas.cpl} goodWhenUp={false} hint="CPL"
              info="Cost Per Lead = ad spend ÷ leads. The average cost to generate one enquiry. Lower is better." />
            <MetricCard label="Lead → Enrol" value={pct(d.overall.leadToEnroll)} delta={d.deltas.leadToEnroll} goodWhenUp
              rag={ragText(d.overall.leadToEnroll, 20, 10)}
              info="Share of leads that became paying customers this month (enrolments ÷ leads). Overall funnel conversion — higher is better." />
            <BudgetCard overall={d.overall} />
          </div>

          {/* Acquisition funnel — one per company */}
          <Card className="break-inside-avoid">
            <CardHeader>
              <CardTitle className="flex items-center gap-1.5">
                Acquisition Funnel by Company
                <InfoHint text="For each company, the journey Leads → Trials → Enrollments for the selected month; the % between stages is the conversion rate. These counts are entered manually per company via the pencil in 'By Company' — they are not pulled from tasks/KPIs." />
              </CardTitle>
            </CardHeader>
            <CardContent className="space-y-5">
              {d.companies.length === 0 ? (
                <EmptyState title="No company data" />
              ) : (
                d.companies.map((c) => (
                  <div key={c.id} className="break-inside-avoid">
                    <div className="mb-2 flex items-center justify-between gap-2">
                      <span className="flex items-center gap-2 text-sm font-semibold">
                        {c.name}
                        {c.id === weakestCompanyId && (
                          <Badge variant="destructive">Lowest conversion</Badge>
                        )}
                      </span>
                      <span className="text-xs text-muted-foreground">
                        Lead → Enrol:{" "}
                        <span className={`font-semibold ${ragText(c.leadToEnroll, 20, 10)}`}>
                          {pct(c.leadToEnroll)}
                        </span>
                      </span>
                    </div>
                    <div className="flex flex-col items-stretch gap-2 sm:flex-row sm:items-center">
                      <FunnelStage label="Leads" value={c.leads} />
                      <FunnelArrow conv={c.leadToTrial} />
                      <FunnelStage label="Trials" value={c.trials} />
                      <FunnelArrow conv={c.trialToEnroll} />
                      <FunnelStage label="Enrollments" value={c.enrollments} highlight />
                    </div>
                  </div>
                ))
              )}
            </CardContent>
          </Card>

          <div className="grid gap-4 lg:grid-cols-3">
            {/* Per-company breakdown */}
            <Card className="lg:col-span-2 overflow-hidden break-inside-avoid">
              <CardHeader>
                <CardTitle>By Company</CardTitle>
              </CardHeader>
              <CardContent className="p-0">
                <div className="overflow-x-auto">
                  <table className="w-full text-sm">
                    <thead>
                      <tr className="border-y border-border text-left text-xs uppercase text-muted-foreground">
                        <th className="px-3 py-2">Company</th>
                        <th className="px-3 py-2 text-right">Revenue</th>
                        <th className="px-3 py-2 text-right">Spend / Budget</th>
                        <th className="px-3 py-2 text-right">ROAS</th>
                        <th className="px-3 py-2 text-right">Enrol</th>
                        <th className="px-3 py-2 text-right">CAC</th>
                        {canEdit && <th className="no-print px-3 py-2" />}
                      </tr>
                    </thead>
                    <tbody>
                      {d.companies.length === 0 ? (
                        <tr>
                          <td colSpan={7} className="px-3 py-6 text-center text-muted-foreground">
                            No companies yet.
                          </td>
                        </tr>
                      ) : (
                        d.companies.map((c) => (
                          <tr key={c.id} className="border-b border-border last:border-0">
                            <td className="px-3 py-2 font-medium">{c.name}</td>
                            <td className="px-3 py-2 text-right">{rm(c.revenue)}</td>
                            <td className="px-3 py-2 text-right">
                              <span className={c.overBudget ? "text-destructive font-medium" : ""}>
                                {rm(c.adSpend)}
                              </span>
                              <span className="text-muted-foreground"> / {rm(c.budget)}</span>
                              {c.overBudget && <Badge variant="destructive" className="ml-1">over</Badge>}
                            </td>
                            <td className={`px-3 py-2 text-right ${ragText(c.roas, 4, 2)}`}>{x(c.roas)}</td>
                            <td className="px-3 py-2 text-right">{num(c.enrollments)}</td>
                            <td className="px-3 py-2 text-right">{rm(c.cac)}</td>
                            {canEdit && (
                              <td className="no-print px-3 py-2 text-right">
                                <Button variant="ghost" size="icon" onClick={() => setEditing(c)} title="Edit figures">
                                  <Pencil className="size-3.5" />
                                </Button>
                              </td>
                            )}
                          </tr>
                        ))
                      )}
                    </tbody>
                  </table>
                </div>
                {canEdit && (
                  <p className="no-print border-t border-border px-3 py-2 text-xs text-muted-foreground">
                    Click the pencil to enter a company&apos;s budget, spend, revenue &amp; funnel for {MONTHS[month - 1]}.
                  </p>
                )}
              </CardContent>
            </Card>

            {/* KPI attainment by category */}
            <Card className="break-inside-avoid">
              <CardHeader>
                <CardTitle>KPI Attainment by Area</CardTitle>
              </CardHeader>
              <CardContent className="space-y-3">
                {d.categories.length === 0 ? (
                  <EmptyState title="No KPIs yet" />
                ) : (
                  d.categories.map((c) => (
                    <div key={c.category}>
                      <div className="mb-1 flex items-center justify-between text-sm">
                        <span className="font-medium">{KPI_CATEGORY_LABEL[c.category] ?? c.category}</span>
                        <span className="text-muted-foreground">
                          {c.attainment}% · {c.kpiCount} KPI{c.kpiCount === 1 ? "" : "s"}
                        </span>
                      </div>
                      <Progress value={c.attainment} />
                    </div>
                  ))
                )}
              </CardContent>
            </Card>
          </div>
        </div>
      )}

      {canEdit && (
        <FinancialsDialog
          company={editing}
          year={year}
          month={month}
          onClose={() => setEditing(null)}
          onSaved={() => q.refetch()}
        />
      )}
    </div>
  );
}

function MetricCard({
  label,
  value,
  delta,
  goodWhenUp,
  hint,
  info,
  rag,
}: {
  label: string;
  value: string;
  delta?: number | null;
  goodWhenUp?: boolean;
  hint?: string;
  info?: string;
  rag?: string;
}) {
  return (
    <Card className="p-4">
      <div className="flex items-center gap-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">
        {label}
        {info && <InfoHint text={info} />}
      </div>
      <div className={`mt-1 text-2xl font-bold ${rag ?? "text-foreground"}`}>{value}</div>
      <div className="mt-0.5 flex items-center gap-1 text-xs">
        {delta === undefined ? null : <DeltaBadge delta={delta} goodWhenUp={goodWhenUp ?? true} />}
        {hint && <span className="text-muted-foreground">{hint}</span>}
      </div>
    </Card>
  );
}

function DeltaBadge({ delta, goodWhenUp }: { delta: number | null; goodWhenUp: boolean }) {
  if (delta === null) return <span className="text-muted-foreground">— vs last mo</span>;
  const up = delta > 0;
  const flat = delta === 0;
  const good = flat ? true : up === goodWhenUp;
  const Icon = flat ? Minus : up ? ArrowUp : ArrowDown;
  return (
    <span className={`inline-flex items-center gap-0.5 font-medium ${good ? "text-success" : "text-destructive"}`}>
      <Icon className="size-3" />
      {Math.abs(delta)}%
    </span>
  );
}

function BudgetCard({ overall }: { overall: ExecMetrics }) {
  const used = overall.budgetUsedPct;
  const rag =
    used === null ? "text-foreground" : used > 110 ? "text-destructive" : used > 100 ? "text-warning" : "text-success";
  return (
    <Card className="p-4">
      <div className="flex items-center gap-1 text-xs font-medium uppercase tracking-wide text-muted-foreground">
        <Wallet className="size-3.5" /> Budget Used
        <InfoHint text="Ad spend as a % of the planned budget for the month (spend ÷ budget). Amber = over 100%, red = over 110% (over budget)." />
      </div>
      <div className={`mt-1 text-2xl font-bold ${rag}`}>{used === null ? "—" : `${used}%`}</div>
      <div className="mt-0.5 text-xs text-muted-foreground">
        {rm(overall.adSpend)} / {rm(overall.budget)}
        {overall.overBudget && <span className="ml-1 font-medium text-destructive">over budget</span>}
      </div>
    </Card>
  );
}

function FunnelStage({ label, value, highlight }: { label: string; value: number; highlight?: boolean }) {
  return (
    <div
      className={`flex-1 rounded-md border p-3 text-center ${
        highlight ? "border-primary bg-primary/5" : "border-border"
      }`}
    >
      <div className="text-2xl font-bold">{value.toLocaleString()}</div>
      <div className="text-xs text-muted-foreground">{label}</div>
    </div>
  );
}

function FunnelArrow({ conv }: { conv: number | null }) {
  return (
    <div className="flex flex-col items-center px-1 text-muted-foreground">
      <span className="text-[11px]">{conv === null ? "—" : `${conv}%`}</span>
      <span className="text-lg leading-none">→</span>
    </div>
  );
}

function FinancialsDialog({
  company,
  year,
  month,
  onClose,
  onSaved,
}: {
  company: ExecCompanyRow | null;
  year: number;
  month: number;
  onClose: () => void;
  onSaved: () => void;
}) {
  const [form, setForm] = React.useState(() => initFin(company));
  const [error, setError] = React.useState("");

  React.useEffect(() => {
    setForm(initFin(company));
    setError("");
  }, [company]);

  const save = useMutation({
    mutationFn: () =>
      apiSend(`/api/companies/${company!.id}/financials`, "POST", {
        year,
        month,
        budget: Number(form.budget) || 0,
        adSpend: Number(form.adSpend) || 0,
        revenue: Number(form.revenue) || 0,
        leads: Number(form.leads) || 0,
        trials: Number(form.trials) || 0,
        enrollments: Number(form.enrollments) || 0,
      }),
    onSuccess: () => {
      onSaved();
      onClose();
    },
    onError: (e) => setError(e instanceof Error ? e.message : "Failed to save"),
  });

  if (!company) return null;
  const fields: { key: keyof typeof form; label: string; money?: boolean }[] = [
    { key: "budget", label: "Budget (RM)", money: true },
    { key: "adSpend", label: "Ad spend (RM)", money: true },
    { key: "revenue", label: "Revenue (RM)", money: true },
    { key: "leads", label: "Leads" },
    { key: "trials", label: "Trials" },
    { key: "enrollments", label: "Enrollments" },
  ];
  return (
    <Dialog open={!!company} onClose={onClose}>
      <DialogHeader title={`${MONTHS[month - 1]} ${year} — ${company.name}`} onClose={onClose} />
      <DialogBody>
        <p className="text-xs text-muted-foreground">
          Enter the month&apos;s figures. ROAS, ROI, CAC, CPL and funnel rates are calculated for you.
        </p>
        <div className="grid grid-cols-2 gap-3">
          {fields.map((f) => (
            <div key={f.key} className="space-y-1.5">
              <Label>{f.label}</Label>
              <Input
                type="number"
                step={f.money ? "any" : "1"}
                min="0"
                value={form[f.key]}
                onChange={(e) => setForm({ ...form, [f.key]: e.target.value })}
              />
            </div>
          ))}
        </div>
        {error && <p className="text-sm text-destructive">{error}</p>}
      </DialogBody>
      <DialogFooter>
        <Button type="button" variant="secondary" onClick={onClose}>
          Cancel
        </Button>
        <Button type="button" disabled={save.isPending} onClick={() => save.mutate()}>
          Save figures
        </Button>
      </DialogFooter>
    </Dialog>
  );
}

function initFin(c: ExecCompanyRow | null) {
  return {
    budget: String(c?.budget ?? "0"),
    adSpend: String(c?.adSpend ?? "0"),
    revenue: String(c?.revenue ?? "0"),
    leads: String(c?.leads ?? "0"),
    trials: String(c?.trials ?? "0"),
    enrollments: String(c?.enrollments ?? "0"),
  };
}
