"use client";

import { useEffect, useMemo, useState } from "react";
import { BarChart3, CalendarDays, Copy, Loader2, WalletCards } from "lucide-react";
import { AffiliationMobileDock, AffiliationSidebar, AffiliatePanel, StatusPill } from "@/components/affiliation/affiliation-ui";
import { formatMoney } from "@/lib/utils";

type DashboardPayload = {
  account: { displayName: string; publicId: string; status: string; createdAt: string };
  range: { label: string; start: string; end: string };
  offer: Offer | null;
  links: LinkItem[];
  stats: {
    clicks: number;
    registrations: number;
    rejectedGeo: number;
    ftd: number;
    qualifiedCpa: number;
    deposits: string;
    commission: string;
    payable: string;
  };
  chart: Array<{ date: string; amount: number }>;
  activityChart: Array<{ date: string; clicks: number; registrations: number; ftd: number; cpa: number; rejectedGeo: number }>;
  countries: Array<{ country: string; count: number }>;
  recentReferrals: Array<{
    id: string;
    email: string | null;
    country: string | null;
    registeredAt: string;
    firstDepositAt: string | null;
    cpaQualifiedAt: string | null;
    depositTotal: string;
    rewardEligible: boolean;
    rejectionReason: string | null;
    link: { id: string; label: string; code: string } | null;
  }>;
  payouts: Array<{ id: string; amount: string; currency: string; status: string; periodStart: string; periodEnd: string }>;
  nextPayoutWindow: { start: string; end: string };
};

type Offer = {
  code: string;
  name: string;
  type: string;
  cpaAmount: string | null;
  revenueShareBps: number | null;
  hybridCpaAmount: string | null;
  hybridRevenueShareBps: number | null;
};

type LinkItem = {
  id: string;
  code: string;
  label: string;
  landingPath: string;
  status: string;
  rewardType: "CPA" | "RS" | "HYBRID";
  cpaAmount: string | null;
  revenueShareBps: number | null;
  minCpaDepositAmount: string;
  cpaValidationMode: "FIRST_DEPOSIT" | "CUMULATIVE_DEPOSIT";
  cpaWindowDays: number | null;
  allowedCountries: string[];
  terms: string | null;
  url: string;
  stats: { clicks: number; registrations: number };
  offer: Offer | null;
};

const presets = [
  ["today", "Aujourd'hui"],
  ["yesterday", "Hier"],
  ["7d", "7 jours"],
  ["30d", "30 jours"],
  ["month", "Mois"]
];

