import { useState, useEffect, useCallback } from 'react';
import { Database, Download, Play, RefreshCw, RotateCcw, Trash2, Upload } from 'lucide-react';
import { toast } from 'sonner';
import { api } from '@/api';
import { cn, fmtBytes, errMessage } from '@/lib/utils';
import { Button, buttonVariants } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import {
  Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import {
  AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle,
  AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction,
} from '@/components/ui/alert-dialog';
import { SectionHeading, Toggle, formatDateTime, BackupTypeBadge } from './adminShared';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';

interface Backup {
  id: string;
  type?: string;
  modified_at?: string | null;
  size_bytes?: number;
  checksum?: string | null;
}

interface BackupSettings {
  enabled: boolean;
  frequency: string;
  time: string;
  retention_count: number | string;
  last_run_at: string | null;
  next_run_at: string | null;
  last_error: string | null;
}

const DEFAULT_SETTINGS: BackupSettings = {
  enabled: false,
  frequency: 'daily',
  time: '02:00',
  retention_count: 2,
  last_run_at: null,
  next_run_at: null,
  last_error: null,
};

export default function BackupManagementCard() {
  const [backups, setBackups]           = useState<Backup[]>([]);
  const [settings, setSettings]         = useState<BackupSettings>(DEFAULT_SETTINGS);
  const [loading, setLoading]           = useState(true);
  const [busy, setBusy]                 = useState('');
  const [restoreTarget, setRestoreTarget] = useState<Backup | null>(null);
  const [deleteTarget, setDeleteTarget]   = useState<Backup | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const [backupData, settingsData] = await Promise.all([
        api.adminBackups() as Promise<{ backups?: Backup[] }>,
        api.adminBackupSettings() as Promise<Partial<BackupSettings>>,
      ]);
      setBackups(backupData.backups || []);
      setSettings({ ...DEFAULT_SETTINGS, ...settingsData });
    } catch (err) {
      toast.error(errMessage(err, 'Failed to load backups.'));
    } finally {
      setLoading(false);
    }
  }, []);

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

  const latest = backups[0];
  const setSchedule = (key: keyof BackupSettings, value: string | boolean) => setSettings(prev => ({ ...prev, [key]: value }));

  async function handleCreate() {
    setBusy('create');
    try {
      await api.createAdminBackup();
      toast.success('Backup created.');
      await load();
    } catch (err) {
      toast.error(errMessage(err, 'Failed to create backup.'));
    } finally {
      setBusy('');
    }
  }

  async function handleDownload(backup: Backup) {
    setBusy(`download:${backup.id}`);
    try {
      const { blob, filename } = await api.downloadAdminBackup(backup.id) as { blob: Blob; filename?: string };
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = filename || backup.id;
      document.body.appendChild(a);
      a.click();
      a.remove();
      URL.revokeObjectURL(url);
    } catch (err) {
      toast.error(errMessage(err, 'Failed to download backup.'));
    } finally {
      setBusy('');
    }
  }

  async function handleImport(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    e.target.value = '';
    if (!file) return;

    setBusy('import');
    try {
      await api.importAdminBackup(file);
      toast.success('Backup imported.');
      await load();
    } catch (err) {
      toast.error(errMessage(err, 'Failed to import backup.'));
    } finally {
      setBusy('');
    }
  }

  async function handleRestore() {
    if (!restoreTarget) return;
    setBusy(`restore:${restoreTarget.id}`);
    try {
      const result = await api.restoreAdminBackup(restoreTarget.id) as { pre_restore_backup?: string };
      toast.success(`Database restored. Pre-restore backup: ${result.pre_restore_backup}`);
      setRestoreTarget(null);
      await load();
    } catch (err) {
      toast.error(errMessage(err, 'Failed to restore backup.'));
    } finally {
      setBusy('');
    }
  }

  async function handleDelete() {
    if (!deleteTarget) return;
    setBusy(`delete:${deleteTarget.id}`);
    try {
      await api.deleteAdminBackup(deleteTarget.id);
      toast.success('Backup deleted.');
      setDeleteTarget(null);
      await load();
    } catch (err) {
      toast.error(errMessage(err, 'Failed to delete backup.'));
    } finally {
      setBusy('');
    }
  }

  async function handleSaveSettings() {
    setBusy('settings');
    try {
      const saved = await api.saveAdminBackupSettings({
        enabled: !!settings.enabled,
        frequency: settings.frequency,
        time: settings.time,
        retention_count: parseInt(String(settings.retention_count), 10) || 2,
      }) as Partial<BackupSettings>;
      setSettings({ ...DEFAULT_SETTINGS, ...saved });
      toast.success('Backup schedule saved.');
    } catch (err) {
      toast.error(errMessage(err, 'Failed to save backup schedule.'));
    } finally {
      setBusy('');
    }
  }

  async function handleRunScheduledNow() {
    setBusy('run-scheduled');
    try {
      await api.runScheduledBackupNow();
      toast.success('Scheduled backup created.');
      await load();
    } catch (err) {
      toast.error(errMessage(err, 'Failed to run scheduled backup.'));
    } finally {
      setBusy('');
    }
  }

  if (loading) {
    return <Card><CardContent className="py-8 text-center text-muted-foreground text-sm">Loading backups…</CardContent></Card>;
  }

  return (
    <>
      <Card>
        <CardHeader className="pb-4">
          <div className="flex items-center justify-between gap-3">
            <div>
              <CardTitle>Database Backups</CardTitle>
              <p className="text-sm text-muted-foreground mt-1">
                Admin-only SQLite backup, import, download, restore, and schedule controls.
              </p>
            </div>
            <TooltipProvider delayDuration={300}>
              <Tooltip>
                <TooltipTrigger asChild>
                  <Badge className={cn('cursor-default', settings.last_error ? 'bg-red-500/15 text-red-400 border-red-500/20' : 'bg-emerald-500/15 text-emerald-400 border-emerald-500/20')}>
                    {settings.last_error ? 'Attention' : 'Ready'}
                  </Badge>
                </TooltipTrigger>
                <TooltipContent>{settings.last_error || 'Backup system is operational'}</TooltipContent>
              </Tooltip>
            </TooltipProvider>
          </div>
        </CardHeader>
        <CardContent className="space-y-6">
          <div className="grid gap-3 md:grid-cols-4">
            {([
              ['Managed backups', backups.length],
              ['Latest backup', latest ? formatDateTime(latest.modified_at) : '—'],
              ['Latest size', latest ? fmtBytes(latest.size_bytes) : '—'],
              ['Scheduled', settings.enabled ? `${settings.frequency} ${settings.time}` : 'Disabled'],
            ] as [string, React.ReactNode][]).map(([label, value]) => (
              <div key={label} className="rounded-lg border border-border bg-muted/20 p-3">
                <p className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">{label}</p>
                <p className="text-sm font-medium mt-1 truncate">{value}</p>
              </div>
            ))}
          </div>

          {settings.last_error && (
            <div className="rounded-lg border border-red-500/25 bg-red-500/10 px-3 py-2 text-sm text-red-400">
              {settings.last_error}
            </div>
          )}

          <div className="flex flex-wrap items-center gap-2">
            <Button onClick={handleCreate} disabled={!!busy}>
              <Database className="h-4 w-4" />
              {busy === 'create' ? 'Creating…' : 'Create Backup'}
            </Button>
            <Button asChild variant="outline" disabled={!!busy}>
              <label className={cn('cursor-pointer', busy && 'pointer-events-none opacity-50')}>
                <Upload className="h-4 w-4" />
                {busy === 'import' ? 'Importing…' : 'Import Backup'}
                <input
                  type="file"
                  accept=".sqlite,.db,application/octet-stream,application/x-sqlite3,application/vnd.sqlite3"
                  onChange={handleImport}
                  className="sr-only"
                  disabled={!!busy}
                />
              </label>
            </Button>
            <Button variant="outline" onClick={load} disabled={!!busy}>
              <RefreshCw className="h-4 w-4" />
              Refresh
            </Button>
          </div>

          <div className="overflow-x-auto rounded-lg border border-border">
            <table className="min-w-[860px] w-full text-sm">
              <thead className="bg-muted/40">
                <tr className="border-b border-border">
                  <th className="text-left px-4 py-3 text-muted-foreground font-medium">Backup</th>
                  <th className="text-left px-4 py-3 text-muted-foreground font-medium">Type</th>
                  <th className="text-left px-4 py-3 text-muted-foreground font-medium">Modified</th>
                  <th className="text-left px-4 py-3 text-muted-foreground font-medium">Size</th>
                  <th className="text-left px-4 py-3 text-muted-foreground font-medium">Checksum</th>
                  <th className="px-4 py-3" />
                </tr>
              </thead>
              <tbody>
                {backups.map(backup => (
                  <tr key={backup.id} className="border-b border-border last:border-0 hover:bg-muted/25">
                    <td className="px-4 py-3 font-mono text-xs max-w-[260px] truncate" title={backup.id}>{backup.id}</td>
                    <td className="px-4 py-3"><BackupTypeBadge type={backup.type} /></td>
                    <td className="px-4 py-3 text-muted-foreground">{formatDateTime(backup.modified_at)}</td>
                    <td className="px-4 py-3 font-mono">{fmtBytes(backup.size_bytes)}</td>
                    <td className="px-4 py-3 font-mono text-xs text-muted-foreground max-w-[120px] truncate" title={backup.checksum ?? undefined}>
                      {backup.checksum || '—'}
                    </td>
                    <td className="px-4 py-3">
                      <div className="flex items-center justify-end gap-1">
                        <Button size="icon" variant="ghost" title="Download backup" onClick={() => handleDownload(backup)} disabled={!!busy}>
                          <Download className="h-4 w-4" />
                        </Button>
                        <Button size="icon" variant="ghost" title="Restore backup" onClick={() => setRestoreTarget(backup)} disabled={!!busy}>
                          <RotateCcw className="h-4 w-4" />
                        </Button>
                        <Button size="icon" variant="ghost" title="Delete backup" onClick={() => setDeleteTarget(backup)} disabled={!!busy}>
                          <Trash2 className="h-4 w-4" />
                        </Button>
                      </div>
                    </td>
                  </tr>
                ))}
                {!backups.length && (
                  <tr>
                    <td colSpan={6} className="px-4 py-8 text-center text-muted-foreground">No managed backups yet.</td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          <div className="border-t border-border pt-5 space-y-4">
            <div className="flex items-center justify-between">
              <div>
                <SectionHeading>Scheduled Backups</SectionHeading>
                <p className="text-xs text-muted-foreground mt-1">
                  Scheduled runs create managed backups and only apply retention to scheduled backups.
                </p>
              </div>
              <Toggle checked={!!settings.enabled} onChange={v => setSchedule('enabled', v)} label="Enable scheduled backups" />
            </div>

            <div className="grid gap-4 md:grid-cols-4">
              <div className="space-y-1.5">
                <Label>Frequency</Label>
                <Select value={settings.frequency} onValueChange={v => setSchedule('frequency', v)}>
                  <SelectTrigger><SelectValue /></SelectTrigger>
                  <SelectContent>
                    <SelectItem value="daily">Daily</SelectItem>
                    <SelectItem value="weekly">Weekly</SelectItem>
                  </SelectContent>
                </Select>
              </div>
              <div className="space-y-1.5">
                <Label>Time</Label>
                <Input type="time" value={settings.time} onChange={e => setSchedule('time', e.target.value)} />
              </div>
              <div className="space-y-1.5">
                <TooltipProvider delayDuration={300}>
                  <Tooltip>
                    <TooltipTrigger asChild>
                      <Label className="cursor-default">Keep scheduled</Label>
                    </TooltipTrigger>
                    <TooltipContent>Number of scheduled backups to retain — older ones are auto-deleted</TooltipContent>
                  </Tooltip>
                </TooltipProvider>
                <Input type="number" min="1" max="365" value={settings.retention_count} onChange={e => setSchedule('retention_count', e.target.value)} />
              </div>
              <div className="space-y-1.5">
                <Label>Next run</Label>
                <div className="h-9 rounded-md border border-input bg-muted/30 px-3 py-2 text-sm text-muted-foreground truncate">
                  {formatDateTime(settings.next_run_at)}
                </div>
              </div>
            </div>

            <div className="grid gap-3 md:grid-cols-2">
              <div className="text-sm text-muted-foreground">Last run: <span className="text-foreground">{formatDateTime(settings.last_run_at)}</span></div>
              <div className="text-sm text-muted-foreground">Last error: <span className="text-foreground">{settings.last_error || '—'}</span></div>
            </div>

            <div className="flex flex-wrap justify-end gap-2">
              <Button variant="outline" onClick={handleRunScheduledNow} disabled={!!busy}>
                <Play className="h-4 w-4" />
                {busy === 'run-scheduled' ? 'Running…' : 'Run Scheduled Now'}
              </Button>
              <Button onClick={handleSaveSettings} disabled={!!busy}>
                {busy === 'settings' ? 'Saving…' : 'Save Schedule'}
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      <AlertDialog open={!!restoreTarget} onOpenChange={(open) => { if (!open) setRestoreTarget(null); }}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Restore this database backup?</AlertDialogTitle>
            <AlertDialogDescription>
              This replaces the live database with <span className="font-mono">{restoreTarget?.id}</span>.
              A pre-restore backup will be created first. Run this during a quiet maintenance window.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={busy.startsWith('restore:')}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className={cn(buttonVariants({ variant: 'destructive' }))}
              onClick={handleRestore}
              disabled={busy.startsWith('restore:')}
            >
              {busy.startsWith('restore:') ? 'Restoring…' : 'Restore Database'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>

      <AlertDialog open={!!deleteTarget} onOpenChange={(open) => { if (!open) setDeleteTarget(null); }}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete this backup?</AlertDialogTitle>
            <AlertDialogDescription>
              This permanently deletes <span className="font-mono">{deleteTarget?.id}</span>.
              The live database is not affected.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel disabled={busy.startsWith('delete:')}>Cancel</AlertDialogCancel>
            <AlertDialogAction
              className={cn(buttonVariants({ variant: 'destructive' }))}
              onClick={handleDelete}
              disabled={busy.startsWith('delete:')}
            >
              {busy.startsWith('delete:') ? 'Deleting…' : 'Delete Backup'}
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </>
  );
}
