import { useMemo, useState } from 'react';
import { createFileRoute, Link } from '@tanstack/react-router';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useServerFn } from '@tanstack/react-start';
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, Tooltip, CartesianGrid } from 'recharts';
import { QRCodeSVG } from 'qrcode.react';
import { Copy, Check, Link2, MousePointerClick, Coins, Wallet, Loader2, LayoutDashboard, Settings, Receipt, Percent } from 'lucide-react';
import { toast } from 'sonner';
import { useAuthStore } from '@/stores/authStore';
import { getAffiliateDashboard, registerAffiliate, updateAffiliateSettings } from '@/lib/affiliate-dashboard.functions';
import { useT, useLang, headLang, localizePath, SITE_URL } from '@/lib/i18n';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

export const Route = createFileRoute('/my-account_/affiliate')({
  head: (ctx) => {
    const lang = headLang(ctx);
    const title = lang === 'en' ? 'Affiliate dashboard | Peptidewinkel' : 'Affiliate-dashboard | Peptidewinkel';
    const description = lang === 'en'
      ? 'Track your Peptidewinkel affiliate visits, commissions, earnings and links.'
      : 'Bekijk je Peptidewinkel-affiliatebezoeken, commissies, verdiensten en links.';
    const url = `${SITE_URL}${localizePath('/my-account/affiliate', lang)}`;
    return {
      meta: [
        { title },
        { name: 'description', content: description },
        { property: 'og:title', content: title },
        { property: 'og:description', content: description },
        { property: 'og:type', content: 'website' },
        { property: 'og:url', content: url },
        { name: 'twitter:card', content: 'summary' },
        { name: 'robots', content: 'noindex, nofollow' },
      ],
    };
  },
  component: AffiliatePage,
});

const RANGES = [7, 30, 90, 0] as const;

function AffiliatePage() {
  const t = useT();
  const lang = useLang();
  const { isLoggedIn, wcToken } = useAuthStore();
  const fetchDash = useServerFn(getAffiliateDashboard);
  const q = useQuery({
    queryKey: ['affiliate-dashboard', wcToken],
    queryFn: () => fetchDash({ data: { wc_token: wcToken! } }),
    enabled: !!wcToken,
  });

  if (!isLoggedIn || !wcToken) {
    return (
      <Shell t={t}>
        <div className="glass-card rounded-3xl p-8 text-center">
          <p className="mb-4">{t('Log in om je affiliate-dashboard te bekijken.', 'Log in to view your affiliate dashboard.')}</p>
          <Link to="/my-account" className="inline-flex gradient-primary text-white font-bold px-6 py-3 rounded-xl text-sm">{t('Inloggen', 'Log in')}</Link>
        </div>
      </Shell>
    );
  }
  if (q.isLoading) return <Shell t={t}><div className="flex justify-center py-20"><Loader2 className="w-6 h-6 animate-spin text-primary" /></div></Shell>;
  if (q.isError || !q.data) {
    const msg = q.error instanceof Error ? q.error.message : '';
    const expired = /log opnieuw in/i.test(msg);
    return (
      <Shell t={t}>
        <div className="glass-card rounded-3xl p-8 text-center">
          <p className="mb-4">{expired
            ? t('Je sessie is verlopen. Log opnieuw in om je affiliate-dashboard te bekijken.', 'Your session has expired. Please log in again to view your affiliate dashboard.')
            : t('Gegevens konden niet geladen worden. Probeer het later opnieuw.', 'Could not load data. Please try again later.')}</p>
          {expired ? (
            <Link to="/my-account" onClick={() => useAuthStore.getState().logout()} className="inline-flex gradient-primary text-white font-bold px-6 py-3 rounded-xl text-sm">{t('Opnieuw inloggen', 'Log in again')}</Link>
          ) : (
            <Button onClick={() => q.refetch()}>{t('Opnieuw proberen', 'Try again')}</Button>
          )}
        </div>
      </Shell>
    );
  }
  if (!q.data.affiliate) return <Shell t={t}><RegisterForm t={t} token={wcToken} /></Shell>;

  return <Shell t={t}><Dashboard t={t} lang={lang} data={q.data as Dash} token={wcToken} /></Shell>;
}

