import { useState } from 'react';
import {
  Play, Archive, HardDrive, Clock, CheckCircle2, ArrowUpRight,
  Database, FileArchive, Cloud,
} from 'lucide-react';
import { Card, CardBody, CardHeader, CardTitle, CardDescription } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { Badge } from '@/components/ui/Badge';
import { Ring } from '@/components/ui/Progress';
import { Loading, ErrorState, Toast } from '@/components/ui/States';
import { BackupNowButton } from '@/components/BackupNowButton';
import { formatBytes, formatDateTime } from '@/lib/format';
import { api, type BackupType } from '@/lib/api';
import { useQuery, useMutation } from '@/hooks/useQuery';
import { ResponsiveContainer, BarChart, Bar, XAxis, YAxis, Tooltip, CartesianGrid } from 'recharts';
import { useApp, type PageKey } from '@/App';

export function Dashboard({ go }: { go: (k: PageKey, opts?: { backupId?: string }) => void }) {
  const { data, isLoading, error, refetch } = useQuery(() => api.dashboard(), []);
  const [toast, setToast] = useState<{ msg: string; tone: 'success' | 'danger' } | null>(null);
  const { trackBackup, activeBackupId } = useApp();

  const backupNow = useMutation(
    (type: BackupType) => api.backups.create({ type }),
    {
      // No toast — the floating BackupProgress panel already communicates state.
      onSuccess: (b) => trackBackup(b.id),
      onError:   (e) => setToast({ msg: e.message, tone: 'danger' }),
    },
  );

  if (isLoading) return <Loading label="Loading dashboard…" />;
  if (error)     return <ErrorState error={error} onRetry={refetch} />;
  if (!data)     return null;

  const last = data.last_backup;
  const protectedNow = !!last && last.status === 'success';
  const accent = data.storage_by_destination.map((_, i) => ['#1dd1a1','#0ea5e9','#f59e0b','#6366f1','#ef4444','#8b5cf6','#ec4899'][i % 7]);

  return (
    <div className="space-y-6 max-w-[1400px]">
      {/* Hero */}
      <div className="rounded-2xl bg-gradient-to-br from-ink-900 to-ink-800 text-white p-5 sm:p-6 flex items-center justify-between gap-4 shadow-pop">
        <div>
          <Badge tone="accent" dot className="bg-white/10 text-white ring-white/20">
            {protectedNow ? 'Protected' : 'No successful backup yet'}
          </Badge>
          <h2 className="text-xl font-semibold mt-3">
            {protectedNow ? 'Your site is fully backed up' : 'Run your first backup'}
          </h2>
          <p className="text-sm text-white/70 mt-1">
            {last
              ? `Last backup: ${formatDateTime(last.date)} · ${formatBytes(last.size)} · ${last.destinations.length} destinations`
              : 'No backups yet. Click below to create the first one.'}
          </p>
          <div className="flex gap-2 mt-4 flex-wrap">
            <BackupNowButton
              disabled={backupNow.isLoading || !!activeBackupId}
              label={activeBackupId ? 'Backup running…' : (backupNow.isLoading ? 'Queuing…' : 'Backup now')}
              onRun={(t) => backupNow.mutate(t)}
            />
            <Button variant="ghost" size="md" className="text-white hover:bg-white/10"
              rightIcon={<ArrowUpRight className="h-4 w-4" />}
              onClick={() => go('schedule')}>
              View schedule
            </Button>
          </div>
        </div>
        <div className="hidden md:flex items-center gap-6">
          <Ring value={data.success_rate} size={108} label="success" tone="dark" />
        </div>
      </div>

      {/* KPIs */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
        <KPI icon={<Archive className="h-4 w-4" />} label="Total backups" value={String(data.total_count)} hint="all time" />
        <KPI icon={<HardDrive className="h-4 w-4" />} label="Storage used" value={formatBytes(data.storage_used)} hint={`across ${data.storage_by_destination.length} destinations`} />
        <KPI icon={<CheckCircle2 className="h-4 w-4" />} label="Success rate" value={`${data.success_rate}%`} hint="all backups" tone={data.success_rate >= 90 ? 'success' : undefined} />
        <KPI icon={<Clock className="h-4 w-4" />} label="Next scheduled" value={formatDateTime(data.next_run)} hint={data.next_run ? 'auto' : 'no schedule'} />
      </div>

      {/* Charts row */}
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
        <Card className="lg:col-span-2">
          <CardHeader>
            <div>
              <CardTitle>Backup size, last 7 days</CardTitle>
              <CardDescription>Daily total across all destinations</CardDescription>
            </div>
            <Badge tone="neutral">MB</Badge>
          </CardHeader>
          <CardBody>
            <div className="h-56">
              <ResponsiveContainer width="100%" height="100%">
                <BarChart data={data.series_7d}>
                  <CartesianGrid stroke="#eef0f2" vertical={false} />
                  <XAxis dataKey="day" stroke="#9aa1aa" fontSize={11} tickLine={false} axisLine={false} />
                  <YAxis stroke="#9aa1aa" fontSize={11} tickLine={false} axisLine={false} />
                  <Tooltip contentStyle={{ fontSize: 12, borderRadius: 8, border: '1px solid #dfe2e6' }} />
                  <Bar dataKey="mb" fill="#1dd1a1" radius={[6, 6, 0, 0]} />
                </BarChart>
              </ResponsiveContainer>
            </div>
          </CardBody>
        </Card>

        <Card>
          <CardHeader>
            <div>
              <CardTitle>Storage by destination</CardTitle>
              <CardDescription>GB used</CardDescription>
            </div>
          </CardHeader>
          <CardBody className="space-y-4">
            {data.storage_by_destination.length === 0 && (
              <p className="text-xs text-ink-500">No destinations configured yet.</p>
            )}
            {data.storage_by_destination.map((d, i) => {
              // All values are bytes (see Destination.usage). Bar fill =
              // used / (used + free), matching the label "X used". A
              // mostly-empty disk shows a near-empty bar even if the OS is
              // using a lot of space on the same volume — that disconnect
              // was the source of the "why is the bar half full when I've
              // only backed up 7 GB?" reports.
              const dfree    = d.free ?? 0;
              const headroom = d.used + dfree;
              const fillPct  = headroom > 0 ? Math.min(100, ( d.used / headroom ) * 100) : 0;
              return (
                <div key={d.name + i}>
                  <div className="flex items-center justify-between text-xs mb-1.5 gap-2">
                    <div className="flex items-center gap-2 min-w-0">
                      <span className="h-2 w-2 rounded-full shrink-0" style={{ background: accent[i] }} />
                      <span className="text-ink-700 font-medium truncate">{d.name}</span>
                    </div>
                    <span className="text-ink-500 shrink-0">{formatBytes(d.used)}</span>
                  </div>
                  <div className="h-1.5 bg-ink-100 rounded-full overflow-hidden">
                    <div className="h-full rounded-full" style={{
                      width: `${fillPct}%`,
                      background: accent[i],
                    }} />
                  </div>
                </div>
              );
            })}
          </CardBody>
        </Card>
      </div>

      {/* Quick actions + Recent */}
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
        <Card className="lg:col-span-2">
          <CardHeader>
            <div>
              <CardTitle>Quick actions</CardTitle>
              <CardDescription>Common backup operations</CardDescription>
            </div>
          </CardHeader>
          <CardBody className="grid grid-cols-1 sm:grid-cols-3 gap-3">
            <QuickAction icon={<FileArchive className="h-4 w-4" />} title="Full backup"   desc="Files + database" onClick={() => backupNow.mutate('full')} />
            <QuickAction icon={<Database className="h-4 w-4" />}    title="Database only" desc="Fast, ~30s"       onClick={() => backupNow.mutate('database')} />
            <QuickAction icon={<Cloud className="h-4 w-4" />}       title="Files only"    desc="Skip database"   onClick={() => backupNow.mutate('files')} />
          </CardBody>
        </Card>

        <Card>
          <CardHeader>
            <CardTitle>Recent backups</CardTitle>
          </CardHeader>
          <CardBody className="space-y-3">
            {data.recent.length === 0 && <p className="text-xs text-ink-500">Nothing here yet.</p>}
            {data.recent.map((b) => (
              <div key={b.id} className="flex items-start gap-3">
                <span className={'mt-1 h-1.5 w-1.5 rounded-full ' + (b.status === 'success' ? 'bg-emerald-500' : b.status === 'failed' ? 'bg-red-500' : 'bg-amber-500')} />
                <div className="flex-1 min-w-0">
                  <p className="text-sm text-ink-800 truncate">{b.type} backup · {b.status}</p>
                  <p className="text-xs text-ink-500">{formatBytes(b.size)} · {formatDateTime(b.date)}</p>
                </div>
              </div>
            ))}
          </CardBody>
        </Card>
      </div>

      {toast && <Toast message={toast.msg} tone={toast.tone} onClose={() => setToast(null)} />}
    </div>
  );
}

function KPI({ icon, label, value, hint, tone }: { icon: React.ReactNode; label: string; value: string; hint?: string; tone?: 'success' }) {
  return (
    <Card>
      <CardBody>
        <div className="flex items-center justify-between">
          <span className="h-7 w-7 grid place-items-center rounded-lg bg-ink-100 text-ink-700">{icon}</span>
          {tone === 'success' && <Badge tone="success" dot>healthy</Badge>}
        </div>
        <p className="text-xs text-ink-500 mt-3">{label}</p>
        <p className="text-2xl font-semibold text-ink-900 mt-0.5 tracking-tight">{value}</p>
        {hint && <p className="text-[11px] text-ink-500 mt-1">{hint}</p>}
      </CardBody>
    </Card>
  );
}

function QuickAction({ icon, title, desc, onClick }: { icon: React.ReactNode; title: string; desc: string; onClick?: () => void }) {
  return (
    <button onClick={onClick} className="flex flex-col items-start text-left p-4 rounded-xl border border-ink-200 hover:border-ink-300 hover:bg-ink-50/60 transition-colors w-full">
      <span className="h-9 w-9 grid place-items-center rounded-lg bg-brand-50 text-brand-700">{icon}</span>
      <span className="mt-3 text-sm font-medium text-ink-900">{title}</span>
      <span className="text-xs text-ink-500 mt-0.5">{desc}</span>
    </button>
  );
}
