import React, { useState, useEffect, useRef } from 'react';
import {
  RotateCcw,
  RefreshCw,
  Loader2,
  CheckCircle2,
  XCircle,
  AlertTriangle,
  Database,
  ChevronDown,
  Trash2,
  Copy,
  Check,
} from 'lucide-react';
import { Button } from '../../components/ui/button';
import { Alert, AlertDescription } from '../../components/ui/alert';
import { Badge } from '../../components/ui/badge';
import { Switch } from '../../components/ui/switch';
import type { BackupEntry } from '../../types';
import { useBackupRestore } from '../BackupRestoreContext';

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

function formatDate(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleString(undefined, {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  });
}

// ─── Container picker inline component ───────────────────────────────────────

interface ContainerPickerProps {
  containers: string[];
  loadingContainers: boolean;
  value: string;
  onChange: (v: string) => void;
  onConfirm: () => void;
  onCancel: () => void;
  isRestoring: boolean;
}

const ContainerPicker: React.FC<ContainerPickerProps> = ({
  containers,
  loadingContainers,
  value,
  onChange,
  onConfirm,
  onCancel,
  isRestoring,
}) => (
  <div className="mt-3 p-3 bg-muted/50 rounded-lg border border-border space-y-3">
    <p className="text-xs font-medium text-foreground">
      Select target PostgreSQL container:
    </p>

    {loadingContainers ? (
      <div className="flex items-center gap-2 text-xs text-muted-foreground">
        <Loader2 className="h-3.5 w-3.5 animate-spin" />
        Loading containers…
      </div>
    ) : containers.length === 0 ? (
      <p className="text-xs text-muted-foreground">No canvas-postgres containers found.</p>
    ) : (
      <select
        value={value}
        onChange={(e) => onChange(e.target.value)}
        disabled={isRestoring}
        className="w-full bg-background border border-border rounded-md px-3 py-1.5 text-sm text-foreground focus:outline-none focus:ring-2 focus:ring-ring disabled:opacity-50"
      >
        {containers.map((c) => (
          <option key={c} value={c}>
            {c}
          </option>
        ))}
      </select>
    )}

    <div className="flex gap-2">
      <Button
        size="sm"
        onClick={onConfirm}
        disabled={!value || isRestoring || loadingContainers}
        className="bg-amber-600 hover:bg-amber-700 h-7 text-xs"
      >
        {isRestoring ? (
          <>
            <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />
            Restoring…
          </>
        ) : (
          <>
            <RotateCcw className="h-3 w-3 mr-1.5" />
            Confirm Restore
          </>
        )}
      </Button>
      <Button
        size="sm"
        variant="ghost"
        onClick={onCancel}
        disabled={isRestoring}
        className="h-7 text-xs"
      >
        Cancel
      </Button>
    </div>
  </div>
);

// ─── Main component ───────────────────────────────────────────────────────────