type T = ReturnType<typeof useT>;
type Dash = Exclude<Awaited<ReturnType<typeof getAffiliateDashboard>>, { affiliate: null }>;

function Shell({ t, children }: { t: T; children: React.ReactNode }) {
  return (
    <div className="min-h-screen account-hero">
      <div className="border-b border-border/40">
        <div className="container py-6 md:py-10">
          <Link to="/my-account" className="text-xs uppercase tracking-[0.18em] text-primary font-bold">← {t('Mijn Account', 'My Account')}</Link>
          <h1 className="text-3xl md:text-4xl font-black tracking-tight mt-1.5">{t('Affiliate-dashboard', 'Affiliate dashboard')}</h1>
        </div>
      </div>
      <div className="container py-8 md:py-12">{children}</div>
    </div>
  );
}

const eur = (n: number, lang: string) => new Intl.NumberFormat(lang === 'en' ? 'en-IE' : 'nl-NL', { style: 'currency', currency: 'EUR' }).format(n);
const fmtDate = (s: string, lang: string) => new Date(s.replace(' ', 'T')).toLocaleDateString(lang === 'en' ? 'en-GB' : 'nl-NL', { day: 'numeric', month: 'short', year: 'numeric' });

function Stat({ icon: Icon, label, value, sub }: { icon: typeof Coins; label: string; value: string; sub?: string }) {
  return (
    <div className="glass-card rounded-2xl p-5">
      <div className="flex items-center gap-2 text-muted-foreground text-xs font-semibold uppercase tracking-wider"><Icon className="w-4 h-4 text-primary" />{label}</div>
      <p className="text-2xl md:text-3xl font-black mt-2">{value}</p>
      {sub && <p className="text-xs text-muted-foreground mt-1">{sub}</p>}
    </div>
  );
}

function CopyBtn({ text }: { text: string }) {
  const [ok, setOk] = useState(false);
  return (
    <Button size="sm" variant="outline" onClick={() => { navigator.clipboard.writeText(text); setOk(true); setTimeout(() => setOk(false), 1500); }}>
      {ok ? <Check className="w-4 h-4" /> : <Copy className="w-4 h-4" />}
    </Button>
  );
}

