// Admin-detail tab content for the cockpit: a numbered section panel (read view) plus a
// per-section editor dialog that persists via updateProjectDetail() (shallow content merge).
import { useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import { Pencil } from 'lucide-react';

import {
  Button,
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  Input,
  Label,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Textarea,
  updateProjectDetail,
} from '@ump/shared';

import {
  displayValue,
  readContent,
  type DetailField,
  type DetailSection,
} from './detailConfig';
import { Field, FieldGrid, SectionPanel } from './DetailPrimitives';

type Content = Record<string, unknown>;

/** One administrative section, read view + an inline ✎ edit affordance (owner/admin only). */
export function DetailSectionPanel({
  section,
  content,
  projectId,
  canEdit,
}: {
  section: DetailSection;
  content: Content;
  projectId: string;
  canEdit: boolean;
}) {
  const [editing, setEditing] = useState(false);
  return (
    <>
      <SectionPanel
        index={section.index}
        title={section.title}
        action={
          canEdit ? (
            <Button variant="ghost" size="sm" className="h-8 gap-1.5 text-primary" onClick={() => setEditing(true)}>
              <Pencil size={14} /> Chỉnh sửa
            </Button>
          ) : undefined
        }
      >
        <FieldGrid>
          {section.fields.map((f) => (
            <Field
              key={f.key}
              label={f.label}
              full={f.full}
              value={displayValue(f, readContent(content, f.key))}
            />
          ))}
        </FieldGrid>
      </SectionPanel>

      {editing && (
        <DetailEditorDialog
          section={section}
          content={content}
          projectId={projectId}
          onClose={() => setEditing(false)}
        />
      )}
    </>
  );
}

/** Coerce a draft string back to the type the BE/JSONB should hold. */
function coerce(field: DetailField, raw: string): unknown {
  if (field.type === 'money' || field.type === 'number' || field.type === 'months') {
    const n = Number(raw);
    return raw.trim() === '' || Number.isNaN(n) ? '' : n;
  }
  return raw;
}

export function DetailEditorDialog({
  section,
  content,
  projectId,
  onClose,
}: {
  section: DetailSection;
  content: Content;
  projectId: string;
  onClose: () => void;
}) {
  const qc = useQueryClient();
  const [draft, setDraft] = useState<Record<string, string>>(() => {
    const d: Record<string, string> = {};
    for (const f of section.fields) {
      const v = readContent(content, f.key);
      d[f.key] = v === undefined || v === null ? '' : String(v);
    }
    return d;
  });

  const save = useMutation({
    mutationFn: () => {
      const patch: Record<string, unknown> = {};
      for (const f of section.fields) patch[f.key] = coerce(f, draft[f.key] ?? '');
      return updateProjectDetail(projectId, patch);
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ['cockpit', projectId] });
      toast.success('Đã lưu.');
      onClose();
    },
    onError: () => toast.error('Lưu thất bại.'),
  });

  const set = (k: string, v: string) => setDraft((d) => ({ ...d, [k]: v }));

  return (
    <Dialog open onOpenChange={(o) => !o && onClose()}>
      <DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-2xl">
        <DialogHeader>
          <DialogTitle className="font-serif">
            {section.index}. {section.title}
          </DialogTitle>
        </DialogHeader>
        <div className="grid grid-cols-1 gap-3.5 py-2 sm:grid-cols-2">
          {section.fields.map((f) => (
            <div key={f.key} className={f.full || f.type === 'textarea' ? 'sm:col-span-2' : undefined}>
              <Label className="mb-1 block text-xs font-semibold text-muted-foreground">{f.label}</Label>
              {f.type === 'textarea' ? (
                <Textarea className="min-h-20" value={draft[f.key] ?? ''} onChange={(e) => set(f.key, e.target.value)} />
              ) : f.type === 'select' ? (
                <Select value={draft[f.key] || undefined} onValueChange={(v) => set(f.key, v)}>
                  <SelectTrigger>
                    <SelectValue placeholder="—" />
                  </SelectTrigger>
                  <SelectContent>
                    {f.options?.map((o) => (
                      <SelectItem key={o} value={o}>
                        {o}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              ) : (
                <Input
                  type={f.type === 'date' ? 'date' : f.type === 'money' || f.type === 'months' ? 'number' : 'text'}
                  value={draft[f.key] ?? ''}
                  onChange={(e) => set(f.key, e.target.value)}
                />
              )}
            </div>
          ))}
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={onClose} disabled={save.isPending}>
            Hủy
          </Button>
          <Button onClick={() => save.mutate()} disabled={save.isPending}>
            Lưu
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
