import type { Desa, PermohonanSuratDetail } from "@/lib/types";
import { cn, initials } from "@/lib/utils";
import {
  barcodePattern,
  createSuratResolver,
  verificationCode,
} from "@/lib/surat/format";
import { cssHalaman, pengaturanCetak } from "@/lib/surat/cetak";
import type {
  IdentitasKey,
  SuratData,
  SuratField,
  SuratFieldSection,
  SuratIdentitySection,
  SuratTableBlock,
  SuratTemplate,
} from "@/lib/surat/types";
import {
  isFieldSection,
  isIdentitySection,
  isTableBlock,
} from "@/lib/surat/types";

const LABEL_IDENTITAS: Record<IdentitasKey, string> = {
  nama: "Nama Lengkap",
  nik: "NIK",
  noKk: "Nomor Kartu Keluarga",
  kepalaKeluarga: "Kepala Keluarga",
  ttl: "Tempat / Tanggal Lahir",
  umur: "Umur",
  jenisKelamin: "Jenis Kelamin",
  alamat: "Alamat",
  agama: "Agama",
  statusKawin: "Status Perkawinan",
  pendidikan: "Pendidikan Terakhir",
  pekerjaan: "Pekerjaan",
  kewarganegaraan: "Kewarganegaraan",
  golonganDarah: "Golongan Darah",
  telepon: "Telepon",
  dusun: "Dusun",
};

const KOSONG = "……………………………";

function stripPrefix(value: string | null | undefined, prefix: string) {
  if (!value) return "-";
  return value.replace(new RegExp(`^${prefix}\\s+`, "i"), "");
}

function Emblem({
  nama,
  logo,
  className,
}: {
  nama: string;
  logo?: string | null;
  className?: string;
}) {
  if (logo) {
    return (
      // eslint-disable-next-line @next/next/no-img-element
      <img
        src={logo}
        alt={`Logo Desa ${nama}`}
        className={cn("h-[24mm] w-[24mm] object-contain", className)}
      />
    );
  }

  const inisial = initials(nama || "Desa") || "SD";
  return (
    <svg
      viewBox="0 0 100 100"
      className={cn("h-[24mm] w-[24mm]", className)}
      aria-hidden="true"
    >
      <circle cx="50" cy="50" r="47" fill="#f8fafc" stroke="#047857" strokeWidth="2.5" />
      <circle cx="50" cy="50" r="41" fill="none" stroke="#d4a017" strokeWidth="1.2" />
      <path
        d="M50 12l3.6 7.4 8.1 1.1-5.9 5.7 1.5 8-7.3-3.9-7.3 3.9 1.5-8-5.9-5.7 8.1-1.1z"
        fill="#d4a017"
      />
      <path
        d="M27 62c-3.2 6.4-2.4 13 1.6 18.4M73 62c3.2 6.4 2.4 13-1.6 18.4"
        stroke="#047857"
        strokeWidth="2.2"
        fill="none"
        strokeLinecap="round"
      />
      <path
        d="M22 66c5-1.4 8.2-.3 10.4 3.1-4.7 1.6-8.4.4-10.4-3.1zM78 66c-5-1.4-8.2-.3-10.4 3.1 4.7 1.6 8.4.4 10.4-3.1zM20 73c5-1.4 8.4-.2 10.6 3.3-4.8 1.5-8.6.2-10.6-3.3zM80 73c-5-1.4-8.4-.2-10.6 3.3 4.8 1.5 8.6.2 10.6-3.3z"
        fill="#047857"
        opacity="0.85"
      />
      <text
        x="50"
        y="57"
        textAnchor="middle"
        fontSize="24"
        fontWeight="700"
        fill="#064e3b"
        fontFamily="Georgia, 'Times New Roman', serif"
      >
        {inisial}
      </text>
      <text
        x="50"
        y="69"
        textAnchor="middle"
        fontSize="6.2"
        letterSpacing="1.4"
        fill="#b45309"
        fontFamily="Georgia, 'Times New Roman', serif"
      >
        DESA
      </text>
    </svg>
  );
}