function Dashboard({ t, lang, data, token }: { t: T; lang: string; data: Dash; token: string }) {
  const [range, setRange] = useState<(typeof RANGES)[number]>(30);
  const a = data.affiliate;

  const { stats, series } = useMemo(() => {
    const now = new Date();
    const start = range ? new Date(now.getTime() - (range - 1) * 86400000) : null;
    const inRange = (d: string) => !start || d.slice(0, 10) >= start.toISOString().slice(0, 10);
    const vs = data.visits.filter((v) => inRange(v.date));
    const cs = data.commissions.filter((c) => c.status !== 'rejected' && inRange(c.date));
    const days = range || 90;
    const weekly = days > 31;
    const buckets = new Map<string, { label: string; visits: number; commissions: number; earnings: number }>();
    const s0 = start ?? new Date(now.getTime() - 89 * 86400000);
    for (let d = new Date(s0); d <= now; d = new Date(d.getTime() + 86400000)) {
      const k = bucketKey(d, weekly);
      if (!buckets.has(k)) buckets.set(k, { label: d.toLocaleDateString(lang === 'en' ? 'en-GB' : 'nl-NL', { day: 'numeric', month: 'short' }), visits: 0, commissions: 0, earnings: 0 });
    }
    for (const v of vs) { const b = buckets.get(bucketKey(new Date(v.date.replace(' ', 'T')), weekly)); if (b) b.visits++; }
    for (const c of cs) { const b = buckets.get(bucketKey(new Date(c.date.replace(' ', 'T')), weekly)); if (b) { b.commissions++; b.earnings += c.amount; } }
    const earnings = cs.reduce((s, c) => s + c.amount, 0);
    return {
      stats: { visits: vs.length, commissions: cs.length, earnings, conv: vs.length ? (cs.filter((c) => c.type === 'sale').length / vs.length) * 100 : 0 },
      series: [...buckets.values()].map((b) => ({ ...b, earnings: Math.round(b.earnings * 100) / 100 })),
    };
  }, [data, range, lang]);

  return (
    <div className="space-y-6">
      {a.status !== 'active' && (
        <div className="glass-card rounded-2xl p-4 text-sm">
          {t('Je aanmelding wordt beoordeeld. Je ontvangt bericht zodra je account actief is.', 'Your application is being reviewed. You will be notified once your account is active.')} ({a.status})
        </div>
      )}
      <Tabs defaultValue="dashboard">
        <TabsList className="flex-wrap h-auto">
          <TabsTrigger value="dashboard"><LayoutDashboard className="w-4 h-4 mr-1.5" />Dashboard</TabsTrigger>
          <TabsTrigger value="links"><Link2 className="w-4 h-4 mr-1.5" />{t('Links', 'Links')}</TabsTrigger>
          <TabsTrigger value="commissions"><Coins className="w-4 h-4 mr-1.5" />{t('Commissies', 'Commissions')}</TabsTrigger>
          <TabsTrigger value="visits"><MousePointerClick className="w-4 h-4 mr-1.5" />{t('Bezoeken', 'Visits')}</TabsTrigger>
          <TabsTrigger value="payouts"><Receipt className="w-4 h-4 mr-1.5" />{t('Uitbetalingen', 'Payouts')}</TabsTrigger>
          <TabsTrigger value="settings"><Settings className="w-4 h-4 mr-1.5" />{t('Instellingen', 'Settings')}</TabsTrigger>
        </TabsList>

        <TabsContent value="dashboard" className="space-y-6 mt-6">
          <div className="flex flex-wrap gap-2">
            {RANGES.map((r) => (
              <button key={r} onClick={() => setRange(r)} className={`px-4 py-2 rounded-full text-xs font-bold ${range === r ? 'gradient-primary text-white' : 'glass-panel text-muted-foreground'}`}>
                {r ? t(`Afgelopen ${r} dagen`, `Last ${r} days`) : t('Alle tijd', 'All time')}
              </button>
            ))}
          </div>
          <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
            <Stat icon={MousePointerClick} label={t('Bezoeken', 'Visits')} value={String(stats.visits)} />
            <Stat icon={Coins} label={t('Commissies', 'Commissions')} value={String(stats.commissions)} />
            <Stat icon={Wallet} label={t('Verdiensten', 'Earnings')} value={eur(stats.earnings, lang)} />
            <Stat icon={Percent} label={t('Conversie', 'Conversion')} value={`${stats.conv.toFixed(1)}%`} sub={t('verkopen / bezoeken', 'sales / visits')} />
          </div>
          <div className="glass-card rounded-2xl p-5 h-80">
            <ResponsiveContainer width="100%" height="100%">
              <LineChart data={series}>
                <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
                <XAxis dataKey="label" fontSize={11} stroke="hsl(var(--muted-foreground))" />
                <YAxis yAxisId="l" fontSize={11} allowDecimals={false} stroke="hsl(var(--muted-foreground))" />
                <YAxis yAxisId="r" orientation="right" fontSize={11} stroke="hsl(var(--muted-foreground))" />
                <Tooltip contentStyle={{ background: 'hsl(var(--card))', border: '1px solid hsl(var(--border))', borderRadius: 12 }} />
                <Line yAxisId="l" type="monotone" dataKey="visits" name={t('Bezoeken', 'Visits')} stroke="hsl(var(--primary))" strokeWidth={2} dot={false} />
                <Line yAxisId="l" type="monotone" dataKey="commissions" name={t('Commissies', 'Commissions')} stroke="hsl(var(--muted-foreground))" strokeWidth={2} dot={false} />
                <Line yAxisId="r" type="monotone" dataKey="earnings" name={t('Verdiensten (€)', 'Earnings (€)')} stroke="hsl(var(--accent-foreground))" strokeWidth={2} dot={false} />
              </LineChart>
            </ResponsiveContainer>
          </div>
          <h2 className="text-lg font-black">{t('Alle tijd', 'All time')}</h2>
          <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
            <Stat icon={MousePointerClick} label={t('Bezoeken', 'Visits')} value={String(data.allTime.visits)} />
            <Stat icon={Coins} label={t('Commissies', 'Commissions')} value={String(data.allTime.commissions)} />
            <Stat icon={Wallet} label={t('Betaald', 'Paid')} value={eur(data.allTime.paid, lang)} />
            <Stat icon={Wallet} label={t('Nog te betalen', 'Unpaid')} value={eur(data.allTime.unpaid, lang)} />
          </div>
          {data.topPages.length > 0 && (
            <div className="glass-card rounded-2xl p-5">
              <h2 className="font-black mb-3">{t('Best presterende pagina’s', 'Top landing pages')}</h2>
              <table className="w-full text-sm">
                <thead className="text-muted-foreground text-xs"><tr><th className="text-left py-1">{t('Pagina', 'Page')}</th><th className="text-right">{t('Bezoeken', 'Visits')}</th><th className="text-right">{t('Conversies', 'Conversions')}</th></tr></thead>
                <tbody>{data.topPages.map((p) => <tr key={p.page} className="border-t border-border/40"><td className="py-2 truncate max-w-[200px]">{p.page}</td><td className="text-right">{p.visits}</td><td className="text-right">{p.conversions}</td></tr>)}</tbody>
              </table>
            </div>
          )}
          {(() => {
            const r = data.rates;
            const fmt = (x: NonNullable<typeof r.sale>) => x.type === 'fixed' ? `€${x.rate.toFixed(2)}` : `${x.rate}%`;
            return (
              <div className="space-y-1 text-xs text-muted-foreground">
                {r.sale && <p>{t('Commissie op verkopen', 'Commission on sales')}: <span className="font-semibold text-foreground">{fmt(r.sale)}</span></p>}
                {r.recurring && r.recurring.rate > 0 && <p>{t('Doorlopende commissie', 'Recurring commission')}: <span className="font-semibold text-foreground">{fmt(r.recurring)}</span></p>}
                <p>{t(`Cookieduur: ${r.cookieDays} dagen (laatste klik telt).`, `Cookie duration: ${r.cookieDays} days (last click wins).`)}</p>
              </div>
            );
          })()}
        </TabsContent>

        <TabsContent value="links" className="mt-6"><LinksTab t={t} slug={a.slug} link={a.link} /></TabsContent>

        <TabsContent value="commissions" className="mt-6">
          <ListTable empty={t('Nog geen commissies.', 'No commissions yet.')} head={[t('Datum', 'Date'), t('Bestelling', 'Order'), 'Status', t('Bedrag', 'Amount')]}
            rows={data.commissions.map((c) => [fmtDate(c.date, lang), `#${c.order}${c.type === 'inherit' ? ` (${t('sub-affiliate', 'sub-affiliate')})` : ''}`, statusLabel(c.status, t), eur(c.amount, lang)])} />
        </TabsContent>
        <TabsContent value="visits" className="mt-6">
          <ListTable empty={t('Nog geen bezoeken.', 'No visits yet.')} head={[t('Datum', 'Date'), t('Landingspagina', 'Landing page'), t('Bestelling?', 'Ordered?')]}
            rows={data.visits.map((v) => [fmtDate(v.date, lang), v.landing, v.converted ? t('Ja', 'Yes') : '—'])} />
        </TabsContent>
        <TabsContent value="payouts" className="mt-6">
          <ListTable empty={t('Nog geen uitbetalingen.', 'No payouts yet.')} head={[t('Datum', 'Date'), t('Methode', 'Method'), 'Status', t('Bedrag', 'Amount')]}
            rows={data.payments.map((p) => [fmtDate(p.date, lang), p.method || '—', statusLabel(p.status, t), eur(p.amount, lang)])} />
        </TabsContent>
        <TabsContent value="settings" className="mt-6"><SettingsForm t={t} token={token} email={a.payment_email} website={a.website} /></TabsContent>
      </Tabs>
    </div>
  );
}

