"use client";

import { useEffect, useState } from "react";
import { ArrowLeftRight, Link2, Plus, Trash2 } from "lucide-react";
import { toast } from "sonner";
import { ApiError, apiSend } from "@/lib/api";
import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";

const ENDPOINT = "/master/jenis-surat-dinas";

const TIPE = [
  { value: "", label: "Pilihan Tipe" },
  { value: "text", label: "Input Teks" },
  { value: "number", label: "Input Angka" },
  { value: "email", label: "Input Email" },
  { value: "url", label: "Input Url" },
  { value: "date", label: "Input Tanggal" },
  { value: "time", label: "Input Jam" },
  { value: "textarea", label: "Text Area" },
  { value: "select-manual", label: "Pilihan (Kustom)" },
  { value: "select-otomatis", label: "Pilihan (Referensi)" },
  { value: "hari", label: "Input Hari" },
  { value: "hari-tanggal", label: "Input Hari dan Tanggal" },
];

const REFERENSI = [
  { value: "", label: "Pilihan Referensi" },
  { value: "tweb_penduduk_sex", label: "Jenis Kelamin" },
  { value: "tweb_penduduk_hubungan", label: "Status Hubungan Dalam Keluarga" },
  { value: "tweb_rtm_hubungan", label: "Status Hubungan Dalam Rumah Tangga" },
  { value: "tweb_penduduk_agama", label: "Agama" },
  { value: "tweb_penduduk_pendidikan_kk", label: "Pendidikan Dalam KK" },
  { value: "tweb_penduduk_pendidikan", label: "Pendidikan Sedang Ditempuh" },
  { value: "tweb_penduduk_pekerjaan", label: "Pekerjaan" },
  { value: "tweb_penduduk_kawin", label: "Status Perkawinan" },
  { value: "tweb_penduduk_warganegara", label: "Warga Negara" },
  { value: "tweb_golongan_darah", label: "Golongan Darah" },
  { value: "tweb_penduduk_status", label: "Status Penduduk" },
  { value: "tweb_status_dasar", label: "Status Dasar" },
  { value: "tweb_cacat", label: "Cacat" },
  { value: "tweb_cara_kb", label: "Cara KB" },
  { value: "tweb_penduduk_asuransi", label: "Asuransi" },
  { value: "tweb_wil_clusterdesa", label: "Dusun" },
  { value: "tweb_keluarga_sejahtera", label: "Keluarga Sejahtera" },
];

const KOLOM = Array.from({ length: 12 }, (_, index) => ({
  value: String(index + 1),
  label: `col-${index + 1}`,
}));

export interface KodeIsian {
  tipe: string;
  nama: string;
  label: string;
  deskripsi: string;
  required: boolean;
  kolom: string;
  atribut: string;
  pilihan: string;
  referensi: string;
  kaitkan: string;
}

export interface BagianForm {
  judul: string;
  label: string;
  info: string;
  prefix: string;
  kode: KodeIsian[];
}

export interface JenisSuratRinci {
  id: number;
  nama: string;
  bagianForm?: string | null;
}

function kodeKosong(): KodeIsian {
  return {
    tipe: "text",
    nama: "",
    label: "",
    deskripsi: "",
    required: true,
    kolom: "6",
    atribut: "",
    pilihan: "",
    referensi: "",
    kaitkan: "",
  };
}

function bagianKosong(): BagianForm {
  return { judul: "Utama", label: "Pemohon", info: "", prefix: "", kode: [kodeKosong()] };
}

function normalisasiKode(raw: unknown): KodeIsian {
  const data = (raw ?? {}) as Record<string, unknown>;
  const teks = (key: string) => (data[key] === null || data[key] === undefined ? "" : String(data[key]));
  return {
    tipe: teks("tipe") || "text",
    nama: teks("nama"),
    label: teks("label"),
    deskripsi: teks("deskripsi"),
    required: data.required !== false,
    kolom: teks("kolom") || "6",
    atribut: teks("atribut"),
    pilihan: teks("pilihan"),
    referensi: teks("referensi"),
    kaitkan: teks("kaitkan"),
  };
}