function Garuda({ className }: { className?: string }) {
  const sayap = [-42, -30, -18, -6, 6, 18];
  const ekor = [-26, -13, 0, 13, 26];
  const Bulu = ({ sudut, panjang }: { sudut: number; panjang: number }) => (
    <path
      d={`M0 -2.6 L${panjang} -1 L${panjang} 1 L0 2.6 Z`}
      transform={`translate(65 52) rotate(${sudut})`}
    />
  );
  return (
    <svg
      viewBox="0 0 120 120"
      className={cn("h-[24mm] w-[24mm]", className)}
      aria-label="Logo Burung Garuda"
      role="img"
    >
      <g fill="#1f2937">
        {sayap.map((sudut) => (
          <Bulu key={`k-${sudut}`} sudut={sudut} panjang={30} />
        ))}
        <g transform="translate(120 0) scale(-1 1)">
          {sayap.map((sudut) => (
            <Bulu key={`p-${sudut}`} sudut={sudut} panjang={30} />
          ))}
        </g>
        {ekor.map((sudut) => (
          <path
            key={`e-${sudut}`}
            d="M0 -2.2 L20 -1 L20 1 L0 2.2 Z"
            transform={`translate(60 74) rotate(${90 + sudut})`}
          />
        ))}
        <path d="M60 40c3.4 0 6 2.6 6 6v6c2.6 3 4 7 4 11 0 6-2.4 11-6 15h-8c-3.6-4-6-9-6-15 0-4 1.4-8 4-11v-6c0-3.4 2.6-6 6-6z" />
        <path d="M54 32c0-4.4 2.8-8 6-8s6 3.6 6 8c0 3.4-2 6-4 7h-4c-2-1-4-3.6-4-7z" />
        <path d="M58 36h4l-2 4z" fill="#b45309" />
      </g>
      <rect
        x="53"
        y="56"
        width="14"
        height="8"
        rx="1.5"
        fill="#f8fafc"
        stroke="#1f2937"
        strokeWidth="1.1"
      />
      <path d="M55 60h10" stroke="#1f2937" strokeWidth="0.9" />
    </svg>
  );
}

function Seal({ nama }: { nama: string }) {
  return (
    <svg
      viewBox="0 0 120 120"
      className="pointer-events-none absolute left-1/2 top-1/2 h-[23mm] w-[23mm] -translate-x-1/2 -translate-y-1/2 -rotate-6 opacity-60"
      aria-hidden="true"
    >
      <defs>
        <path id="seal-top" d="M60 60m-42 0a42 42 0 1 1 84 0" fill="none" />
        <path id="seal-bottom" d="M60 60m-42 0a42 42 0 1 0 84 0" fill="none" />
      </defs>
      <circle cx="60" cy="60" r="56" fill="none" stroke="#047857" strokeWidth="1.4" />
      <circle cx="60" cy="60" r="51" fill="none" stroke="#047857" strokeWidth="2.6" />
      <circle cx="60" cy="60" r="34" fill="none" stroke="#047857" strokeWidth="0.9" />
      <text fill="#047857" fontSize="7.6" letterSpacing="1.5" fontFamily="Georgia, serif">
        <textPath href="#seal-top" startOffset="50%" textAnchor="middle">
          SISTEM INFORMASI DESA
        </textPath>
      </text>
      <text fill="#047857" fontSize="7.2" letterSpacing="1.8" fontFamily="Georgia, serif">
        <textPath href="#seal-bottom" startOffset="50%" textAnchor="middle">
          DOKUMEN DIGITAL
        </textPath>
      </text>
      <path
        d="M60 43l3.3 6.8 7.5 1.1-5.4 5.2 1.3 7.4-6.7-3.6-6.7 3.6 1.3-7.4-5.4-5.2 7.5-1.1z"
        fill="#047857"
        opacity="0.9"
      />
      <text
        x="60"
        y="78"
        textAnchor="middle"
        fontSize="12"
        fontWeight="700"
        fill="#047857"
        fontFamily="Georgia, serif"
      >
        {initials(nama || "Desa")}
      </text>
    </svg>
  );
}

