import { AlertCircle, Loader2, Plus, RotateCcw, Server } from "lucide-react";
import { type BackupRecord } from "@/app/lib/api";
import { Button } from "../ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "../ui/dialog";
import { Input } from "../ui/input";
import { Switch } from "../ui/switch";
import {
  DAY_OF_WEEK,
  formatBytes,
  formatDate,
  FREQUENCY_OPTIONS,
  selectClass,
} from "./utils";

type CreateBackupDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  clients: string[];
  createClient: string;
  setCreateClient: (value: string) => void;
  createLabel: string;
  setCreateLabel: (value: string) => void;
  createPgUri: string;
  setCreatePgUri: (value: string) => void;
  createUseCustomUri: boolean;
  setCreateUseCustomUri: (value: boolean) => void;
  creating: boolean;
  onCreate: () => void;
};

export function CreateBackupDialog(props: CreateBackupDialogProps) {
  const {
    open,
    onOpenChange,
    clients,
    createClient,
    setCreateClient,
    createLabel,
    setCreateLabel,
    createPgUri,
    setCreatePgUri,
    createUseCustomUri,
    setCreateUseCustomUri,
    creating,
    onCreate,
  } = props;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Create backup</DialogTitle>
          <DialogDescription>
            Runs pg_dump and uploads a compressed archive to S3.
          </DialogDescription>
        </DialogHeader>
        <div className="space-y-4 py-2">
          <div className="flex items-center gap-3">
            <label className="text-xs font-medium text-foreground whitespace-nowrap">
              Use custom PG URI
            </label>
            <Switch
              checked={createUseCustomUri}
              onCheckedChange={setCreateUseCustomUri}
            />
          </div>
          {createUseCustomUri ? (
            <div className="space-y-1.5">
              <label className="text-xs font-medium text-foreground">
                Postgres URI
              </label>
              <Input
                placeholder="postgres://user:pass@host:5432/dbname"
                value={createPgUri}
                onChange={(e) => setCreatePgUri(e.target.value)}
                className="h-9 text-xs font-mono"
              />
              <div className="space-y-1.5 mt-3">
                <label className="text-xs font-medium text-foreground">
                  Client name
                  <span className="text-muted-foreground font-normal">
                    {" "}
                    (for labeling)
                  </span>
                </label>
                <Input
                  placeholder="e.g. staging-db"
                  value={createClient}
                  onChange={(e) => setCreateClient(e.target.value)}
                  className="h-9 text-xs"
                />
              </div>
            </div>
          ) : (
            <div className="space-y-1.5">
              <label className="text-xs font-medium text-foreground">
                Client
              </label>
              <select
                value={createClient}
                onChange={(e) => setCreateClient(e.target.value)}
                className={selectClass}
              >
                <option value="">Select client...</option>
                {clients.map((c) => (
                  <option key={c} value={c}>
                    {c}
                  </option>
                ))}
              </select>
            </div>
          )}
          <div className="space-y-1.5">
            <label className="text-xs font-medium text-foreground">
              Label
              <span className="text-muted-foreground font-normal">
                {" "}
                (optional)
              </span>
            </label>
            <Input
              placeholder="e.g. pre-deploy, weekly-2024-01-01"
              value={createLabel}
              onChange={(e) => setCreateLabel(e.target.value)}
              className="h-9 text-xs"
            />
          </div>
        </div>
        <DialogFooter>
          <Button
            variant="outline"
            size="sm"
            onClick={() => onOpenChange(false)}
          >
            Cancel
          </Button>
          <Button
            size="sm"
            onClick={onCreate}
            disabled={
              creating ||
              (!createUseCustomUri && !createClient) ||
              (createUseCustomUri && !createPgUri.trim())
            }
          >
            {creating && <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />}
            {creating ? "Creating..." : "Create backup"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

type RestoreBackupDialogProps = {
  target: BackupRecord | null;
  onOpenChange: (open: boolean) => void;
  clients: string[];
  restoreClient: string;
  setRestoreClient: (value: string) => void;
  restorePgUri: string;
  setRestorePgUri: (value: string) => void;
  restoreUseCustomUri: boolean;
  setRestoreUseCustomUri: (value: boolean) => void;
  restoring: boolean;
  onRestore: () => void;
};

export function RestoreBackupDialog(props: RestoreBackupDialogProps) {
  const {
    target,
    onOpenChange,
    clients,
    restoreClient,
    setRestoreClient,
    restorePgUri,
    setRestorePgUri,
    restoreUseCustomUri,
    setRestoreUseCustomUri,
    restoring,
    onRestore,
  } = props;

  return (
    <Dialog open={!!target} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Restore backup</DialogTitle>
          <DialogDescription>
            Downloads from S3 and runs pg_restore. Existing data will be
            replaced.
          </DialogDescription>
        </DialogHeader>
        {target && (
          <div className="space-y-4 py-2">
            <div className="rounded-lg border border-border bg-muted/40 p-4 text-xs space-y-1.5">
              <p>
                <span className="text-muted-foreground">Backup: </span>
                <span className="font-medium">{target.label ?? target.id}</span>
              </p>
              <p>
                <span className="text-muted-foreground">Created: </span>
                {formatDate(target.created_at)}
              </p>
              <p>
                <span className="text-muted-foreground">Size: </span>
                <span className="tabular-nums">
                  {formatBytes(target.size_bytes)}
                </span>
              </p>
            </div>
            <div className="flex items-center gap-3">
              <label className="text-xs font-medium text-foreground whitespace-nowrap">
                Use custom PG URI
              </label>
              <Switch
                checked={restoreUseCustomUri}
                onCheckedChange={setRestoreUseCustomUri}
              />
            </div>
            {restoreUseCustomUri ? (
              <div className="space-y-1.5">
                <label className="text-xs font-medium text-foreground">
                  Target Postgres URI
                </label>
                <Input
                  placeholder="postgres://user:pass@host:5432/dbname"
                  value={restorePgUri}
                  onChange={(e) => setRestorePgUri(e.target.value)}
                  className="h-9 text-xs font-mono"
                />
              </div>
            ) : (
              <div className="space-y-1.5">
                <label className="text-xs font-medium text-foreground">
                  Restore target client
                </label>
                <select
                  value={restoreClient}
                  onChange={(e) => setRestoreClient(e.target.value)}
                  className={selectClass}
                >
                  <option value="">Select client...</option>
                  {clients.map((c) => (
                    <option key={c} value={c}>
                      {c}
                    </option>
                  ))}
                </select>
              </div>
            )}
            <div className="flex items-start gap-2 rounded-lg border border-destructive/30 bg-destructive/5 p-3 text-xs text-destructive">
              <AlertCircle className="h-3.5 w-3.5 shrink-0 mt-0.5" />
              <span>
                This will overwrite all data in the target. This cannot be
                undone.
              </span>
            </div>
          </div>
        )}
        <DialogFooter>
          <Button
            variant="outline"
            size="sm"
            onClick={() => onOpenChange(false)}
          >
            Cancel
          </Button>
          <Button
            size="sm"
            variant="destructive"
            onClick={onRestore}
            disabled={
              restoring ||
              (!restoreUseCustomUri && !restoreClient) ||
              (restoreUseCustomUri && !restorePgUri.trim())
            }
          >
            {restoring && <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />}
            {restoring ? "Restoring..." : "Restore"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

type DeleteBackupDialogProps = {
  target: BackupRecord | null;
  deleting: boolean;
  onOpenChange: (open: boolean) => void;
  onDelete: () => void;
};

export function DeleteBackupDialog({
  target,
  deleting,
  onOpenChange,
  onDelete,
}: DeleteBackupDialogProps) {
  return (
    <Dialog open={!!target} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Delete backup</DialogTitle>
          <DialogDescription>
            This will permanently delete the backup from S3.
          </DialogDescription>
        </DialogHeader>
        {target && (
          <div className="rounded-lg border border-border bg-muted/40 p-4 text-xs space-y-1.5">
            <p>
              <span className="text-muted-foreground">Backup: </span>
              <span className="font-medium">{target.label ?? target.id}</span>
            </p>
            <p>
              <span className="text-muted-foreground">Size: </span>
              <span className="tabular-nums">
                {formatBytes(target.size_bytes)}
              </span>
            </p>
          </div>
        )}
        <DialogFooter>
          <Button
            variant="outline"
            size="sm"
            onClick={() => onOpenChange(false)}
          >
            Cancel
          </Button>
          <Button
            size="sm"
            variant="destructive"
            onClick={onDelete}
            disabled={deleting}
          >
            {deleting && <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />}
            {deleting ? "Deleting..." : "Delete"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

type ScheduleDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  clients: string[];
  schedClient: string;
  setSchedClient: (value: string) => void;
  schedFrequency: string;
  setSchedFrequency: (value: string) => void;
  schedTime: string;
  setSchedTime: (value: string) => void;
  schedDay: number;
  setSchedDay: (value: number) => void;
  schedDayOfMonth: number;
  setSchedDayOfMonth: (value: number) => void;
  schedLabel: string;
  setSchedLabel: (value: string) => void;
  creatingSchedule: boolean;
  onCreate: () => void;
};

export function ScheduleDialog(props: ScheduleDialogProps) {
  const {
    open,
    onOpenChange,
    clients,
    schedClient,
    setSchedClient,
    schedFrequency,
    setSchedFrequency,
    schedTime,
    setSchedTime,
    schedDay,
    setSchedDay,
    schedDayOfMonth,
    setSchedDayOfMonth,
    schedLabel,
    setSchedLabel,
    creatingSchedule,
    onCreate,
  } = props;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Create backup schedule</DialogTitle>
          <DialogDescription>
            Set up a recurring backup job saved to the server.
          </DialogDescription>
        </DialogHeader>
        <div className="space-y-4 py-2">
          <div className="space-y-1.5">
            <label className="text-xs font-medium text-foreground">
              Client
            </label>
            <select
              value={schedClient}
              onChange={(e) => setSchedClient(e.target.value)}
              className={selectClass}
            >
              <option value="">Select client...</option>
              {clients.map((c) => (
                <option key={c} value={c}>
                  {c}
                </option>
              ))}
            </select>
          </div>
          <div className="space-y-1.5">
            <label className="text-xs font-medium text-foreground">
              Frequency
            </label>
            <select
              value={schedFrequency}
              onChange={(e) => setSchedFrequency(e.target.value)}
              className={selectClass}
            >
              {FREQUENCY_OPTIONS.map((opt) => (
                <option key={opt.value} value={opt.value}>
                  {opt.label}
                </option>
              ))}
            </select>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div className="space-y-1.5">
              <label className="text-xs font-medium text-foreground">
                Time
              </label>
              <Input
                type="time"
                value={schedTime}
                onChange={(e) => setSchedTime(e.target.value)}
                className="h-9 text-xs"
              />
            </div>
            {schedFrequency === "weekly" && (
              <div className="space-y-1.5">
                <label className="text-xs font-medium text-foreground">
                  Day of week
                </label>
                <select
                  value={schedDay}
                  onChange={(e) => setSchedDay(Number(e.target.value))}
                  className={selectClass}
                >
                  {DAY_OF_WEEK.map((day, i) => (
                    <option key={i} value={i}>
                      {day}
                    </option>
                  ))}
                </select>
              </div>
            )}
            {schedFrequency === "monthly" && (
              <div className="space-y-1.5">
                <label className="text-xs font-medium text-foreground">
                  Day of month
                </label>
                <Input
                  type="number"
                  min={1}
                  max={28}
                  value={schedDayOfMonth}
                  onChange={(e) => setSchedDayOfMonth(Number(e.target.value))}
                  className="h-9 text-xs"
                />
              </div>
            )}
          </div>
          <div className="space-y-1.5">
            <label className="text-xs font-medium text-foreground">
              Label
              <span className="text-muted-foreground font-normal">
                {" "}
                (optional)
              </span>
            </label>
            <Input
              value={schedLabel}
              onChange={(e) => setSchedLabel(e.target.value)}
              placeholder="e.g. nightly-backup"
              className="h-9 text-xs"
            />
          </div>
        </div>
        <DialogFooter>
          <Button
            variant="outline"
            size="sm"
            onClick={() => onOpenChange(false)}
          >
            Cancel
          </Button>
          <Button
            size="sm"
            onClick={onCreate}
            disabled={!schedClient || creatingSchedule}
          >
            {creatingSchedule && (
              <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />
            )}
            Create schedule
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

type AddClientDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  newClientName: string;
  setNewClientName: (value: string) => void;
  newClientPgUri: string;
  setNewClientPgUri: (value: string) => void;
  addingClient: boolean;
  onAddClient: () => void;
};

export function AddClientDialog(props: AddClientDialogProps) {
  const {
    open,
    onOpenChange,
    newClientName,
    setNewClientName,
    newClientPgUri,
    setNewClientPgUri,
    addingClient,
    onAddClient,
  } = props;

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Add database client</DialogTitle>
          <DialogDescription>
            Register a new Postgres database using its connection URI.
          </DialogDescription>
        </DialogHeader>
        <div className="space-y-4 py-2">
          <div className="space-y-1.5">
            <label className="text-xs font-medium text-foreground">
              Client name
            </label>
            <Input
              placeholder="e.g. production, staging"
              value={newClientName}
              onChange={(e) => setNewClientName(e.target.value)}
              className="h-9 text-xs"
            />
          </div>
          <div className="space-y-1.5">
            <label className="text-xs font-medium text-foreground">
              Postgres URI
            </label>
            <Input
              placeholder="postgres://user:pass@host:5432/dbname"
              value={newClientPgUri}
              onChange={(e) => setNewClientPgUri(e.target.value)}
              className="h-9 text-xs font-mono"
            />
          </div>
        </div>
        <DialogFooter>
          <Button
            variant="outline"
            size="sm"
            onClick={() => onOpenChange(false)}
          >
            Cancel
          </Button>
          <Button
            size="sm"
            onClick={onAddClient}
            disabled={
              addingClient || !newClientName.trim() || !newClientPgUri.trim()
            }
          >
            {addingClient && (
              <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />
            )}
            <Plus className="h-3 w-3 mr-1" />
            Add client
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