export function AffiliateDashboard() {
  const [data, setData] = useState<DashboardPayload | null>(null);
  const [message, setMessage] = useState("");
  const [loading, setLoading] = useState(true);
  const [preset, setPreset] = useState("30d");
  const [from, setFrom] = useState("");
  const [to, setTo] = useState("");
  const origin = typeof window === "undefined" ? "" : window.location.origin;

  useEffect(() => {
    void load();
  }, []);

  async function load(nextPreset = preset, nextFrom = from, nextTo = to) {
    setLoading(true);
    setMessage("");
    const params = new URLSearchParams();
    if (nextFrom || nextTo) {
      if (nextFrom) params.set("from", nextFrom);
      if (nextTo) params.set("to", nextTo);
    } else {
      params.set("preset", nextPreset);
    }
    const response = await fetch(`/api/affiliation/me?${params.toString()}`, { cache: "no-store" });
    const payload = await response.json();
    setLoading(false);
    if (!payload.ok) {
      setMessage(payload.error?.message ?? "Impossible de charger le dashboard");
      return;
    }
    setData(payload.data);
  }

  async function requestPayout() {
    setMessage("");
    const response = await fetch("/api/affiliation/payouts/request", { method: "POST" });
    const payload = await response.json();
    if (!payload.ok) {
      setMessage(payload.error?.message ?? "Demande de paiement impossible");
      return;
    }
    setMessage("Demande de paiement envoyée.");
    await load();
  }

  const commissionPath = useMemo(() => buildPath(data?.chart ?? []), [data?.chart]);
  const inPayoutWindow = data ? isNowInWindow(data.nextPayoutWindow.start, data.nextPayoutWindow.end) : false;

  if (loading && !data) {
    return <div className="grid min-h-screen place-items-center bg-[#020910] text-felt"><Loader2 className="h-6 w-6 animate-spin" /></div>;
  }

  return (
    <div className="flex min-h-screen bg-[#020910] pb-20 text-white md:pb-0">
      <AffiliationSidebar />
      <main className="mx-auto w-full max-w-[1120px] space-y-3 p-3 md:p-4">
        <header className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
          <div>
            <div className="text-[11px] font-bold uppercase text-felt">Dashboard affilié</div>
            <h1 className="text-xl font-extrabold text-white">Vue d'ensemble</h1>
            {data ? <p className="mt-1 text-[11px] font-semibold text-slate-500">{dateText(data.range.start)} - {dateText(data.range.end)}</p> : null}
          </div>
          <div className="grid gap-2 sm:grid-cols-[150px_1fr_1fr_auto]">
            <select
              value={preset}
              onChange={(event) => {
                setPreset(event.target.value);
                setFrom("");
                setTo("");
                void load(event.target.value, "", "");
              }}
              className="h-9 rounded-lg border border-white/10 bg-white/[0.06] px-2 text-xs font-bold text-white"
            >
              {presets.map(([value, label]) => <option key={value} value={value}>{label}</option>)}
            </select>
            <input type="date" value={from} onChange={(event) => setFrom(event.target.value)} className="h-9 rounded-lg border border-white/10 bg-white/[0.06] px-2 text-xs font-bold text-white" />
            <input type="date" value={to} onChange={(event) => setTo(event.target.value)} className="h-9 rounded-lg border border-white/10 bg-white/[0.06] px-2 text-xs font-bold text-white" />
            <button onClick={() => void load()} className="flex h-9 items-center justify-center gap-2 rounded-lg bg-felt px-3 text-xs font-black text-ink-950">
              <CalendarDays className="h-3.5 w-3.5" />
              Appliquer
            </button>
          </div>
        </header>

        {message ? <div className="rounded-lg border border-gold/25 bg-gold/10 p-2 text-xs font-semibold text-gold">{message}</div> : null}

        <div className="grid gap-2 sm:grid-cols-2 lg:grid-cols-4 xl:grid-cols-8">
          <Metric label="Clics" value={data?.stats.clicks ?? 0} />
          <Metric label="Inscrits valides" value={data?.stats.registrations ?? 0} />
          <Metric label="GEO refusés" value={data?.stats.rejectedGeo ?? 0} tone="gold" />
          <Metric label="FTD" value={data?.stats.ftd ?? 0} />
          <Metric label="CPA validés" value={data?.stats.qualifiedCpa ?? 0} />
          <Metric label="Dépôts" value={formatMoney(data?.stats.deposits ?? "0")} />
          <Metric label="Commissions" value={formatMoney(data?.stats.commission ?? "0")} tone="felt" />
          <Metric label="Payable" value={formatMoney(data?.stats.payable ?? "0")} tone="felt" />
        </div>

        <div className="grid gap-3 xl:grid-cols-[1.2fr_0.8fr]">
          <AffiliatePanel className="p-3" id="stats">
            <div className="flex items-center justify-between">
              <h2 className="text-sm font-bold text-white">Activité joueurs</h2>
              <span className="text-[11px] font-semibold text-slate-500">{data?.range.label}</span>
            </div>
            <ActivityBars rows={data?.activityChart ?? []} />
          </AffiliatePanel>

          <AffiliatePanel className="p-3">
            <div className="flex items-center justify-between">
              <h2 className="text-sm font-bold text-white">Commissions</h2>
              <BarChart3 className="h-4 w-4 text-felt" />
            </div>
            {data?.chart.some((item) => item.amount > 0) ? (
              <svg viewBox="0 0 320 120" className="mt-3 h-36 w-full">
                <path d={commissionPath.area} fill="rgba(15,191,143,.16)" />
                <path d={commissionPath.line} fill="none" stroke="#10e0bd" strokeWidth="2" />
              </svg>
            ) : (
              <Empty text="Aucune commission enregistrée sur la période." />
            )}
          </AffiliatePanel>
        </div>

        <AffiliatePanel className="p-3" id="liens">
          <div className="flex items-center justify-between gap-3">
            <div>
              <h2 className="text-sm font-bold text-white">Media items / liens</h2>
              <p className="mt-1 text-[11px] text-slate-500">Les liens sont créés et configurés par l'administration.</p>
            </div>
            <span className="text-[11px] font-semibold text-slate-500">{data?.links.length ?? 0}</span>
          </div>
          <div className="mt-3 overflow-x-auto">
            <div className="min-w-[880px] space-y-2">
              {data?.links.length ? (
                data.links.map((link) => (
                  <div key={link.id} className="grid grid-cols-[1.1fr_1.2fr_1fr_0.8fr_auto] items-center gap-2 rounded-lg bg-white/[0.035] p-2 text-xs">
                    <div className="min-w-0">
                      <div className="font-bold text-white">{link.label}</div>
                      <div className="text-[11px] text-slate-500">ID {link.code} · {statusLabel(link.status)}</div>
                    </div>
                    <div className="min-w-0">
                      <div className="truncate rounded-md bg-felt/10 px-2 py-1 text-[11px] font-semibold text-felt">{origin}{link.url}</div>
                    </div>
                    <div>
                      <div className="font-bold text-white">{dealText(link)}</div>
                      <div className="text-[11px] text-slate-500">{conditionText(link)}</div>
                    </div>
                    <div>
                      <GeoPills countries={link.allowedCountries} />
                    </div>
                    <div className="flex items-center gap-2">
                      <div className="text-right text-[11px] text-slate-500">
                        <div>{link.stats.clicks} clics</div>
                        <div>{link.stats.registrations} inscrits</div>
                      </div>
                      <button onClick={() => navigator.clipboard.writeText(`${origin}${link.url}`)} className="flex h-8 items-center justify-center gap-1 rounded-lg border border-white/10 px-2 text-[11px] font-bold text-slate-200">
                        <Copy className="h-3.5 w-3.5" />
                        Copier
                      </button>
                    </div>
                  </div>
                ))
              ) : (
                <Empty text="Aucun lien actif. Contactez votre manager affiliation." />
              )}
            </div>
          </div>
        </AffiliatePanel>

        <div className="grid gap-3 xl:grid-cols-[1.15fr_0.85fr]">
          <AffiliatePanel className="p-3">
            <h2 className="text-sm font-bold text-white">Customer activities</h2>
            <div className="mt-3 space-y-2">
              {data?.recentReferrals.length ? (
                data.recentReferrals.map((referral) => (
                  <div key={referral.id} className="grid gap-2 rounded-lg bg-white/[0.035] p-2 text-xs sm:grid-cols-[1fr_auto_auto] sm:items-center">
                    <div className="min-w-0">
                      <div className="font-bold text-white">{referral.email ?? "Joueur inscrit"}</div>
                      <div className="truncate text-[11px] text-slate-500">{referral.link?.label ?? "Lien"} · {dateTime(referral.registeredAt)}</div>
                    </div>
                    <div className="flex flex-wrap gap-1">
                      <StatusPill label={referral.country ?? "N/A"} tone={referral.rewardEligible ? "felt" : "ember"} />
                      <StatusPill label={referral.cpaQualifiedAt ? "CPA validé" : referral.firstDepositAt ? "FTD" : "Inscrit"} tone={referral.cpaQualifiedAt ? "felt" : "slate"} />
                    </div>
                    <div className="text-right text-[11px] font-bold text-slate-300">{formatMoney(referral.depositTotal)}</div>
                  </div>
                ))
              ) : (
                <Empty text="Aucune activité joueur sur cette période." />
              )}
            </div>
          </AffiliatePanel>

          <AffiliatePanel className="p-3" id="paiements">
            <div className="flex items-center justify-between gap-3">
              <h2 className="text-sm font-bold text-white">Paiements</h2>
              <button onClick={() => void requestPayout()} disabled={!inPayoutWindow} className="h-8 rounded-lg bg-felt px-3 text-[11px] font-black text-ink-950 disabled:bg-white/[0.08] disabled:text-slate-500">
                Demander
              </button>
            </div>
            <p className="mt-2 text-[11px] leading-4 text-slate-500">
              Paiements mensuels entre le {dateTextUtc(data?.nextPayoutWindow.start)} et le {dateTextUtc(data?.nextPayoutWindow.end)}.
            </p>
            <div className="mt-3 space-y-2">
              {data?.payouts.length ? data.payouts.map((payout) => <Row key={payout.id} title={formatMoney(payout.amount, payout.currency)} meta={`${dateTextUtc(payout.periodStart)} - ${dateTextUtc(payout.periodEnd)}`} value={statusLabel(payout.status)} />) : <Empty text="Aucun paiement enregistré." />}
            </div>
          </AffiliatePanel>
        </div>
      </main>
      <AffiliationMobileDock />
    </div>
  );
}