function bucketKey(d: Date, weekly: boolean) {
  if (!weekly) return d.toISOString().slice(0, 10);
  const m = new Date(d); m.setUTCDate(m.getUTCDate() - ((m.getUTCDay() + 6) % 7));
  return m.toISOString().slice(0, 10);
}

function statusLabel(s: string, t: T) {
  const map: Record<string, [string, string]> = {
    unpaid: ['Openstaand', 'Unpaid'], paid: ['Betaald', 'Paid'], pending: ['In behandeling', 'Pending'],
    rejected: ['Afgewezen', 'Rejected'], requested: ['Aangevraagd', 'Requested'], failed: ['Mislukt', 'Failed'],
  };
  const m = map[s];
  return m ? t(m[0], m[1]) : s;
}

function ListTable({ head, rows, empty }: { head: string[]; rows: string[][]; empty: string }) {
  if (!rows.length) return <div className="glass-card rounded-2xl p-6 text-sm text-muted-foreground">{empty}</div>;
  return (
    <div className="glass-card rounded-2xl p-2 overflow-x-auto">
      <table className="w-full text-sm">
        <thead className="text-xs text-muted-foreground"><tr>{head.map((h, i) => <th key={h} className={`px-3 py-2 ${i === head.length - 1 ? 'text-right' : 'text-left'}`}>{h}</th>)}</tr></thead>
        <tbody>{rows.map((r, i) => <tr key={i} className="border-t border-border/40">{r.map((c, j) => <td key={j} className={`px-3 py-2 ${j === r.length - 1 ? 'text-right font-semibold' : ''}`}>{c}</td>)}</tr>)}</tbody>
      </table>
    </div>
  );
}

