'use client';

/**
 * RecordEditorDialog / RecordDeleteConfirm — create, edit, and delete forms
 * for AWS Route 53 DNS records, driving the plan 24-05 CRUD routes.
 *
 * Plain useState form fields — no react-hook-form (CLAUDE.md scopes that to
 * admin/auth forms; this matches the surrounding /admin/sync/* pages' plain-
 * state style).
 *
 * D-01: the type selector offers only the six writable record types. NS and
 * SOA never appear here — the server-side validator is the real gate
 * (lib/services/route53-record-validation.ts), this is UI consistency only.
 *
 * D-03: RecordDeleteConfirm's single confirmation dialog is a misclick guard
 * only. Deletion executes immediately on confirm — do not add a typed-name
 * check, a second reviewer step, or any staged/pending state; doing so would
 * turn this into exactly the multi-step gate D-03 rules out.
 *
 * T-24-20: both the save and delete controls disable themselves while their
 * own request is in flight, preventing a double-submit against the same
 * hosted zone from producing AWS's PriorRequestNotComplete.
 */

import { useState, useEffect } from 'react';
import { toast } from 'sonner';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Loader2, Plus, X, Trash2 } from 'lucide-react';
import type { Route53Record, Route53WritableType } from '@/lib/types/route53';

/** D-01: closed allowlist — must match
 * lib/services/route53-record-validation.ts WRITABLE_RECORD_TYPES exactly.
 * NS and SOA are zone-delegation records and are never offered here. */
const RECORD_TYPES: Route53WritableType[] = ['A', 'AAAA', 'CNAME', 'MX', 'TXT', 'SRV'];
const DEFAULT_TTL = 300;
const MAX_RESOURCE_RECORDS = 100;

interface WriteResponseBody {
  error?: string;
  message?: string;
  propagationStatus?: 'INSYNC' | 'PENDING';
}

// ── RecordEditorDialog (create / edit) ──────────────────────────────────────

export interface RecordEditorDialogProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  zoneId: string;
  mode: 'create' | 'edit';
  record?: Route53Record;
  onSaved: () => void;
}

