import { useEffect, useState } from 'react';
import { api, SyncPair, Machine } from '../api/client';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Label } from '@/components/ui/Label';
import { Textarea } from '@/components/ui/Textarea';
import { Select, SelectValue, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/Select';
import {
  Modal,
  ModalContent,
  ModalHeader,
  ModalTitle,
  ModalDescription,
  ModalBody,
  ModalFooter,
} from '@/components/ui/Modal';
import { PageHeader } from '@/components/ui/PageHeader';
import {
  Table,
  TableHeader,
  TableBody,
  TableHead,
  TableRow,
  TableCell,
} from '@/components/ui/Table';
import { EmptyState } from '@/components/ui/EmptyState';
import { Badge } from '@/components/ui/Badge';
import { Card } from '@/components/ui/Card';
import { Play, Trash2, Plus, GitCompare, ArrowRight, ArrowLeft, Pencil } from 'lucide-react';
import { toast } from 'sonner';
import { cn } from '@/lib/utils';

type SyncPairForm = {
  id: number | undefined;
  name: string;
  source_machine_id: number | null;
  source_path: string;
  dest_machine_id: number | null;
  dest_path: string;
  direction: 'push' | 'pull' | 'mirror';
  rsync_flags: string;
  exclude_patterns: string;
  enabled: boolean;
};

const defaultForm: SyncPairForm = {
  id: undefined,
  name: '',
  source_machine_id: null,
  source_path: '',
  dest_machine_id: null,
  dest_path: '',
  direction: 'push',
  rsync_flags: '-aP',
  exclude_patterns: '',
  enabled: true,
};

export default function SyncPairs() {
  const [pairs, setPairs] = useState<SyncPair[]>([]);
  const [machines, setMachines] = useState<Machine[]>([]);
  const [modalOpen, setModalOpen] = useState(false);
  const [deleteId, setDeleteId] = useState<number | null>(null);
  const [form, setForm] = useState<SyncPairForm>(defaultForm);
  const [running, setRunning] = useState<Record<number, boolean>>({});
  const [loading, setLoading] = useState(false);

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

  async function load() {
    try {
      const [p, m] = await Promise.all([
        api<SyncPair[]>('/api/sync-pairs'),
        api<Machine[]>('/api/machines'),
      ]);
      setPairs(p);
      setMachines(m);
    } catch {}
  }

  function openCreate() {
    setForm(defaultForm);
    setModalOpen(true);
  }

  function openEdit(p: SyncPair) {
    setForm({
      id: p.id,
      name: p.name,
      source_machine_id: p.source_machine_id,
      source_path: p.source_path,
      dest_machine_id: p.dest_machine_id,
      dest_path: p.dest_path,
      direction: p.direction as 'push' | 'pull' | 'mirror',
      rsync_flags: p.rsync_flags,
      exclude_patterns: p.exclude_patterns || '',
      enabled: p.enabled,
    });
    setModalOpen(true);
  }

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!form.name.trim()) {
      toast.error('Name is required');
      return;
    }
    if (!form.source_path.trim() || !form.dest_path.trim()) {
      toast.error('Source and destination paths are required');
      return;
    }
    setLoading(true);
    try {
      await api(form.id ? `/api/sync-pairs/${form.id}` : '/api/sync-pairs', {
        method: form.id ? 'PUT' : 'POST',
        body: {
          name: form.name,
          source_machine_id: form.source_machine_id,
          source_path: form.source_path,
          dest_machine_id: form.dest_machine_id,
          dest_path: form.dest_path,
          direction: form.direction,
          rsync_flags: form.rsync_flags,
          exclude_patterns: form.exclude_patterns,
          enabled: form.enabled,
        },
      });
      setModalOpen(false);
      toast.success(form.id ? 'Sync pair updated' : 'Sync pair created');
      load();
    } catch (e: unknown) {
      toast.error((e as Error).message);
    } finally {
      setLoading(false);
    }
  }

  async function trigger(pairId: number) {
    setRunning(r => ({ ...r, [pairId]: true }));
    try {
      await api(`/api/sync-pairs/${pairId}/run`, { method: 'POST' });
      toast.success('Job triggered');
      load();
    } catch (e: unknown) {
      toast.error((e as Error).message);
    } finally {
      setRunning(r => ({ ...r, [pairId]: false }));
    }
  }

  async function handleDelete() {
    if (deleteId === null) return;
    try {
      await api(`/api/sync-pairs/${deleteId}`, { method: 'DELETE' });
      toast.success('Sync pair deleted');
      setDeleteId(null);
      load();
    } catch (e: unknown) {
      toast.error((e as Error).message);
    }
  }

  function machineName(id: number | null) {
    if (!id) return 'Local server';
    const m = machines.find(m => m.id === id);
    return m ? m.name : `Machine ${id}`;
  }

  const directionIcon = (dir: string) => {
    if (dir === 'push') return <ArrowRight className="h-3 w-3" />
    if (dir === 'pull') return <ArrowLeft className="h-3 w-3" />
    return <GitCompare className="h-3 w-3" />
  }

  return (
    <div className="space-y-6">
      <PageHeader
        title="Sync Pairs"
        description="Define source and destination for rsync operations"
        actions={
          <Button onClick={openCreate} size="sm">
            <Plus className="h-4 w-4" />
            Add Sync Pair
          </Button>
        }
      />

      <Card>
        <div className="p-0">
          {pairs.length === 0 ? (
            <EmptyState
              icon={<GitCompare className="h-5 w-5" />}
              title="No sync pairs"
              description="Create a sync pair to define data transfer between machines"
              action={
                <Button onClick={openCreate} size="sm">
                  <Plus className="h-4 w-4" />
                  Add Sync Pair
                </Button>
              }
            />
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>Name</TableHead>
                  <TableHead>Source</TableHead>
                  <TableHead>Destination</TableHead>
                  <TableHead>Direction</TableHead>
                  <TableHead>Enabled</TableHead>
                  <TableHead className="w-28">Actions</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {pairs.map(p => (
                  <TableRow key={p.id}>
                    <TableCell className="font-medium">{p.name}</TableCell>
                    <TableCell>
                      <span className="font-mono text-xs text-fg-muted">
                        {machineName(p.source_machine_id)}:{p.source_path}
                      </span>
                    </TableCell>
                    <TableCell>
                      <span className="font-mono text-xs text-fg-muted">
                        {machineName(p.dest_machine_id)}:{p.dest_path}
                      </span>
                    </TableCell>
                    <TableCell>
                      <div className="flex items-center gap-1.5">
                        {directionIcon(p.direction)}
                        <span className="text-xs capitalize">{p.direction}</span>
                      </div>
                    </TableCell>
                    <TableCell>
                      {p.enabled ? (
                        <Badge variant="success" label="Active" />
                      ) : (
                        <Badge variant="neutral" label="Disabled" />
                      )}
                    </TableCell>
                    <TableCell>
                      <div className="flex items-center gap-1">
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          onClick={() => openEdit(p)}
                          className="text-fg-muted hover:text-fg hover:bg-surface-raised"
                          title="Edit"
                        >
                          <Pencil className="h-3.5 w-3.5" />
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          onClick={() => trigger(p.id)}
                          disabled={running[p.id]}
                          loading={running[p.id]}
                          className="text-emerald-400 hover:text-emerald-300 hover:bg-emerald-500/10"
                          title="Run now"
                        >
                          <Play className="h-3.5 w-3.5" />
                        </Button>
                        <Button
                          variant="ghost"
                          size="icon-sm"
                          onClick={() => setDeleteId(p.id)}
                          className="text-rose-400 hover:text-rose-300 hover:bg-rose-500/10"
                          title="Delete"
                        >
                          <Trash2 className="h-3.5 w-3.5" />
                        </Button>
                      </div>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </div>
      </Card>

      <Modal open={modalOpen} onOpenChange={setModalOpen}>
        <ModalContent size="lg">
          <ModalHeader>
            <ModalTitle>{form.id ? 'Edit Sync Pair' : 'Add Sync Pair'}</ModalTitle>
            <ModalDescription>
              {form.id
                ? 'Update the configuration for this sync pair'
                : 'Define a new source and destination for data syncing'}
            </ModalDescription>
          </ModalHeader>
          <form onSubmit={handleSubmit}>
            <ModalBody className="space-y-4">
              <div className="space-y-1.5">
                <Label htmlFor="sp-name" required>
                  Name
                </Label>
                <Input
                  id="sp-name"
                  placeholder="backup-photos"
                  value={form.name}
                  onChange={e => setForm({ ...form, name: e.target.value })}
                />
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1.5">
                  <Label htmlFor="sp-source-machine">Source Machine</Label>
                  <Select
                    value={form.source_machine_id?.toString() ?? ''}
                    onValueChange={v =>
                      setForm({ ...form, source_machine_id: v ? Number(v) : null })
                    }
                  >
                    <SelectTrigger id="sp-source-machine">
                      <SelectValue placeholder="Local server" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="">Local server</SelectItem>
                      {machines.map(m => (
                        <SelectItem key={m.id} value={m.id.toString()}>
                          {m.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="sp-dest-machine">Dest Machine</Label>
                  <Select
                    value={form.dest_machine_id?.toString() ?? ''}
                    onValueChange={v =>
                      setForm({ ...form, dest_machine_id: v ? Number(v) : null })
                    }
                  >
                    <SelectTrigger id="sp-dest-machine">
                      <SelectValue placeholder="Local server" />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="">Local server</SelectItem>
                      {machines.map(m => (
                        <SelectItem key={m.id} value={m.id.toString()}>
                          {m.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1.5">
                  <Label htmlFor="sp-source-path" required>
                    Source Path
                  </Label>
                  <Input
                    id="sp-source-path"
                    placeholder="/data/photos"
                    value={form.source_path}
                    onChange={e =>
                      setForm({ ...form, source_path: e.target.value })
                    }
                  />
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="sp-dest-path" required>
                    Dest Path
                  </Label>
                  <Input
                    id="sp-dest-path"
                    placeholder="/backup/photos"
                    value={form.dest_path}
                    onChange={e =>
                      setForm({ ...form, dest_path: e.target.value })
                    }
                  />
                </div>
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1.5">
                  <Label htmlFor="sp-direction">Direction</Label>
                  <Select
                    value={form.direction}
                    onValueChange={(v: 'push' | 'pull' | 'mirror') =>
                      setForm({ ...form, direction: v })
                    }
                  >
                    <SelectTrigger id="sp-direction">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="push">Push</SelectItem>
                      <SelectItem value="pull">Pull</SelectItem>
                      <SelectItem value="mirror">Mirror</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
                <div className="space-y-1.5">
                  <Label htmlFor="sp-rsync-flags">Rsync Flags</Label>
                  <Input
                    id="sp-rsync-flags"
                    placeholder="-aP"
                    value={form.rsync_flags}
                    onChange={e =>
                      setForm({ ...form, rsync_flags: e.target.value })
                    }
                  />
                </div>
              </div>
              <div className="space-y-1.5">
                <Label htmlFor="sp-exclude">Exclude Patterns</Label>
                <Textarea
                  id="sp-exclude"
                  placeholder="node_modules&#10;.git&#10;*.tmp"
                  value={form.exclude_patterns}
                  onChange={e =>
                    setForm({ ...form, exclude_patterns: e.target.value })
                  }
                  className="font-mono text-xs"
                  rows={3}
                />
                <p className="text-xs text-fg-subtle">
                  One pattern per line
                </p>
              </div>
              <div
                className={cn(
                  'flex items-center gap-2 rounded-card p-3 transition-colors',
                  form.enabled
                    ? 'bg-accent/5 border border-accent/20'
                    : 'bg-surface-raised border border-border'
                )}
              >
                <input
                  type="checkbox"
                  id="sp-enabled"
                  checked={form.enabled}
                  onChange={e => setForm({ ...form, enabled: e.target.checked })}
                  className="h-4 w-4 rounded border-border accent-accent"
                />
                <Label htmlFor="sp-enabled" className="cursor-pointer mb-0">
                  Enable this sync pair
                </Label>
              </div>
            </ModalBody>
            <ModalFooter>
              <Button
                type="button"
                variant="secondary"
                onClick={() => setModalOpen(false)}
              >
                Cancel
              </Button>
              <Button type="submit" loading={loading}>
                {form.id ? 'Save Changes' : 'Add Sync Pair'}
              </Button>
            </ModalFooter>
          </form>
        </ModalContent>
      </Modal>

      <Modal open={deleteId !== null} onOpenChange={v => !v && setDeleteId(null)}>
        <ModalContent size="sm">
          <ModalHeader>
            <ModalTitle>Delete Sync Pair</ModalTitle>
            <ModalDescription>
              Are you sure you want to delete this sync pair? All associated
              job history will remain.
            </ModalDescription>
          </ModalHeader>
          <ModalFooter>
            <Button variant="secondary" onClick={() => setDeleteId(null)}>
              Cancel
            </Button>
            <Button variant="danger-solid" onClick={handleDelete}>
              Delete
            </Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
    </div>
  );
}