export const RestoreStep: React.FC = () => {
  const { currentStep } = useBackupRestore();
  const [backups, setBackups] = useState<BackupEntry[]>([]);
  const [isLoading, setIsLoading] = useState(true);

  const [containers, setContainers] = useState<string[]>([]);
  const [loadingContainers, setLoadingContainers] = useState(false);

  // Per-backup picker state
  const [pickerOpenId, setPickerOpenId] = useState<string | null>(null);
  const [pickerContainer, setPickerContainer] = useState<string>('');

  // Delete confirmation
  const [confirmDeleteId, setConfirmDeleteId] = useState<string | null>(null);

  // Restore progress
  const [restoringId, setRestoringId] = useState<string | null>(null);
  const [terminalOutput, setTerminalOutput] = useState<string>('');
  const [showTerminal, setShowTerminal] = useState(false);
  const [result, setResult] = useState<{ success: boolean; message: string } | null>(null);
  const [copiedOutput, setCopiedOutput] = useState<string | null>(null);

  const terminalRef = useRef<HTMLDivElement>(null);

  // ── data loading ──────────────────────────────────────────────────────────

  const loadBackups = async () => {
    setIsLoading(true);
    try {
      const list = await window.backupRestoreAPI.getBackups();
      setBackups(list);
    } catch (err) {
      console.error('Failed to load backups:', err);
    } finally {
      setIsLoading(false);
    }
  };

  const loadContainers = async () => {
    setLoadingContainers(true);
    try {
      const list = await window.backupRestoreAPI.getContainers();
      setContainers(list);
      if (list.length > 0) setPickerContainer((prev) => prev || list[0]);
    } catch (err) {
      console.error('Failed to load containers:', err);
    } finally {
      setLoadingContainers(false);
    }
  };

  useEffect(() => {
    if (currentStep === 'restore' && !restoringId) {
      loadBackups();
    }
  }, [currentStep]);

  // ── terminal auto-scroll ──────────────────────────────────────────────────

  useEffect(() => {
    if (terminalRef.current) {
      terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
    }
  }, [terminalOutput]);

  // ── subscribe to restore output stream ────────────────────────────────────

  useEffect(() => {
    const unsubscribe = window.backupRestoreAPI.onRestoreOutput((output) => {
      setTerminalOutput((prev) => prev + output);
    });
    return unsubscribe;
  }, []);

  // ── default toggle ────────────────────────────────────────────────────────

  const handleDefaultToggle = async (backup: BackupEntry, checked: boolean) => {
    // Optimistic update
    setBackups((prev) =>
      prev.map((b) => ({ ...b, isDefault: checked && b.id === backup.id }))
    );
    try {
      await window.backupRestoreAPI.setDefaultBackup(backup.id, checked);
    } catch (err) {
      console.error('Failed to set default backup:', err);
      // Revert
      loadBackups();
    }
  };

  // ── restore flow ──────────────────────────────────────────────────────────

  const openPicker = async (backup: BackupEntry) => {
    setPickerOpenId(backup.id);
    setResult(null);
    if (containers.length === 0) {
      await loadContainers();
    }
  };

  const closePicker = () => {
    setPickerOpenId(null);
  };

  const handleDelete = async (id: string) => {
    try {
      await window.backupRestoreAPI.deleteBackup(id);
      setBackups((prev) => prev.filter((b) => b.id !== id));
      if (pickerOpenId === id) setPickerOpenId(null);
    } catch (err) {
      console.error('Failed to delete backup:', err);
    } finally {
      setConfirmDeleteId(null);
    }
  };

  const handleConfirmRestore = async (backup: BackupEntry) => {
    if (!pickerContainer) return;

    setRestoringId(backup.id);
    setTerminalOutput('');
    setShowTerminal(true);
    setResult(null);
    setPickerOpenId(null);

    try {
      const res = await window.backupRestoreAPI.restoreBackup({
        backupFilePath: backup.filePath,
        containerName: pickerContainer,
      });
      setResult(res);
    } catch (err: any) {
      setResult({ success: false, message: err.message || 'Restore failed' });
    } finally {
      setRestoringId(null);
    }
  };

  // ── render ────────────────────────────────────────────────────────────────

  return (
    <div className="max-w-2xl mx-auto space-y-6">
      {/* Header */}
      <div className="flex items-center gap-3">
        <div className="p-2 bg-amber-100 dark:bg-amber-900/30 rounded-lg">
          <RotateCcw className="h-6 w-6 text-amber-600 dark:text-amber-400" />
        </div>
        <div>
          <h2 className="text-xl font-semibold text-foreground">Restore Database</h2>
          <p className="text-sm text-muted-foreground">
            Restore Canvas PostgreSQL databases from a previous backup.
          </p>
        </div>
      </div>

      <Alert variant="warning">
        <div className="flex items-start gap-2">
          <AlertTriangle className="h-4 w-4 mt-0.5 flex-shrink-0 text-amber-600 dark:text-amber-500" />
          <AlertDescription className="text-sm">
            Restoring will overwrite the current <strong>canvas_production</strong>,{' '}
            <strong>canvas_development</strong>, and <strong>canvas_test</strong> databases.
            Make sure Canvas is not running before restoring.
          </AlertDescription>
        </div>
      </Alert>

      {/* Backup list */}
      <div className="bg-card border border-border rounded-lg overflow-hidden">
        <div className="flex items-center justify-between px-4 py-3 border-b border-border">
          <h3 className="text-sm font-medium text-foreground">Available Backups</h3>
          <Button
            variant="ghost"
            size="sm"
            onClick={loadBackups}
            disabled={isLoading || !!restoringId}
            className="h-7 w-7 p-0"
            title="Refresh backup list"
          >
            <RefreshCw className={`h-3.5 w-3.5 ${isLoading ? 'animate-spin' : ''}`} />
          </Button>
        </div>

        {isLoading ? (
          <div className="flex items-center gap-2 px-4 py-6 text-sm text-muted-foreground">
            <Loader2 className="h-4 w-4 animate-spin" />
            Loading backups…
          </div>
        ) : backups.length === 0 ? (
          <div className="flex flex-col items-center gap-2 px-4 py-8 text-center">
            <Database className="h-8 w-8 text-muted-foreground/40" />
            <p className="text-sm text-muted-foreground">No backups found.</p>
            <p className="text-xs text-muted-foreground">
              Create a backup first using the Backup tab.
            </p>
          </div>
        ) : (
          <ul className="divide-y divide-border">
            {backups.map((backup) => {
              const isThisRestoring = restoringId === backup.id;
              const isPickerOpen = pickerOpenId === backup.id;
              const anyRestoring = !!restoringId;

              return (
                <li key={backup.id} className="px-4 py-4 space-y-2">
                  {/* Row 1: date + container badge + default switch */}
                  <div className="flex items-center justify-between gap-3">
                    <div className="flex items-center gap-2 min-w-0">
                      <span className="text-sm font-medium text-foreground whitespace-nowrap">
                        {formatDate(backup.createdAt)}
                      </span>
                      <Badge variant="outline" className="shrink-0 font-mono text-xs">
                        {backup.containerName}
                      </Badge>
                    </div>

                    <div className="flex items-center gap-2 shrink-0">
                      <span className="text-xs text-muted-foreground whitespace-nowrap">
                        Default restore
                      </span>
                      <Switch
                        checked={!!backup.isDefault}
                        onCheckedChange={(checked) => handleDefaultToggle(backup, checked)}
                        disabled={anyRestoring}
                      />
                    </div>
                  </div>

                  {/* Row 2: notes */}
                  {backup.notes && (
                    <p className="text-xs text-muted-foreground leading-relaxed">
                      {backup.notes}
                    </p>
                  )}

                  {/* Row 3: actions */}
                  <div>
                    <div className="flex items-center gap-2">
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={() => (isPickerOpen ? closePicker() : openPicker(backup))}
                        disabled={anyRestoring}
                        className="h-7 text-xs gap-1.5"
                      >
                        {isThisRestoring ? (
                          <>
                            <Loader2 className="h-3.5 w-3.5 animate-spin" />
                            Restoring…
                          </>
                        ) : (
                          <>
                            <RotateCcw className="h-3.5 w-3.5" />
                            Restore
                            <ChevronDown
                              className={`h-3 w-3 transition-transform ${isPickerOpen ? 'rotate-180' : ''}`}
                            />
                          </>
                        )}
                      </Button>

                      {confirmDeleteId === backup.id ? (
                        <>
                          <span className="text-xs text-muted-foreground">Delete?</span>
                          <Button
                            size="sm"
                            variant="destructive"
                            onClick={() => handleDelete(backup.id)}
                            disabled={anyRestoring}
                            className="h-7 text-xs"
                          >
                            Confirm
                          </Button>
                          <Button
                            size="sm"
                            variant="ghost"
                            onClick={() => setConfirmDeleteId(null)}
                            className="h-7 text-xs"
                          >
                            Cancel
                          </Button>
                        </>
                      ) : (
                        <Button
                          size="sm"
                          variant="ghost"
                          onClick={() => setConfirmDeleteId(backup.id)}
                          disabled={anyRestoring}
                          className="h-7 text-xs text-muted-foreground hover:text-destructive gap-1.5"
                        >
                          <Trash2 className="h-3.5 w-3.5" />
                          Delete
                        </Button>
                      )}
                    </div>

                    {/* Inline container picker */}
                    {isPickerOpen && (
                      <ContainerPicker
                        containers={containers}
                        loadingContainers={loadingContainers}
                        value={pickerContainer}
                        onChange={setPickerContainer}
                        onConfirm={() => handleConfirmRestore(backup)}
                        onCancel={closePicker}
                        isRestoring={isThisRestoring}
                      />
                    )}
                  </div>
                </li>
              );
            })}
          </ul>
        )}
      </div>

      {/* Terminal output */}
      {showTerminal && (
        <div className="bg-card border border-border rounded-lg p-5 space-y-3">
          <div className="flex items-center justify-between">
            <h3 className="text-sm font-medium text-foreground">Restore Output</h3>
            <button
              onClick={() => { navigator.clipboard.writeText(terminalOutput); setCopiedOutput('restore'); setTimeout(() => setCopiedOutput(null), 2000); }}
              className="p-1 hover:bg-secondary rounded"
              title="Copy output"
            >
              {copiedOutput === 'restore' ? <Check className="h-3.5 w-3.5 text-green-600" /> : <Copy className="h-3.5 w-3.5 text-muted-foreground" />}
            </button>
          </div>
          <div
            ref={terminalRef}
            className="bg-black text-green-400 p-4 rounded font-mono text-xs overflow-auto max-h-80"
            style={{ whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}
          >
            {terminalOutput || 'Waiting for output…'}
          </div>
        </div>
      )}

      {/* Result alert */}
      {result && (
        <Alert variant={result.success ? 'success' : 'destructive'}>
          <div className="flex items-start gap-2">
            {result.success ? (
              <CheckCircle2 className="h-4 w-4 mt-0.5 shrink-0 text-green-600" />
            ) : (
              <XCircle className="h-4 w-4 mt-0.5 shrink-0" />
            )}
            <AlertDescription className="text-sm whitespace-pre-line">
              {result.message}
            </AlertDescription>
          </div>
        </Alert>
      )}
    </div>
  );
};