export function RecordEditorDialog({
  open,
  onOpenChange,
  zoneId,
  mode,
  record,
  onSaved,
}: RecordEditorDialogProps) {
  const [name, setName] = useState('');
  const [type, setType] = useState<Route53WritableType>('A');
  const [ttl, setTtl] = useState(DEFAULT_TTL);
  const [values, setValues] = useState<string[]>(['']);
  const [submitting, setSubmitting] = useState(false);
  const [formError, setFormError] = useState<string | null>(null);

  useEffect(() => {
    if (!open) return;
    if (mode === 'edit' && record) {
      setName(record.name);
      setType((record.type as Route53WritableType) ?? 'A');
      setTtl(record.ttl ?? DEFAULT_TTL);
      const existing = (record.resourceRecords ?? []).map((r) => r.value);
      setValues(existing.length > 0 ? existing : ['']);
    } else {
      setName('');
      setType('A');
      setTtl(DEFAULT_TTL);
      setValues(['']);
    }
    setFormError(null);
  }, [open, mode, record]);

  const updateValue = (idx: number, v: string) => {
    setValues((prev) => prev.map((existing, i) => (i === idx ? v : existing)));
  };

  const addValue = () => {
    setValues((prev) => (prev.length >= MAX_RESOURCE_RECORDS ? prev : [...prev, '']));
  };

  const removeValue = (idx: number) => {
    setValues((prev) => (prev.length <= 1 ? prev : prev.filter((_, i) => i !== idx)));
  };

  const handleSubmit = async () => {
    setSubmitting(true);
    setFormError(null);
    try {
      const resourceRecords = values
        .map((v) => v.trim())
        .filter((v) => v.length > 0)
        .map((v) => ({ value: v }));

      const payload = { name, type, ttl: Number(ttl), resourceRecords };
      const url =
        mode === 'create'
          ? `/api/route53/zones/${zoneId}/records`
          : `/api/route53/zones/${zoneId}/records/${encodeURIComponent(record!.recordKey)}`;
      const method = mode === 'create' ? 'POST' : 'PATCH';

      const res = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      const body: WriteResponseBody = await res.json().catch(() => ({}));

      if (res.ok) {
        const propagationLabel = body.propagationStatus === 'INSYNC' ? 'Propagated' : 'Submitted — propagating';
        toast.success(`Record ${mode === 'create' ? 'created' : 'updated'} — ${propagationLabel}`);
        onSaved();
        onOpenChange(false);
        return;
      }

      const message = body.message || body.error || 'Failed to save record';
      setFormError(message);
      toast.error(message);
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Failed to save record';
      setFormError(message);
      toast.error(message);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={(next) => !submitting && onOpenChange(next)}>
      <DialogContent className="max-w-lg">
        <DialogHeader>
          <DialogTitle>{mode === 'create' ? 'New DNS record' : 'Edit DNS record'}</DialogTitle>
          <DialogDescription>
            {mode === 'create'
              ? 'Creates a resource record set in AWS Route 53.'
              : 'Name and type cannot be changed here — renaming a record set is a delete-plus-create, not an update.'}
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-4">
          <div className="space-y-1.5">
            <Label htmlFor="record-name">Name</Label>
            <Input
              id="record-name"
              value={name}
              onChange={(e) => setName(e.target.value)}
              placeholder="www.example.com"
              disabled={mode === 'edit'}
            />
          </div>

          <div className="grid grid-cols-2 gap-3">
            <div className="space-y-1.5">
              <Label htmlFor="record-type">Type</Label>
              <Select
                value={type}
                onValueChange={(v) => setType(v as Route53WritableType)}
                disabled={mode === 'edit'}
              >
                <SelectTrigger id="record-type">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {RECORD_TYPES.map((t) => (
                    <SelectItem key={t} value={t}>
                      {t}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            <div className="space-y-1.5">
              <Label htmlFor="record-ttl">TTL (seconds)</Label>
              <Input
                id="record-ttl"
                type="number"
                min={0}
                max={2147483647}
                value={ttl}
                onChange={(e) => setTtl(Number(e.target.value))}
              />
            </div>
          </div>

          <div className="space-y-1.5">
            <Label>Values</Label>
            <div className="space-y-2">
              {values.map((v, idx) => (
                <div key={idx} className="flex items-center gap-2">
                  <Input
                    value={v}
                    onChange={(e) => updateValue(idx, e.target.value)}
                    placeholder={type === 'MX' ? '10 mail.example.com' : 'value'}
                  />
                  <Button
                    type="button"
                    variant="ghost"
                    size="icon"
                    onClick={() => removeValue(idx)}
                    disabled={values.length <= 1}
                  >
                    <X className="w-4 h-4" />
                  </Button>
                </div>
              ))}
            </div>
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={addValue}
              disabled={values.length >= MAX_RESOURCE_RECORDS}
            >
              <Plus className="w-3.5 h-3.5 mr-1.5" />
              Add value
            </Button>
          </div>

          {formError && (
            <div className="text-sm text-destructive bg-destructive/10 rounded p-2">{formError}</div>
          )}
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)} disabled={submitting}>
            Cancel
          </Button>
          <Button onClick={handleSubmit} disabled={submitting || !name.trim()}>
            {submitting && <Loader2 className="w-4 h-4 mr-2 animate-spin" />}
            {mode === 'create' ? 'Create record' : 'Save changes'}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

// ── RecordDeleteConfirm ──────────────────────────────────────────────────────

export interface RecordDeleteConfirmProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  zoneId: string;
  record?: Route53Record;
  onSaved: () => void;
}

export function RecordDeleteConfirm({
  open,
  onOpenChange,
  zoneId,
  record,
  onSaved,
}: RecordDeleteConfirmProps) {
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (open) setError(null);
  }, [open]);

  if (!record) return null;

  const handleDelete = async () => {
    setSubmitting(true);
    setError(null);
    try {
      const res = await fetch(
        `/api/route53/zones/${zoneId}/records/${encodeURIComponent(record.recordKey)}`,
        { method: 'DELETE' }
      );
      const body: WriteResponseBody = await res.json().catch(() => ({}));

      if (res.ok) {
        toast.success('Record deleted');
        onSaved();
        onOpenChange(false);
        return;
      }

      const message = body.message || body.error || 'Failed to delete record';
      setError(message);
      toast.error(message);
    } catch (err) {
      const message = err instanceof Error ? err.message : 'Failed to delete record';
      setError(message);
      toast.error(message);
    } finally {
      setSubmitting(false);
    }
  };

  const values = (record.resourceRecords ?? []).map((r) => r.value).join(', ') || '—';

  return (
    <Dialog open={open} onOpenChange={(next) => !submitting && onOpenChange(next)}>
      <DialogContent className="max-w-md">
        <DialogHeader>
          <DialogTitle>Delete DNS record</DialogTitle>
          <DialogDescription>
            This dialog is a single misclick guard — confirming deletes the record from AWS
            Route 53 immediately, with no further review step.
          </DialogDescription>
        </DialogHeader>

        <div className="rounded-md border p-3 text-sm space-y-1">
          <div>
            <span className="text-muted-foreground">Name:</span> {record.name}
          </div>
          <div>
            <span className="text-muted-foreground">Type:</span> {record.type}
          </div>
          <div>
            <span className="text-muted-foreground">TTL:</span> {record.ttl ?? '—'}
          </div>
          <div>
            <span className="text-muted-foreground">Values:</span> {values}
          </div>
        </div>

        {error && <div className="text-sm text-destructive bg-destructive/10 rounded p-2">{error}</div>}

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)} disabled={submitting}>
            Cancel
          </Button>
          <Button variant="destructive" onClick={handleDelete} disabled={submitting}>
            {submitting ? (
              <Loader2 className="w-4 h-4 mr-2 animate-spin" />
            ) : (
              <Trash2 className="w-4 h-4 mr-2" />
            )}
            Delete record
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