function normalisasiBagian(raw: unknown): BagianForm[] {
  if (!raw) return [bagianKosong()];
  let isi: unknown = raw;
  if (typeof raw === "string") {
    try {
      isi = JSON.parse(raw);
    } catch {
      return [bagianKosong()];
    }
  }
  if (!Array.isArray(isi) || !isi.length) return [bagianKosong()];
  return isi.map((item) => {
    const data = (item ?? {}) as Record<string, unknown>;
    const teks = (key: string) => (data[key] === null || data[key] === undefined ? "" : String(data[key]));
    return {
      judul: teks("judul") || "Utama",
      label: teks("label"),
      info: teks("info"),
      prefix: teks("prefix"),
      kode: Array.isArray(data.kode) ? data.kode.map(normalisasiKode) : [],
    };
  });
}

export function BagianFormBuilder({
  target,
  onClose,
  onSaved,
}: {
  target: JenisSuratRinci | null;
  onClose: () => void;
  onSaved: () => void;
}) {
  const [bagian, setBagian] = useState<BagianForm[]>([bagianKosong()]);
  const [aktif, setAktif] = useState(0);
  const [saving, setSaving] = useState(false);

  useEffect(() => {
    if (!target) return;
    setBagian(normalisasiBagian(target.bagianForm));
    setAktif(0);
  }, [target]);

  const semuaNama = bagian.flatMap((item) => item.kode.map((kode) => kode.nama)).filter(Boolean);

  function ubahBagian(index: number, patch: Partial<BagianForm>) {
    setBagian((current) =>
      current.map((item, posisi) => (posisi === index ? { ...item, ...patch } : item)),
    );
  }

  function ubahKode(indexBagian: number, indexKode: number, patch: Partial<KodeIsian>) {
    setBagian((current) =>
      current.map((item, posisi) =>
        posisi === indexBagian
          ? {
              ...item,
              kode: item.kode.map((kode, nomor) =>
                nomor === indexKode ? { ...kode, ...patch } : kode,
              ),
            }
          : item,
      ),
    );
  }

  function tambahBagian() {
    setBagian((current) => [
      ...current,
      { judul: `Bagian ${current.length + 1}`, label: "", info: "", prefix: "", kode: [kodeKosong()] },
    ]);
    setAktif(bagian.length);
  }

  function hapusBagian(index: number) {
    if (bagian.length <= 1) {
      toast.error("Minimal satu bagian form harus tersedia");
      return;
    }
    setBagian((current) => current.filter((_, posisi) => posisi !== index));
    setAktif((current) => Math.max(0, current - (index <= current ? 1 : 0)));
  }

  function tambahKode(indexBagian: number) {
    setBagian((current) =>
      current.map((item, posisi) =>
        posisi === indexBagian ? { ...item, kode: [...item.kode, kodeKosong()] } : item,
      ),
    );
  }

  function hapusKode(indexBagian: number, indexKode: number) {
    setBagian((current) =>
      current.map((item, posisi) =>
        posisi === indexBagian
          ? { ...item, kode: item.kode.filter((_, nomor) => nomor !== indexKode) }
          : item,
      ),
    );
  }

  function pindahkan(indexBagian: number, indexKode: number, tujuan: number) {
    if (tujuan === indexBagian) return;
    setBagian((current) => {
      const kode = current[indexBagian]?.kode[indexKode];
      if (!kode) return current;
      return current.map((item, posisi) => {
        if (posisi === indexBagian) {
          return { ...item, kode: item.kode.filter((_, nomor) => nomor !== indexKode) };
        }
        if (posisi === tujuan) return { ...item, kode: [...item.kode, kode] };
        return item;
      });
    });
  }

  async function simpan() {
    if (!target) return;
    setSaving(true);
    try {
      await apiSend(`${ENDPOINT}/${target.id}`, "PATCH", {
        bagianForm: JSON.stringify(bagian),
      });
      toast.success("Kode isian surat dinas disimpan");
      onSaved();
      onClose();
    } catch (error) {
      toast.error(error instanceof ApiError ? error.message : "Gagal menyimpan kode isian");
    } finally {
      setSaving(false);
    }
  }

  const current = bagian[aktif] ?? bagian[0];

  return (
    <Dialog open={Boolean(target)} onOpenChange={(open) => !open && onClose()}>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-3xl">
        <DialogHeader>
          <DialogTitle>Kode Isian — {target?.nama ?? ""}</DialogTitle>
          <DialogDescription>
            Susun bagian form dan kode isian yang dipakai saat membuat surat dinas jenis ini.
          </DialogDescription>
        </DialogHeader>

        <div className="flex flex-wrap items-end gap-2">
          <div className="flex flex-wrap gap-1">
            {bagian.map((item, index) => (
              <button
                key={`${item.judul}-${index}`}
                type="button"
                onClick={() => setAktif(index)}
                className={`rounded-t-md border border-b-0 px-3 py-1.5 text-sm ${
                  index === aktif
                    ? "bg-background font-semibold"
                    : "bg-muted text-muted-foreground"
                }`}
              >
                {item.judul || `Bagian ${index + 1}`}
              </button>
            ))}
          </div>
          <div className="ml-auto flex gap-2">
            <Button type="button" variant="outline" size="sm" onClick={tambahBagian}>
              <Plus className="h-4 w-4" /> Tambah Bagian Form
            </Button>
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={() => hapusBagian(aktif)}
            >
              <Trash2 className="h-4 w-4" /> Hapus Bagian Form
            </Button>
          </div>
        </div>

        {current && (
          <div className="space-y-4 rounded-lg border p-3">
            <div className="grid gap-3 sm:grid-cols-2">
              <div className="space-y-1.5">
                <Label>Judul Bagian</Label>
                <Input
                  value={current.judul}
                  onChange={(event) => ubahBagian(aktif, { judul: event.target.value })}
                />
              </div>
              <div className="space-y-1.5">
                <Label>Label Bagian</Label>
                <Input
                  value={current.label}
                  onChange={(event) => ubahBagian(aktif, { label: event.target.value })}
                />
              </div>
              <div className="space-y-1.5">
                <Label>Info Bagian</Label>
                <Input
                  value={current.info}
                  onChange={(event) => ubahBagian(aktif, { info: event.target.value })}
                />
              </div>
              <div className="space-y-1.5">
                <Label>Prefix Bagian</Label>
                <Input
                  value={current.prefix}
                  onChange={(event) => ubahBagian(aktif, { prefix: event.target.value })}
                />
              </div>
            </div>

            <div className="space-y-3">
              {current.kode.map((kode, indexKode) => (
                <div key={indexKode} className="space-y-3 rounded-md border bg-muted/30 p-3">
                  <div className="flex items-center justify-between">
                    <p className="text-sm font-semibold">Kode Isian #{indexKode + 1}</p>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      onClick={() => hapusKode(aktif, indexKode)}
                    >
                      <Trash2 className="h-4 w-4" /> Hapus
                    </Button>
                  </div>
                  <div className="grid gap-3 sm:grid-cols-2">
                    <div className="space-y-1.5">
                      <Label>Tipe</Label>
                      <Select
                        value={kode.tipe}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { tipe: event.target.value })
                        }
                      >
                        {TIPE.map((item) => (
                          <option key={item.value} value={item.value}>
                            {item.label}
                          </option>
                        ))}
                      </Select>
                    </div>
                    <div className="space-y-1.5">
                      <Label>Nama</Label>
                      <Input
                        value={kode.nama}
                        placeholder="Masukkan Nama"
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { nama: event.target.value })
                        }
                      />
                    </div>
                    <div className="space-y-1.5">
                      <Label>Label</Label>
                      <Input
                        value={kode.label}
                        placeholder="Masukkan Label"
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { label: event.target.value })
                        }
                      />
                    </div>
                    <div className="space-y-1.5">
                      <Label>Placeholder</Label>
                      <Input
                        value={kode.deskripsi}
                        placeholder="Masukkan Placeholder"
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { deskripsi: event.target.value })
                        }
                      />
                    </div>
                    <div className="space-y-1.5">
                      <Label>Kolom</Label>
                      <Select
                        value={kode.kolom}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { kolom: event.target.value })
                        }
                      >
                        {KOLOM.map((item) => (
                          <option key={item.value} value={item.value}>
                            {item.label}
                          </option>
                        ))}
                      </Select>
                    </div>
                    <div className="space-y-1.5">
                      <Label>Atribut</Label>
                      <Input
                        value={kode.atribut}
                        placeholder={'minlength="5" maxlength="50"'}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { atribut: event.target.value })
                        }
                      />
                    </div>
                    <div className="space-y-1.5">
                      <Label>Referensi</Label>
                      <Select
                        value={kode.referensi}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { referensi: event.target.value })
                        }
                      >
                        {REFERENSI.map((item) => (
                          <option key={item.value} value={item.value}>
                            {item.label}
                          </option>
                        ))}
                      </Select>
                    </div>
                    <div className="space-y-1.5">
                      <Label>Kaitkan</Label>
                      <Select
                        value={kode.kaitkan}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { kaitkan: event.target.value })
                        }
                      >
                        <option value="">Tidak dikaitkan</option>
                        {semuaNama
                          .filter((nama) => nama && nama !== kode.nama)
                          .map((nama) => (
                            <option key={nama} value={nama}>
                              {nama}
                            </option>
                          ))}
                      </Select>
                    </div>
                    <div className="space-y-1.5 sm:col-span-2">
                      <Label>Pilihan (format JSON)</Label>
                      <Textarea
                        value={kode.pilihan}
                        placeholder="{}"
                        rows={2}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { pilihan: event.target.value })
                        }
                      />
                    </div>
                  </div>
                  <div className="flex flex-wrap items-center gap-3">
                    <label className="flex items-center gap-2 text-sm">
                      <input
                        type="checkbox"
                        checked={kode.required}
                        onChange={(event) =>
                          ubahKode(aktif, indexKode, { required: event.target.checked })
                        }
                      />
                      Wajib diisi
                    </label>
                    {bagian.length > 1 && (
                      <div className="ml-auto flex items-center gap-2">
                        <ArrowLeftRight className="h-4 w-4 text-muted-foreground" />
                        <Select
                          value=""
                          aria-label="Pindahkan kode isian ke bagian form lain"
                          className="w-48"
                          onChange={(event) => {
                            if (!event.target.value) return;
                            pindahkan(aktif, indexKode, Number(event.target.value));
                          }}
                        >
                          <option value="">Pindahkan ke…</option>
                          {bagian.map((item, posisi) =>
                            posisi === aktif ? null : (
                              <option key={posisi} value={posisi}>
                                {item.judul || `Bagian ${posisi + 1}`}
                              </option>
                            ),
                          )}
                        </Select>
                      </div>
                    )}
                  </div>
                </div>
              ))}
            </div>

            <div className="flex items-center gap-2">
              <Button type="button" variant="outline" size="sm" onClick={() => tambahKode(aktif)}>
                <Plus className="h-4 w-4" /> Tambah Kode Isian
              </Button>
              <span className="flex items-center gap-1 text-xs text-muted-foreground">
                <Link2 className="h-3.5 w-3.5" />
                Kode isian yang dikaitkan mengikuti nilai kode lainnya.
              </span>
            </div>
          </div>
        )}

        <DialogFooter>
          <Button variant="outline" onClick={onClose}>
            Batal
          </Button>
          <Button onClick={simpan} disabled={saving}>
            {saving ? "Menyimpan…" : "Simpan"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