function SectionTitle({
  children,
  tone = "emerald",
}: {
  children: React.ReactNode;
  tone?: "emerald" | "gold";
}) {
  return (
    <div className="mb-2 flex items-center gap-2">
      <span
        className={cn(
          "h-[1.55em] w-1 rounded-full",
          tone === "emerald" ? "bg-emerald-700" : "bg-amber-500",
        )}
      />
      <h3 className="text-[12px] font-bold uppercase tracking-[0.14em] text-emerald-950">
        {children}
      </h3>
      <span className="ml-1 h-px flex-1 bg-gradient-to-r from-emerald-700/30 to-transparent" />
    </div>
  );
}

function IdentityBlock({
  section,
  template,
  resolver,
}: {
  section: SuratIdentitySection;
  template: SuratTemplate;
  resolver: ReturnType<typeof createSuratResolver>;
}) {
  return (
    <section className="break-inside-avoid rounded-md border border-emerald-900/10 bg-emerald-50/40 px-4 py-3">
      {section.title && <SectionTitle>{resolver.resolve(section.title)}</SectionTitle>}
      <dl className="grid gap-x-6 gap-y-2 sm:grid-cols-2">
        {section.identitas.map((key) => (
          <div key={key} className="grid grid-cols-[42mm_1.5mm_1fr] text-[12.5px] leading-5">
            <dt className="text-slate-600">{LABEL_IDENTITAS[key]}</dt>
            <dd className="text-slate-500">:</dd>
            <dd className="font-semibold text-slate-900">
              {resolver.identity[key] || "-"}
            </dd>
          </div>
        ))}
      </dl>
    </section>
  );
}

function FieldBlock({
  section,
  template,
  resolver,
}: {
  section: SuratFieldSection;
  template: SuratTemplate;
  resolver: ReturnType<typeof createSuratResolver>;
}) {
  const fieldsByKey = new Map(template.fields.map((field) => [field.key, field]));
  const entries = section.fields
    .map((key) => {
      const field = fieldsByKey.get(key) as SuratField | undefined;
      const value = field ? resolver.fieldValue(field.key) : resolver.resolve(`{f:${key}}`);
      return { field, key, value };
    })
    .filter((entry) => entry.value || entry.field?.required);

  if (!entries.length) return null;

  const columns = section.columns ?? 2;

  return (
    <section className="break-inside-avoid">
      {section.title && <SectionTitle>{resolver.resolve(section.title)}</SectionTitle>}
      <dl
        className={cn(
          "grid gap-x-6 gap-y-1.5",
          columns === 1 && "grid-cols-1",
          columns === 2 && "sm:grid-cols-2",
          columns === 3 && "sm:grid-cols-3",
        )}
      >
        {entries.map(({ field, key, value }) => {
          const wide = field?.type === "textarea";
          return (
            <div
              key={key}
              className={cn(
                "grid grid-cols-[31mm_2mm_1fr] text-[12.5px] leading-5",
                wide && (columns === 1 ? "col-span-1" : "sm:col-span-2"),
                columns === 3 && wide && "sm:col-span-3",
                columns === 3 && "grid-cols-[24mm_2mm_1fr]",
              )}
            >
              <dt className="text-slate-600">{field?.label ?? key}</dt>
              <dd className="text-slate-500">:</dd>
              <dd className="font-semibold text-slate-900">{value || KOSONG}</dd>
            </div>
          );
        })}
      </dl>
      {section.note && (
        <p className="mt-1 text-[11px] italic text-slate-500">{resolver.resolve(section.note)}</p>
      )}
    </section>
  );
}