function Metric({ label, value, tone = "slate" }: { label: string; value: string | number; tone?: "felt" | "gold" | "slate" }) {
  const color = tone === "felt" ? "text-felt" : tone === "gold" ? "text-gold" : "text-white";
  return (
    <AffiliatePanel className="p-2.5">
      <div className="text-[10px] font-bold uppercase text-slate-500">{label}</div>
      <div className={`mt-1 truncate text-base font-bold ${color}`}>{value}</div>
    </AffiliatePanel>
  );
}

function ActivityBars({ rows }: { rows: DashboardPayload["activityChart"] }) {
  const visibleRows = rows.slice(-14);
  const max = Math.max(...visibleRows.map((item) => Math.max(item.clicks, item.registrations, item.ftd, item.cpa, item.rejectedGeo)), 1);
  if (!rows.length) return <Empty text="Aucune donnée disponible." />;
  return (
    <div className="mt-3 flex h-44 items-end gap-1.5 overflow-hidden rounded-lg bg-white/[0.02] p-3">
      {visibleRows.map((item) => (
        <div key={item.date} className="flex min-w-0 flex-1 flex-col items-center gap-1">
          <div className="flex h-32 w-full items-end justify-center gap-0.5">
            <span className="w-1.5 rounded-t bg-slate-500" style={{ height: `${Math.max(4, (item.clicks / max) * 100)}%` }} />
            <span className="w-1.5 rounded-t bg-felt" style={{ height: `${Math.max(4, (item.registrations / max) * 100)}%` }} />
            <span className="w-1.5 rounded-t bg-gold" style={{ height: `${Math.max(4, (item.cpa / max) * 100)}%` }} />
          </div>
          <div className="truncate text-[9px] font-semibold text-slate-600">{item.date.slice(5)}</div>
        </div>
      ))}
    </div>
  );
}

