'use client';

import { useState, useEffect, useMemo } from 'react';
import { motion } from 'framer-motion';
import {
  Cpu, TrendingUp, FileText, Table2, Printer,
  BarChart3, Calendar,
} from 'lucide-react';
import {
  AreaChart, Area, ResponsiveContainer, XAxis, YAxis,
  Tooltip, CartesianGrid,
} from 'recharts';
import type { Project } from '../data/projectsData';
import { useSession } from '../lib/session-context';
import { getPlanCapabilities } from '../lib/plan-access';
import { estimateConversionTokens, eurFromTokens, formatEur } from '../lib/conversion-pricing';

/** Display helper: render an internal token amount as a € price (tokens never shown to users). */
function eur(tokens: number): string {
  return formatEur(eurFromTokens(tokens));
}

// ── helpers ─────────────────────────────────────────────────────────────────

function langLabel(id: string) {
  const map: Record<string, string> = {
    cobol: 'COBOL', java: 'Java', python: 'Python', csharp: 'C#',
    javascript: 'JS', typescript: 'TS', cpp: 'C++', fortran: 'Fortran',
    rpg: 'RPG', pl1: 'PL/I', ada: 'Ada', kotlin: 'Kotlin',
    scala: 'Scala', go: 'Go', rust: 'Rust', php: 'PHP',
    ruby: 'Ruby', swift: 'Swift', vb6: 'VB6', vbnet: 'VB.NET',
    assembler: 'Assembler', jcl: 'JCL', mumps: 'MUMPS', cics: 'CICS',
    natural: 'Natural', abap: 'ABAP', pascal: 'Pascal',
  };
  return map[id] ?? id;
}

function projectTokens(p: Project): number {
  return estimateConversionTokens({
    tokensUsed: (p as any).tokensUsed,
    totalLines: p.totalLines,
    sourceLanguage: p.sourceLanguage,
    estimatedLOC: (p.config as any)?.estimatedLOC,
  });
}