function TableBlock({
  block,
  resolver,
}: {
  block: SuratTableBlock;
  resolver: ReturnType<typeof createSuratResolver>;
}) {
  return (
    <section className="break-inside-avoid">
      {block.title && <SectionTitle tone="gold">{resolver.resolve(block.title)}</SectionTitle>}
      <div className="overflow-hidden rounded-md border border-emerald-900/20">
        <table className="w-full border-collapse text-[11.5px] leading-5">
          <thead>
            <tr className="bg-emerald-800 text-white">
              {block.columns.map((column, index) => (
                <th
                  key={`${column}-${index}`}
                  className={cn(
                    "border border-emerald-900/30 px-2.5 py-1.5 font-semibold uppercase tracking-wide",
                    block.align?.[index] === "right" && "text-right",
                    block.align?.[index] === "center" && "text-center",
                  )}
                >
                  {resolver.resolve(column)}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {block.rows.map((row, rowIndex) => (
              <tr key={rowIndex} className={rowIndex % 2 === 1 ? "bg-emerald-50/60" : "bg-white"}>
                {row.map((cell, cellIndex) => (
                  <td
                    key={cellIndex}
                    className={cn(
                      "border border-emerald-900/15 px-2.5 py-1.5 text-slate-800",
                      block.align?.[cellIndex] === "right" && "text-right",
                      block.align?.[cellIndex] === "center" && "text-center",
                    )}
                  >
                    {resolver.resolve(cell)}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
          {block.footer && (
            <tfoot>
              <tr className="bg-amber-50 font-semibold text-slate-900">
                {block.footer.map((cell, index) => (
                  <td
                    key={index}
                    className={cn(
                      "border border-emerald-900/20 px-2.5 py-1.5",
                      block.align?.[index] === "right" && "text-right",
                      block.align?.[index] === "center" && "text-center",
                    )}
                  >
                    {resolver.resolve(cell)}
                  </td>
                ))}
              </tr>
            </tfoot>
          )}
        </table>
      </div>
      {block.note && (
        <p className="mt-1 text-[11px] italic text-slate-500">{resolver.resolve(block.note)}</p>
      )}
    </section>
  );
}

function SignatureBlock({
  title,
  name,
  detail,
  place,
  date,
  seal,
  qr,
}: {
  title: string;
  name: string;
  detail?: string;
  place: string;
  date: string;
  seal?: string;
  qr?: string;
}) {
  return (
    <div className="w-[66mm] text-center text-[12.5px] leading-5">
      <p className="text-slate-700">
        {place}, {date}
      </p>
      <p className="font-semibold text-slate-900">{title}</p>
      <div className="relative h-[21mm]">
        {seal && <Seal nama={seal} />}
      </div>
      <p className="font-bold text-slate-950 underline decoration-1 underline-offset-4">
        {name || KOSONG}
      </p>
      {detail && <p className="text-[11px] text-slate-600">{detail}</p>}
      {qr && (
        <div className="mt-2 flex justify-center">
          {/* eslint-disable-next-line @next/next/no-img-element */}
          <img src={qr} alt="QR Code TTE" className="h-[20mm] w-[20mm]" />
        </div>
      )}
    </div>
  );
}

export function SuratDocument({
  template,
  surat,
  desa,
  data,
  className,
}: {
  template: SuratTemplate;
  surat: PermohonanSuratDetail;
  desa?: Desa;
  data: SuratData;
  className?: string;
}) {
  const resolver = createSuratResolver({ template, surat, desa, data });
  const namaDesa = resolver.namaDesa === "-" ? "" : resolver.namaDesa;
  const kecamatan = stripPrefix(desa?.kecamatan, "Kecamatan");
  const kabupaten = stripPrefix(desa?.kabupaten, "Kabupaten");
  const tanggal = resolver.tanggalSurat;
  const signatures = template.signature ?? "kepala";
  const namaKepala = desa?.kepalaDesa ?? "";
  const cetak = pengaturanCetak(surat.jenis);

  const identitySections = template.sections.filter(isIdentitySection);
  const fieldBefore = template.sections.filter(
    (section) => isFieldSection(section) && section.placement !== "after",
  ) as SuratFieldSection[];
  const fieldAfter = template.sections.filter(
    (section) => isFieldSection(section) && section.placement === "after",
  ) as SuratFieldSection[];
  const tableBefore = template.sections.filter(
    (section) => isTableBlock(section) && section.placement === "before",
  ) as SuratTableBlock[];
  const tableAfter = template.sections.filter(
    (section) => isTableBlock(section) && section.placement !== "before",
  ) as SuratTableBlock[];

  const kodeVerifikasi = verificationCode(surat.nomor, surat.penduduk.nik);
  const bars = barcodePattern(kodeVerifikasi);
  const isiQrVerifikasi = `Core Mulyadadi|${surat.nomor}|${kodeVerifikasi}`;
  const urlQr = (isi: string) =>
    `/api/backend/qrcode?size=280&type=png&data=${encodeURIComponent(isi)}`;

  const kepalaBlock = (
    <SignatureBlock
      title={`Kepala Desa ${namaDesa}`}
      name={namaKepala}
      detail={desa?.nipKepalaDesa ? `NIP. ${desa.nipKepalaDesa}` : undefined}
      place={namaDesa || "Desa"}
      date={tanggal}
      seal={namaDesa}
      qr={cetak.qrCodeTte ? urlQr(isiQrVerifikasi) : undefined}
    />
  );

  const pemohonBlock = (
    <SignatureBlock
      title={template.signatureKanan ?? "Pemohon"}
      name={resolver.signatureName}
      detail={`NIK. ${surat.penduduk.nik}`}
      place={namaDesa || "Desa"}
      date={tanggal}
    />
  );

  return (
    <article
      className={cn(
        "surat-sheet relative mx-auto flex flex-col overflow-hidden bg-white text-slate-900 shadow-lg print:max-w-none print:shadow-none",
        className,
      )}
      style={{ fontFamily: '"Times New Roman", Times, Georgia, serif' }}
    >
      <style dangerouslySetInnerHTML={{ __html: cssHalaman(cetak) }} />

      <div
        className="pointer-events-none absolute inset-0 flex items-center justify-center opacity-[0.035]"
        aria-hidden="true"
      >
        <Emblem nama={namaDesa} className="h-[120mm] w-[120mm] -rotate-12" />
      </div>

      <div className="relative">
        {cetak.header > 0 && (
        <>
        <header
          className={cn(
            "flex items-center gap-4",
            cetak.header === 1 && "surat-header-repeat",
          )}
        >
          {cetak.logoGaruda ? (
            <Garuda />
          ) : (
            <Emblem nama={namaDesa} logo={desa?.logo} />
          )}
          <div className="flex-1 text-center leading-tight">
            <p className="text-[12.5px] font-semibold uppercase tracking-[0.16em] text-emerald-950">
              Pemerintah Kabupaten {kabupaten}
            </p>
            <p className="text-[12.5px] font-semibold uppercase tracking-[0.16em] text-emerald-950">
              Kecamatan {kecamatan}
            </p>
            <p
              className="mt-0.5 text-[23px] font-bold uppercase tracking-[0.1em] text-emerald-950"
              style={{ fontFamily: 'Georgia, "Times New Roman", serif' }}
            >
              Desa {namaDesa}
            </p>
            <p className="mt-1 text-[10.5px] leading-4 text-slate-600">
              {[
                desa?.alamat,
                desa?.kodePos ? `Kode Pos ${desa.kodePos}` : null,
                desa?.telepon ? `Telp. ${desa.telepon}` : null,
                desa?.email,
                desa?.website,
              ]
                .filter(Boolean)
                .join(" · ") || "Alamat kantor desa belum diatur"}
            </p>
          </div>
          <div className="w-[24mm] shrink-0 text-right text-[9px] leading-4 text-slate-500">
            {desa?.kodeDesa && (
              <>
                <p className="font-semibold uppercase tracking-wide">Kode Wilayah</p>
                <p className="font-mono">{desa.kodeDesa}</p>
              </>
            )}
            <p className="mt-1.5 font-semibold uppercase tracking-wide">Arsip Digital</p>
            <p className="font-mono">{surat.nomor}</p>
          </div>
        </header>

        <div className="mt-3">
          <div className="h-[2.5px] bg-gradient-to-r from-emerald-800 via-emerald-600 to-emerald-800" />
          <div className="mt-[2px] h-[1px] bg-amber-500/80" />
        </div>
        </>
        )}

        <div className="mt-5 text-center">
          <h1 className="text-[17.5px] font-bold uppercase leading-6 tracking-[0.12em] text-emerald-950 underline decoration-emerald-800/60 decoration-1 underline-offset-[6px]">
            {resolver.resolve(template.judul)}
          </h1>
          <p className="mt-2 font-mono text-[12px] text-slate-700">Nomor: {surat.nomor}</p>
          {template.kode !== "-" && (
            <p className="mt-0.5 text-[10px] uppercase tracking-[0.2em] text-slate-500">
              Kode Layanan {template.kode}
            </p>
          )}
        </div>

        <div className="mt-6 space-y-3.5 text-[13px] leading-6">
          {template.addressee && (
            <div className="pl-1">
              <p className="text-slate-600">Kepada</p>
              <p className="font-semibold text-slate-900">
                Yth. {resolver.resolve(template.addressee)}
              </p>
              <p className="text-slate-600">di tempat</p>
            </div>
          )}

          {template.pembuka && <p className="text-justify">{resolver.resolve(template.pembuka)}</p>}

          {identitySections.map((section, index) => (
            <IdentityBlock
              key={`identity-${index}`}
              section={section}
              template={template}
              resolver={resolver}
            />
          ))}

          {tableBefore.map((block, index) => (
            <TableBlock key={`table-before-${index}`} block={block} resolver={resolver} />
          ))}

          {fieldBefore.map((section, index) => (
            <FieldBlock
              key={`fields-before-${index}`}
              section={section}
              template={template}
              resolver={resolver}
            />
          ))}

          {template.isi.map((paragraph, index) => (
            <p key={index} className="text-justify">
              {resolver.resolve(paragraph)}
            </p>
          ))}

          {tableAfter.map((block, index) => (
            <TableBlock key={`table-after-${index}`} block={block} resolver={resolver} />
          ))}

          {fieldAfter.map((section, index) => (
            <FieldBlock
              key={`fields-after-${index}`}
              section={section}
              template={template}
              resolver={resolver}
            />
          ))}

          {template.penutup && <p className="text-justify">{resolver.resolve(template.penutup)}</p>}
        </div>

        <div
          className={cn(
            "mt-8 flex break-inside-avoid",
            signatures === "kepala-pemohon" ? "items-start justify-between gap-6" : "justify-end",
          )}
        >
          {signatures === "kepala-pemohon" && pemohonBlock}
          {(signatures === "kepala" || signatures === "kepala-pemohon") && kepalaBlock}
          {signatures === "pemohon" && pemohonBlock}
        </div>

        {cetak.footer && (
        <footer className="mt-auto pt-8">
          <div className="flex items-end justify-between gap-4 border-t border-dashed border-slate-300 pt-2.5">
            <div className="flex items-center gap-2.5">
              {cetak.qrCode ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img
                  src={urlQr(isiQrVerifikasi)}
                  alt="QR Code Verifikasi"
                  className="h-[22mm] w-[22mm]"
                />
              ) : (
                <div className="flex h-7 items-stretch gap-[1.5px]" aria-hidden="true">
                  {bars.map((width, index) => (
                    <span
                      key={index}
                      className="block bg-slate-800"
                      style={{ width: `${width}px` }}
                    />
                  ))}
                </div>
              )}
              <div className="text-[9px] leading-3 text-slate-500">
                <p className="font-semibold uppercase tracking-[0.18em] text-emerald-900">
                  Verifikasi Dokumen
                </p>
                <p className="font-mono text-[10px] text-slate-700">{kodeVerifikasi}</p>
              </div>
            </div>
            <div className="max-w-[92mm] text-right text-[8.5px] leading-3 text-slate-500">
              <p>
                Surat ini diterbitkan melalui aplikasi Core Mulyadadi pada{" "}
                {tanggal}.
              </p>
              <p>
                Keabsahan dokumen dapat dikonfirmasi kepada Pemerintah Desa {namaDesa}{" "}
                dengan menyebutkan nomor surat dan kode verifikasi di atas.
              </p>
            </div>
          </div>
        </footer>
        )}
      </div>
    </article>
  );
}