function GeoPills({ countries }: { countries: string[] }) {
  if (!countries.length) return <span className="text-[11px] font-semibold text-slate-500">Tous pays</span>;
  return (
    <div className="flex flex-wrap gap-1">
      {countries.map((country) => (
        <span key={country} className="rounded-md bg-felt/10 px-1.5 py-0.5 text-[10px] font-black text-felt">{country}</span>
      ))}
    </div>
  );
}

function Row({ title, meta, value }: { title: string; meta: string; value: string }) {
  return (
    <div className="flex items-center justify-between gap-2 rounded-lg bg-white/[0.035] p-2">
      <div className="min-w-0">
        <div className="truncate text-xs font-bold text-white">{title}</div>
        <div className="truncate text-[11px] text-slate-500">{meta}</div>
      </div>
      <div className="text-xs font-bold text-felt">{value}</div>
    </div>
  );
}

function Empty({ text }: { text: string }) {
  return <div className="rounded-lg border border-dashed border-white/10 bg-white/[0.02] p-3 text-xs font-semibold text-slate-500">{text}</div>;
}

function dealText(link: LinkItem) {
  const cpa = link.cpaAmount ? formatMoney(link.cpaAmount) : null;
  const rs = link.revenueShareBps ? `${(link.revenueShareBps / 100).toFixed(0)}% RS` : null;
  if (link.rewardType === "CPA") return cpa ? `${cpa} CPA` : "CPA";
  if (link.rewardType === "RS") return rs ?? "RS";
  return [cpa ? `${cpa} CPA` : null, rs].filter(Boolean).join(" + ") || "Hybrid";
}

function conditionText(link: LinkItem) {
  const mode = link.cpaValidationMode === "CUMULATIVE_DEPOSIT" ? "cumul dépôts" : "1er dépôt";
  const window = link.cpaWindowDays ? ` · ${link.cpaWindowDays}j` : "";
  return `Min ${formatMoney(link.minCpaDepositAmount)} · ${mode}${window}`;
}

function statusLabel(status: string) {
  const labels: Record<string, string> = {
    active: "Actif",
    deactivated: "Désactivé",
    PENDING: "En attente",
    ACTIVE: "Actif",
    SUSPENDED: "Suspendu",
    CLOSED: "Fermé",
    REQUESTED: "Demandé",
    APPROVED: "Approuvé",
    PAID: "Payé",
    REJECTED: "Refusé",
    PAYABLE: "Payable"
  };
  return labels[status] ?? status;
}

function dateText(value?: string) {
  if (!value) return "-";
  return new Intl.DateTimeFormat("fr-FR", { day: "2-digit", month: "2-digit", year: "numeric" }).format(new Date(value));
}

function dateTextUtc(value?: string) {
  if (!value) return "-";
  return new Intl.DateTimeFormat("fr-FR", { day: "2-digit", month: "2-digit", year: "numeric", timeZone: "UTC" }).format(new Date(value));
}

function dateTime(value: string) {
  return new Intl.DateTimeFormat("fr-FR", { day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit" }).format(new Date(value));
}

function isNowInWindow(start: string, end: string) {
  const now = Date.now();
  return now >= new Date(start).getTime() && now <= new Date(end).getTime();
}

function buildPath(points: Array<{ amount: number }>) {
  if (!points.length) return { line: "", area: "" };
  const max = Math.max(...points.map((item) => item.amount), 1);
  const coords = points.map((item, index) => {
    const x = (index / Math.max(1, points.length - 1)) * 320;
    const y = 110 - (item.amount / max) * 90;
    return [x, y] as const;
  });
  const line = coords.map(([x, y], index) => `${index === 0 ? "M" : "L"}${x.toFixed(1)} ${y.toFixed(1)}`).join(" ");
  return { line, area: `${line} L320 120 L0 120 Z` };
}