function LinksTab({ t, slug, link }: { t: T; slug: string; link: string }) {
  const [page, setPage] = useState('');
  const built = useMemo(() => {
    let p = page.trim();
    try { if (p.startsWith('http')) p = new URL(p).pathname; } catch { p = ''; }
    if (p && !p.startsWith('/')) p = '/' + p;
    return `https://peptidewinkel.com${p || '/'}?aff=${encodeURIComponent(slug)}`;
  }, [page, slug]);
  const quick = [['/shop', t('Webshop', 'Shop')], ['/product-category/stacks-kits', t('Bundels', 'Bundles')], ['/labtesten', t('Labtesten', 'Lab tests')]];
  return (
    <div className="grid md:grid-cols-2 gap-6">
      <div className="glass-card rounded-2xl p-5 space-y-3">
        <h2 className="font-black">{t('Je persoonlijke link', 'Your personal link')}</h2>
        <div className="flex gap-2"><Input readOnly value={link} /><CopyBtn text={link} /></div>
        <div className="bg-white p-3 rounded-xl w-fit"><QRCodeSVG value={link} size={140} /></div>
      </div>
      <div className="glass-card rounded-2xl p-5 space-y-3">
        <h2 className="font-black">{t('Link naar een specifieke pagina', 'Link to a specific page')}</h2>
        <Input placeholder={t('Plak een product- of pagina-URL van peptidewinkel.com', 'Paste a product or page URL from peptidewinkel.com')} value={page} onChange={(e) => setPage(e.target.value.slice(0, 300))} />
        <div className="flex flex-wrap gap-2">{quick.map(([p, l]) => <button key={p} onClick={() => setPage(p)} className="glass-panel text-xs font-bold px-3 py-1.5 rounded-full">{l}</button>)}</div>
        <div className="flex gap-2"><Input readOnly value={built} /><CopyBtn text={built} /></div>
        <div className="bg-white p-3 rounded-xl w-fit"><QRCodeSVG value={built} size={140} /></div>
      </div>
    </div>
  );
}