function buildHistory(projects: Project[], period: 'daily' | 'weekly' | 'monthly' | 'annual') {
  const now = new Date();
  const configs = {
    daily:   { count: 30,  labelFn: (i: number) => { const d = new Date(); d.setDate(d.getDate() - (29 - i)); return d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short' }); } },
    weekly:  { count: 12,  labelFn: (i: number) => { const d = new Date(); d.setDate(d.getDate() - ((11 - i) * 7)); return `W${Math.ceil(d.getDate() / 7)}`; } },
    monthly: { count: 12,  labelFn: (i: number) => { const d = new Date(); d.setMonth(d.getMonth() - (11 - i)); return d.toLocaleDateString('en-GB', { month: 'short', year: '2-digit' }); } },
    annual:  { count: 5,   labelFn: (i: number) => String(new Date().getFullYear() - (4 - i)) },
  };
  const cfg = configs[period];

  // Create buckets for each period
  const buckets = Array.from({ length: cfg.count }, (_, i) => ({
    label: cfg.labelFn(i),
    tokens: 0,
  }));

  // Distribute project tokens based on creation date
  projects.forEach(p => {
    const tokens = projectTokens(p);
    if (tokens === 0) return;

    const created = new Date(p.createdAt);
    let bucketIndex = 0;

    if (period === 'daily') {
      const daysDiff = Math.floor((now.getTime() - created.getTime()) / (1000 * 60 * 60 * 24));
      bucketIndex = Math.max(0, Math.min(cfg.count - 1, 29 - daysDiff));
    } else if (period === 'monthly') {
      const monthsDiff = (now.getFullYear() - created.getFullYear()) * 12 + (now.getMonth() - created.getMonth());
      bucketIndex = Math.max(0, Math.min(cfg.count - 1, 11 - monthsDiff));
    } else if (period === 'annual') {
      const yearsDiff = now.getFullYear() - created.getFullYear();
      bucketIndex = Math.max(0, Math.min(cfg.count - 1, 4 - yearsDiff));
    } else if (period === 'weekly') {
      const weeksDiff = Math.floor((now.getTime() - created.getTime()) / (1000 * 60 * 60 * 24 * 7));
      bucketIndex = Math.max(0, Math.min(cfg.count - 1, 11 - weeksDiff));
    }

    buckets[bucketIndex].tokens += tokens;
  });

  return buckets;
}

// ── export utilities ─────────────────────────────────────────────────────────

function downloadBlob(content: string, filename: string, mimeType: string) {
  const blob = new Blob([content], { type: mimeType });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

function exportCSV(projects: Project[], sessionTokens: number) {
  const rows = [
    ['Conversion', 'Source Language', 'Target Language', 'Lines', 'Cost (EUR)'],
    ...projects.map(p => [
      p.name,
      langLabel(p.sourceLanguage),
      langLabel(p.targetLanguage),
      String(p.totalLines ?? 0),
      eur(projectTokens(p)),
    ]),
    [],
    ['Active spend', eur(sessionTokens)],
    ['Total spend', eur(projects.reduce((s, p) => s + projectTokens(p), 0))],
  ];
  const csv = rows.map(r => r.map(v => `"${v.replace(/"/g, '""')}"`).join(',')).join('\n');
  downloadBlob(csv, 'scriba-spend.csv', 'text/csv');
}

function exportExcel(projects: Project[], sessionTokens: number) {
  const total = projects.reduce((s, p) => s + projectTokens(p), 0);
  const headerRow = ['Conversion', 'Source Language', 'Target Language', 'Lines', 'Cost (EUR)'];
  const dataRows = projects.map(p => [
    p.name,
    langLabel(p.sourceLanguage),
    langLabel(p.targetLanguage),
    p.totalLines ?? 0,
    eur(projectTokens(p)),
  ]);

  const esc = (v: unknown) => String(v).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  const xmlRow = (cells: unknown[]) =>
    `<Row>${cells.map(c =>
      typeof c === 'number'
        ? `<Cell><Data ss:Type="Number">${c}</Data></Cell>`
        : `<Cell><Data ss:Type="String">${esc(c)}</Data></Cell>`
    ).join('')}</Row>`;

  const xml = `<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
  <Worksheet ss:Name="Spend">
    <Table>
      ${xmlRow(headerRow)}
      ${dataRows.map(xmlRow).join('\n      ')}
    </Table>
  </Worksheet>
  <Worksheet ss:Name="Summary">
    <Table>
      ${xmlRow(['Active spend', eur(sessionTokens)])}
      ${xmlRow(['Total spend', eur(total)])}
      ${xmlRow(['Conversions', projects.length])}
    </Table>
  </Worksheet>
</Workbook>`;
  downloadBlob(xml, 'scriba-spend.xls', 'application/vnd.ms-excel');
}

function exportPDF(projects: Project[], sessionTokens: number, tier: string) {
  const total = projects.reduce((s, p) => s + projectTokens(p), 0);
  const esc = (v: string) => v.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  const trs = projects.map(p =>
    `<tr>
      <td>${esc(p.name)}</td>
      <td>${esc(langLabel(p.sourceLanguage))}</td>
      <td>${esc(langLabel(p.targetLanguage))}</td>
      <td>${(p.totalLines ?? 0).toLocaleString()}</td>
      <td><strong>${eur(projectTokens(p))}</strong></td>
    </tr>`
  ).join('');

  const html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>Scriba AI — Token Consumption Report</title>
<style>
  body{font-family:sans-serif;color:#111;margin:32px}
  h1{font-size:20px;margin-bottom:4px}
  .meta{font-size:12px;color:#666;margin-bottom:24px}
  .summary{display:flex;gap:24px;margin-bottom:24px}
  .card{border:1px solid #ddd;border-radius:8px;padding:16px 24px;min-width:140px}
  .card p{margin:0;font-size:11px;color:#888;text-transform:uppercase;letter-spacing:.05em}
  .card h2{margin:4px 0 0;font-size:22px}
  table{width:100%;border-collapse:collapse;font-size:13px}
  th{background:#f5f5f5;text-align:left;padding:8px 10px;border-bottom:2px solid #ddd}
  td{padding:7px 10px;border-bottom:1px solid #eee}
  tr:nth-child(even) td{background:#fafafa}
  @media print{body{margin:0}}
</style>
</head>
<body>
<h1>Scriba AI — Spend Report</h1>
<p class="meta">Generated: ${esc(new Date().toLocaleString())} · Plan: ${esc(tier)}</p>
<div class="summary">
  <div class="card"><p>Active spend</p><h2>${eur(sessionTokens)}</h2></div>
  <div class="card"><p>Total spend</p><h2>${eur(total)}</h2></div>
  <div class="card"><p>Conversions</p><h2>${projects.length}</h2></div>
</div>
<table>
  <thead><tr><th>Conversion</th><th>Source</th><th>Target</th><th>Lines</th><th>Cost</th></tr></thead>
  <tbody>${trs}</tbody>
</table>
</body>
</html>`;

  const blob = new Blob([html], { type: 'text/html' });
  const url = URL.createObjectURL(blob);
  const printWin = window.open(url, '_blank');
  if (printWin) {
    printWin.addEventListener('load', () => {
      printWin.print();
      URL.revokeObjectURL(url);
    });
  }
}

// ── custom tooltip ────────────────────────────────────────────────────────────

function ChartTooltip({ active, payload, label }: any) {
  if (!active || !payload?.length) return null;
  return (
    <div className="glass rounded-lg p-3 text-xs border border-border shadow-xl">
      <p className="text-muted mb-1">{label}</p>
      <p className="font-semibold text-foreground">{eur(payload[0].value)}</p>
    </div>
  );
}

// ── component ─────────────────────────────────────────────────────────────────

type Period = 'daily' | 'weekly' | 'monthly' | 'annual';

interface Props {
  projects?: Project[];
}

export default function TokenDashboard({ projects: propProjects }: Props) {
  const { user: sessionUser } = useSession();
  const capabilities = getPlanCapabilities(sessionUser?.tier);
  const projects = propProjects ?? [];
  const [companyTokenSummary, setCompanyTokenSummary] = useState<{
    remainingCreditsTokens: number;
    includedCreditsAllowance: number;
    consumed: number;
    conversionCount: number;
    freeTokensConsumed: number;
  } | null>(null);

  const [period, setPeriod] = useState<Period>('daily');
  const [month, setMonth] = useState<string>('all');

  const ym = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
  const monthLabel = (key: string) => {
    const [y, m] = key.split('-').map(Number);
    return new Date(y, m - 1, 1).toLocaleDateString('en-GB', { month: 'short', year: 'numeric' });
  };

  const months = useMemo(() => {
    const set = new Set<string>();
    for (const p of projects) {
      const d = p.createdAt ? new Date(p.createdAt) : null;
      if (d && !isNaN(d.getTime())) set.add(ym(d));
    }
    return Array.from(set).sort().reverse();
  }, [projects]);

  const scoped = useMemo(() => {
    if (month === 'all') return projects;
    return projects.filter((p) => {
      const d = p.createdAt ? new Date(p.createdAt) : null;
      return d && !isNaN(d.getTime()) && ym(d) === month;
    });
  }, [projects, month]);

  useEffect(() => {
    if (!sessionUser?.companyId) {
      setCompanyTokenSummary(null);
      return;
    }
    fetch(`/api/companies/${sessionUser.companyId}/tokens`, { credentials: 'include' })
      .then((res) => (res.ok ? res.json() : null))
      .then((data) => {
        if (data?.tokens) {
          setCompanyTokenSummary({
            remainingCreditsTokens: data.tokens.remaining ?? data.tokens.licenseCreditsRemaining ?? 0,
            includedCreditsAllowance:
              data.tokens.includedCreditsAllowance ?? capabilities.includedCreditsTokens,
            consumed: data.tokens.consumed ?? 0,
            conversionCount: data.conversionCount ?? data.projectCount ?? 0,
            freeTokensConsumed: data.company?.freeTokensConsumed ?? 0,
          });
        }
      })
      .catch(() => {});
  }, [sessionUser?.companyId]);

  const sessionTokens = useMemo(() => {
    const activeProjects = projects.filter(p => ['analyzing', 'converting', 'validating'].includes(p.status));
    return activeProjects.reduce((s, p) => s + projectTokens(p), 0);
  }, [projects]);

  const scopedTotalTokens = useMemo(() => scoped.reduce((s, p) => s + projectTokens(p), 0), [scoped]);
  // For the all-time view prefer the authoritative company consumption; for a
  // specific month show the sum of that month's conversions.
  const totalTokens = month === 'all' ? (companyTokenSummary?.consumed ?? scopedTotalTokens) : scopedTotalTokens;
  const conversionCount = month === 'all' ? (companyTokenSummary?.conversionCount ?? projects.length) : scoped.length;
  const historyData = useMemo(() => buildHistory(projects, period), [projects, period]);
  const perProject = useMemo(
    () => [...scoped].map(p => ({ ...p, tokens: projectTokens(p) })).sort((a, b) => b.tokens - a.tokens),
    [scoped],
  );
  const maxTokens = perProject[0]?.tokens ?? 1;

  const PERIODS: { id: Period; label: string }[] = [
    { id: 'daily', label: 'Daily' },
    { id: 'weekly', label: 'Weekly' },
    { id: 'monthly', label: 'Monthly' },
    { id: 'annual', label: 'Annual' },
  ];

  return (
    <div className="space-y-5">

      {/* Header */}
      <motion.div initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }}
        className="flex items-center justify-between gap-4">
        <div>
          <h2 className="text-2xl font-bold text-foreground flex items-center gap-2">
            <Cpu className="w-6 h-6 text-accent-light" /> Usage
          </h2>
          <p className="text-sm text-muted mt-1">
            {month === 'all' ? 'All time' : monthLabel(month)} · per-conversion spend with export
          </p>
        </div>
        <div className="flex items-center gap-2">
          <div className="flex items-center gap-1.5 px-2.5 py-2 rounded-lg glass-light">
            <Calendar className="w-3.5 h-3.5 text-muted" />
            <select
              value={month}
              onChange={(e) => setMonth(e.target.value)}
              className="bg-transparent text-xs font-medium text-foreground outline-none cursor-pointer"
            >
              <option value="all">All time</option>
              {months.map((m) => (
                <option key={m} value={m}>{monthLabel(m)}</option>
              ))}
            </select>
          </div>
          <button onClick={() => exportCSV(scoped, sessionTokens)}
            className="flex items-center gap-1.5 px-3 py-2 rounded-lg glass-light text-xs font-medium text-muted hover:text-foreground transition-colors cursor-pointer">
            <FileText className="w-3.5 h-3.5" /> CSV
          </button>
          <button onClick={() => exportExcel(scoped, sessionTokens)}
            className="flex items-center gap-1.5 px-3 py-2 rounded-lg glass-light text-xs font-medium text-muted hover:text-foreground transition-colors cursor-pointer">
            <Table2 className="w-3.5 h-3.5" /> Excel
          </button>
          <button onClick={() => exportPDF(scoped, sessionTokens, capabilities.tier)}
            className="flex items-center gap-1.5 px-3 py-2 rounded-lg glass-light text-xs font-medium text-muted hover:text-foreground transition-colors cursor-pointer">
            <Printer className="w-3.5 h-3.5" /> PDF
          </button>
        </div>
      </motion.div>

      {/* Stat cards */}
      <div className="grid grid-cols-4 gap-3">

        {/* Active projects tokens */}
        <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.04 }}
          className="glass rounded-xl p-5 border border-accent/20 relative overflow-hidden">
          <div className="absolute -top-4 -right-4 w-20 h-20 rounded-full bg-accent/10 blur-xl pointer-events-none" />
          <div className="flex items-center gap-2 mb-3">
            <span className="w-2 h-2 rounded-full bg-green-400" />
            <p className="text-[10px] text-muted uppercase tracking-wider font-medium">Active Conversions</p>
          </div>
          <p className="text-2xl font-bold text-foreground tabular-nums">{eur(sessionTokens)}</p>
          <p className="text-[11px] text-muted mt-1">in progress</p>
          <div className="mt-3 text-[10px] text-muted">
            {projects.filter(p => ['analyzing', 'converting', 'validating'].includes(p.status)).length} active conversion{projects.filter(p => ['analyzing', 'converting', 'validating'].includes(p.status)).length !== 1 ? 's' : ''}
          </div>
        </motion.div>

        <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.07 }}
          className="glass rounded-xl p-5">
          <p className="text-[10px] text-muted uppercase tracking-wider font-medium mb-3">Total Spend</p>
          <p className="text-2xl font-bold text-foreground tabular-nums">{eur(totalTokens)}</p>
          <p className="text-[11px] text-muted mt-1">across {conversionCount} conversion{conversionCount !== 1 ? 's' : ''}</p>
          <p className="mt-3 text-[10px] text-muted capitalize">{capabilities.tier} · {capabilities.supportSla} SLA</p>
        </motion.div>

        <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.1 }}
          className="glass rounded-xl p-5">
          <p className="text-[10px] text-muted uppercase tracking-wider font-medium mb-3">Plan credit remaining</p>
          {companyTokenSummary ? (
            <>
              <p className="text-2xl font-bold text-foreground tabular-nums">
                {eur(companyTokenSummary.remainingCreditsTokens)}
              </p>
              <p className="text-[11px] text-muted mt-1">
                of {eur(companyTokenSummary.includedCreditsAllowance)} / year · applied at confirmation
              </p>
              <p className="mt-3 text-[10px] text-muted">
                Billed on the 1st for completed conversions.
              </p>
            </>
          ) : (
            <>
              <p className="text-2xl font-bold text-foreground tabular-nums">—</p>
              <p className="text-[11px] text-muted mt-1">Join a company to see plan credits</p>
            </>
          )}
        </motion.div>

        <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.13 }}
          className="glass rounded-xl p-5">
          <p className="text-[10px] text-muted uppercase tracking-wider font-medium mb-3">Avg per Conversion</p>
          <p className="text-2xl font-bold text-foreground tabular-nums">
            {conversionCount > 0 ? eur(Math.round(totalTokens / conversionCount)) : '—'}
          </p>
          <p className="text-[11px] text-muted mt-1">per conversion</p>
          {perProject[0] && (
            <p className="mt-3 text-[10px] text-muted truncate">
              Top: {perProject[0].name}
            </p>
          )}
        </motion.div>
      </div>

      {/* History chart */}
      <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.16 }}
        className="glass rounded-xl p-5">
        <div className="flex items-center justify-between mb-4">
          <h3 className="text-sm font-semibold text-foreground flex items-center gap-2">
            <TrendingUp className="w-4 h-4 text-accent-light" /> Consumption History
          </h3>
          <div className="flex gap-1 bg-surface rounded-lg p-1">
            {PERIODS.map(p => (
              <button key={p.id} onClick={() => setPeriod(p.id)}
                className={`px-3 py-1 rounded-md text-xs font-medium transition-all cursor-pointer ${
                  period === p.id ? 'bg-accent/20 text-accent-light' : 'text-muted hover:text-foreground'
                }`}>
                {p.label}
              </button>
            ))}
          </div>
        </div>
        {historyData.length > 0 ? (
          <ResponsiveContainer width="100%" height={220}>
            <AreaChart data={historyData} margin={{ top: 5, right: 5, bottom: 0, left: 0 }}>
              <defs>
                <linearGradient id="tokenGrad" x1="0" y1="0" x2="0" y2="1">
                  <stop offset="5%" stopColor="var(--color-accent)" stopOpacity={0.3} />
                  <stop offset="95%" stopColor="var(--color-accent)" stopOpacity={0} />
                </linearGradient>
              </defs>
              <CartesianGrid strokeDasharray="3 3" stroke="var(--color-border)" vertical={false} />
              <XAxis dataKey="label" tick={{ fontSize: 10, fill: 'var(--color-muted)' }} tickLine={false} axisLine={false} interval="preserveStartEnd" />
              <YAxis tick={{ fontSize: 10, fill: 'var(--color-muted)' }} tickLine={false} axisLine={false}
                tickFormatter={(v: number) => { const e = eurFromTokens(v); return e >= 1000 ? `€${(e / 1000).toFixed(0)}k` : `€${Math.round(e)}`; }} />
              <Tooltip content={<ChartTooltip />} />
              <Area type="monotone" dataKey="tokens" stroke="var(--color-accent)" strokeWidth={2} fill="url(#tokenGrad)" dot={false} />
            </AreaChart>
          </ResponsiveContainer>
        ) : (
          <div className="h-[220px] flex items-center justify-center">
            <p className="text-xs text-muted italic">No conversion data yet — create a conversion to see usage.</p>
          </div>
        )}
      </motion.div>

      {/* Per-project breakdown */}
      <motion.div initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} transition={{ delay: 0.19 }}
        className="glass rounded-xl p-5">
        <h3 className="text-sm font-semibold text-foreground mb-4 flex items-center gap-2">
          <BarChart3 className="w-4 h-4 text-accent-light" /> Per-conversion detail
        </h3>
        {perProject.length === 0 ? (
          <p className="text-xs text-muted italic">No conversions yet.</p>
        ) : (
          <div className="overflow-hidden rounded-lg border border-border">
            <div className="grid grid-cols-[1fr_110px_110px_160px] gap-4 px-4 py-2.5 bg-surface text-[10px] text-muted uppercase tracking-wider font-semibold">
              <span>Conversion</span>
              <span>Source</span>
              <span>Target</span>
              <span>Cost</span>
            </div>
            {perProject.map((p, i) => {
              const pct = maxTokens > 0 ? Math.round((p.tokens / maxTokens) * 100) : 0;
              return (
                <div key={p.id}
                  className={`grid grid-cols-[1fr_110px_110px_160px] gap-4 px-4 py-3 items-center text-xs border-t border-border/50 ${i % 2 !== 0 ? 'bg-surface/40' : ''}`}>
                  <div className="min-w-0">
                    <p className="font-medium text-foreground truncate">{p.name}</p>
                    <p className="text-[10px] text-muted mt-0.5 capitalize">{p.status}</p>
                  </div>
                  <span className="text-muted">{langLabel(p.sourceLanguage)}</span>
                  <span className="text-muted">{langLabel(p.targetLanguage)}</span>
                  <div className="flex items-center gap-2">
                    <div className="flex-1 h-1.5 rounded-full bg-surface overflow-hidden">
                      <div className="h-full rounded-full bg-accent" style={{ width: `${pct}%` }} />
                    </div>
                    <span className="tabular-nums font-medium text-foreground w-20 text-right">{eur(p.tokens)}</span>
                  </div>
                </div>
              );
            })}
            <div className="grid grid-cols-[1fr_110px_110px_160px] gap-4 px-4 py-3 border-t border-border bg-surface/60 text-xs font-semibold">
              <span className="text-foreground">Total</span>
              <span /><span />
              <span className="text-foreground text-right">{eur(totalTokens)}</span>
            </div>
          </div>
        )}
      </motion.div>

    </div>
  );
}