function useAffForm(initialEmail: string, initialSite: string) {
  const [email, setEmail] = useState(initialEmail);
  const [website, setWebsite] = useState(initialSite);
  const [busy, setBusy] = useState(false);
  return { email, setEmail, website, setWebsite, busy, setBusy };
}

function SettingsForm({ t, token, email, website }: { t: T; token: string; email: string; website: string }) {
  const f = useAffForm(email, website);
  const save = useServerFn(updateAffiliateSettings);
  const qc = useQueryClient();
  return (
    <form className="glass-card rounded-2xl p-5 space-y-4 max-w-lg" onSubmit={async (e) => {
      e.preventDefault(); f.setBusy(true);
      try { await save({ data: { wc_token: token, payment_email: f.email, website: f.website } }); toast.success(t('Opgeslagen', 'Saved')); qc.invalidateQueries({ queryKey: ['affiliate-dashboard'] }); }
      catch { toast.error(t('Controleer je gegevens en probeer opnieuw.', 'Check your details and try again.')); }
      finally { f.setBusy(false); }
    }}>
      <label className="block text-sm font-semibold">{t('E-mailadres voor uitbetaling (PayPal)', 'Payout email (PayPal)')}<Input type="email" required maxLength={254} value={f.email} onChange={(e) => f.setEmail(e.target.value)} className="mt-1" /></label>
      <label className="block text-sm font-semibold">{t('Website of social-profiel', 'Website or social profile')}<Input type="url" maxLength={300} placeholder="https://" value={f.website} onChange={(e) => f.setWebsite(e.target.value)} className="mt-1" /></label>
      <Button type="submit" disabled={f.busy}>{f.busy && <Loader2 className="w-4 h-4 animate-spin mr-2" />}{t('Opslaan', 'Save')}</Button>
    </form>
  );
}

function RegisterForm({ t, token }: { t: T; token: string }) {
  const customer = useAuthStore((s) => s.customer);
  const f = useAffForm(customer?.email || '', '');
  const reg = useServerFn(registerAffiliate);
  const qc = useQueryClient();
  return (
    <form className="glass-card rounded-3xl p-6 md:p-8 space-y-4 max-w-xl" onSubmit={async (e) => {
      e.preventDefault(); f.setBusy(true);
      try { await reg({ data: { wc_token: token, payment_email: f.email, website: f.website } }); toast.success(t('Aanmelding ontvangen!', 'Application received!')); qc.invalidateQueries({ queryKey: ['affiliate-dashboard'] }); }
      catch { toast.error(t('Aanmelden mislukt, controleer je gegevens.', 'Sign-up failed, check your details.')); }
      finally { f.setBusy(false); }
    }}>
      <h2 className="text-xl font-black">{t('Word affiliate', 'Become an affiliate')}</h2>
      <p className="text-sm text-muted-foreground">{t('Verdien commissie op bestellingen via jouw persoonlijke link. Na beoordeling krijg je toegang tot je dashboard.', 'Earn commission on orders placed through your personal link. After review you get access to your dashboard.')}</p>
      <label className="block text-sm font-semibold">{t('E-mailadres voor uitbetaling (PayPal)', 'Payout email (PayPal)')}<Input type="email" required maxLength={254} value={f.email} onChange={(e) => f.setEmail(e.target.value)} className="mt-1" /></label>
      <label className="block text-sm font-semibold">{t('Website of social-profiel', 'Website or social profile')}<Input type="url" maxLength={300} placeholder="https://" value={f.website} onChange={(e) => f.setWebsite(e.target.value)} className="mt-1" /></label>
      <Button type="submit" disabled={f.busy}>{f.busy && <Loader2 className="w-4 h-4 animate-spin mr-2" />}{t('Aanmelden', 'Apply')}</Button>
    </form>
  );
}
