import FullScreenLoading from "@/components/FullScreenLoading";
import ModalFile from "@/components/ModalFile";
import { DataNotFound } from "@/components/NotFoundPengajuanSurat";
import notification from "@/components/notificationGlobal";
import SuccessPengajuan from "@/components/SuccessPengajuanSurat";
import apiFetch from "@/lib/apiFetch";
import { parseTanggalID } from "@/server/lib/stringToDate";
import {
  ActionIcon,
  Alert,
  Anchor,
  Badge,
  Box,
  Button,
  Card,
  Container,
  Divider,
  FileInput,
  Flex,
  Grid,
  Group,
  Modal,
  Select,
  Stack,
  Text,
  TextInput,
  Tooltip,
} from "@mantine/core";
import { DateInput } from "@mantine/dates";
import { useDisclosure, useShallowEffect } from "@mantine/hooks";
import {
  IconBuildingCommunity,
  IconFiles,
  IconInfoCircle,
  IconNotes,
  IconUpload,
} from "@tabler/icons-react";
import dayjs from "dayjs";
import "dayjs/locale/id";
import _ from "lodash";
import React, { useState } from "react";
import { useLocation, useNavigate } from "react-router-dom";

type DataItem = {
  key: string;
  value: string;
};

type UpdateDataItem = {
  id: string;
  key: string;
  value: any;
};

type FormSurat = {
  kategoriId: string;
  nama: string;
  phone: string;
  dataPelengkap: DataItem[];
  syaratDokumen: DataItem[];
};

type FormUpdateSurat = {
  dataPelengkap: UpdateDataItem[];
  syaratDokumen: UpdateDataItem[];
};

type DataPengajuan = {
  id: string;
  noPengajuan: string;
  category: string;
  status: "antrian" | "diproses" | "selesai" | "ditolak";
  createdAt: Date;
  updatedAt: Date;
  idSurat: string | undefined;
  alasan: string | undefined | null;
};

export default function UpdateDataSurat() {
  const navigate = useNavigate();
  const { search } = useLocation();
  const query = new URLSearchParams(search);
  const noPengajuan = query.get("pengajuan");
  const [found, setFound] = useState(true);

  return (
    <Container size="md" w={"100%"}>
      <Box>
        <Stack gap="lg">
          {found && (
            <Group justify="space-between" align="center" mt={"lg"}>
              <Group align="center">
                <IconBuildingCommunity size={28} />
                <div>
                  <Text fw={800} size="xl">
                    Update Data Pengajuan Surat Administrasi
                  </Text>
                  <Text size="sm" c="dimmed">
                    Formulir ini digunakan untuk memperbarui data pengajuan
                    surat administrasi yang telah diajukan sebelumnya.
                  </Text>
                </div>
              </Group>
            </Group>
          )}
          <Stack gap="lg" mb="lg">
            {!noPengajuan ? (
              <SearchData />
            ) : found ? (
              <DataUpdate
                noPengajuan={noPengajuan}
                onValidate={(e) => {
                  setFound(e);
                }}
              />
            ) : (
              <DataNotFound
                backTo={() => navigate("/darmasaba/update-data-surat")}
              />
            )}
          </Stack>
        </Stack>
      </Box>
    </Container>
  );
}

function FieldLabel({ label, hint }: { label: string; hint?: string }) {
  return (
    <Group justify="apart" gap="xs" align="center">
      <Text fw={600}>{label}</Text>
      {hint && (
        <Tooltip label={hint} withArrow>
          <ActionIcon size={24} variant="subtle">
            <IconInfoCircle size={16} />
          </ActionIcon>
        </Tooltip>
      )}
    </Group>
  );
}

function FormSection({
  title,
  icon,
  children,
  description,
  info,
}: {
  title?: string;
  icon?: React.ReactNode;
  children: React.ReactNode;
  description?: string;
  info?: string;
}) {
  return (
    <Card radius="md" shadow="sm" withBorder>
      <Box mb="xs">
        <Group justify="apart" align="center">
          <Group align="center" gap="xs">
            {icon}
            {title && <Text fw={700}>{title}</Text>}
          </Group>
          {description && <Badge variant="light">{description}</Badge>}
        </Group>
        {info && (
          <Text size="sm" c="dimmed">
            {info}
          </Text>
        )}
      </Box>
      {title && <Divider mb="sm" />}
      <Stack gap="sm">{children}</Stack>
    </Card>
  );
}

function FileInputWrapper({
  label,
  placeholder,
  accept,
  onChange,
  preview,
  name,
  description,
  linkView,
  disabled,
}: {
  label: string;
  placeholder?: string;
  accept?: string;
  linkView?: string;
  onChange: (file: File | null) => void;
  preview?: string | null;
  name: string;
  description?: string;
  disabled?: boolean;
}) {
  const [viewImg, setViewImg] = useState("");
  const [openedPreviewFile, setOpenedPreviewFile] = useState(false);

  useShallowEffect(() => {
    if (viewImg) {
      setOpenedPreviewFile(true);
    }
  }, [viewImg]);

  return (
    <>
      <ModalFile
        open={openedPreviewFile && !_.isEmpty(viewImg)}
        onClose={() => {
          setOpenedPreviewFile(false);
        }}
        folder="syarat-dokumen"
        fileName={viewImg}
      />

      <Stack gap="xs">
        <Flex direction={"column"}>
          <Group justify="apart" align="center">
            <Text fw={500}>{label}</Text>
          </Group>
          {description && (
            <Text size="sm" c="dimmed" mt={4} style={{ lineHeight: 1.2 }}>
              {description}
            </Text>
          )}
          {linkView && (
            <Anchor onClick={() => setViewImg(linkView)} size="sm">
              Lihat dokumen sebelumnya
            </Anchor>
          )}
        </Flex>

        <FileInput
          accept={accept}
          placeholder={placeholder}
          onChange={(f) => onChange(f)}
          leftSection={<IconUpload />}
          aria-label={label}
          name={name}
          disabled={disabled}
        />

        {preview ? (
          <div>
            <Text size="xs" color="dimmed">
              Preview:
            </Text>
            <div style={{ marginTop: 6 }}>
              <img
                src={preview}
                alt={`${label} preview`}
                style={{ maxWidth: "200px", borderRadius: 4 }}
              />
            </div>
          </div>
        ) : null}
      </Stack>
    </>
  );
}

function SearchData() {
  const [submitLoading, setSubmitLoading] = useState(false);
  const [searchPengajuan, setSearchPengajuan] = useState("");
  const [searchPengajuanPhone, setSearchPengajuanPhone] = useState("");
  const navigate = useNavigate();

  async function handleSearch() {
    try {
      setSubmitLoading(true);
      if (searchPengajuan == "" || searchPengajuanPhone == "") {
        notification({
          title: "Peringatan",
          message: "Silakan isi nomor pengajuan atau nomor telephone",
          type: "warning",
        });
        return;
      }

      const response = await apiFetch.api.pelayanan["get-no-pengajuan"].post({
        phone: searchPengajuanPhone,
        noPengajuan: searchPengajuan,
      });

      if (response.status === 200) {
        if (response.data?.success) {
          navigate(
            `/darmasaba/update-data-surat?pengajuan=${response.data.nomer}`,
          );
        } else {
          notification({
            title: "Peringatan",
            message: response.data?.message || "Data pengajuan tidak valid",
            type: "warning",
          });
        }
      } else {
        notification({
          title: "Error",
          message: "Pengajuan tidak ditemukan atau gagal memuat data",
          type: "error",
        });
      }
    } catch (error) {
      console.error("Error searching:", error);
      notification({
        title: "Error",
        message: "Gagal mencari data pengajuan",
        type: "error",
      });
    } finally {
      setSubmitLoading(false);
    }
  }

  return (
    <FormSection
      title="Cari Pengajuan Surat"
      info="Masukkan nomor pengajuan dan nomor telepon yang digunakan saat pengajuan surat."
    >
      <Grid>
        <Grid.Col span={6}>
          <TextInput
            label={
              <FieldLabel
                label="Nomor Pengajuan"
                hint="Nomor pengajuan surat"
              />
            }
            placeholder="PS-2025-000123"
            onChange={(e) => {
              setSearchPengajuan(e.target.value);
            }}
          />
        </Grid.Col>

        <Grid.Col span={6}>
          <TextInput
            label={
              <FieldLabel
                label="Nomor Telephone"
                hint="Nomor telephone yang dapat dihubungi / terhubung dengan whatsapp"
              />
            }
            placeholder="08123456789"
            type="number"
            onChange={(e) => {
              setSearchPengajuanPhone(e.target.value);
            }}
          />
        </Grid.Col>

        <Grid.Col span={12}>
          <Button
            fullWidth
            variant="light"
            color="blue"
            onClick={() => {
              handleSearch();
            }}
            loading={submitLoading}
          >
            Cari Pengajuan
          </Button>
        </Grid.Col>
      </Grid>
    </FormSection>
  );
}

function DataUpdate({
  noPengajuan,
  onValidate,
}: {
  noPengajuan: string;
  onValidate: (e: boolean) => void;
}) {
  const [opened, { open, close }] = useDisclosure(false);
  const navigate = useNavigate();
  const [errors, setErrors] = useState<Record<string, string | null>>({});
  const [sukses, setSukses] = useState(false);
  const [submitLoading, setSubmitLoading] = useState(false);
  const [dataPelengkap, setDataPelengkap] = useState<DataItem[]>([]);
  const [dataSyaratDokumen, setDataSyaratDokumen] = useState<DataItem[]>([]);
  const [dataPengajuan, setDataPengajuan] = useState<DataPengajuan | {}>({});
  const [status, setStatus] = useState("");
  const [formSurat, setFormSurat] = useState<FormUpdateSurat>({
    dataPelengkap: [],
    syaratDokumen: [],
  });

  async function fetchData() {
    try {
      const res = await apiFetch.api.pelayanan["detail-data"].post({
        nomerPengajuan: noPengajuan,
      });
      if (res.data && res.data.success === true) {
        onValidate(true);
        setDataPelengkap(res.data.dataPelengkap || []);
        setDataSyaratDokumen(res.data.syaratDokumen || []);
        setDataPengajuan(res.data.pengajuan || {});

        setStatus(
          res.data.pengajuan && "status" in res.data.pengajuan
            ? res.data.pengajuan.status
            : "",
        );
      } else {
        // notification({
        //    title: "Error",
        //    message: res.data?.message || "Gagal memuat data",
        //    type: "error",
        // });
        onValidate(false);
        setDataPelengkap([]);
        setDataSyaratDokumen([]);
        setDataPengajuan({});
      }
    } catch (error) {
      console.error("Error fetching data:", error);
    }
  }

  useShallowEffect(() => {
    fetchData();
  }, []);

  function validateField(key: string, value: any) {
    const stringValue = String(value ?? "").trim();

    // wajib diisi
    if (!stringValue) {
      return "Field wajib diisi";
    }

    // 🔥 semua key yg mengandung "nik"
    if (key.toLowerCase().includes("nik")) {
      if (!/^\d+$/.test(stringValue)) {
        return "NIK harus berupa angka";
      }

      if (stringValue.length !== 16) {
        return "NIK harus 16 digit";
      }
    }

    return null;
  }


  function upsertById<T extends { id: string }>(array: T[], item: T): T[] {
    const index = array.findIndex((v) => v.id === item.id);

    // ➕ insert
    if (index === -1) {
      return [...array, item];
    }

    // ✏️ update
    return array.map((v, i) => (i === index ? { ...v, ...item } : v));
  }

  function validationForm({
    kategori,
    value,
  }: {
    kategori: "dataPelengkap" | "syaratDokumen";
    value: UpdateDataItem;
  }) {
    const errorMsg = validateField(value.key, value.value);

    setErrors((prev) => ({
      ...prev,
      [value.id]: errorMsg,
    }));

    setFormSurat((prev) => ({
      ...prev,
      [kategori]: upsertById(prev[kategori], {
        id: value.id,
        key: value.key,
        value: value.value,
      }),
    }));
  }


  function updateArrayByKey(
    list: UpdateDataItem[],
    id: string,
    value: any,
  ): UpdateDataItem[] {
    return list.map((item) => (item.id === id ? { ...item, value } : item));
  }

  function onChecking() {
    const hasError = Object.values(errors).some((v) => v);

    if (hasError) {
      return notification({
        title: "Gagal",
        message: "Masih ada data yang belum valid",
        type: "error",
      });
    }

    if (
      formSurat.dataPelengkap.length == 0 &&
      formSurat.syaratDokumen.length == 0
    )
      return notification({
        title: "Peringatan",
        message: "Tidak ada data yang diupdate",
        type: "warning",
      });
    const isFormKosong = Object.values(formSurat).some(
      (value: UpdateDataItem[] | string) => {
        if (Array.isArray(value)) {
          return value.some(
            (item) =>
              typeof item.value === "string" && item.value.trim() === "",
          );
        }

        if (typeof value === "string") {
          return value.trim() === "";
        }

        return false;
      },
    );

    if (isFormKosong) {
      return notification({
        title: "Gagal",
        message: "Silahkan lengkapi form surat",
        type: "error",
      });
    } else {
      open();
    }
  }

  async function onSubmit() {
    try {
      setSubmitLoading(true);
      // 🔥 CLONE state SEKALI
      let finalFormSurat = structuredClone(formSurat);

      // 2️⃣ Upload satu per satu
      for (const itemUpload of finalFormSurat.syaratDokumen) {
        const updImg = await apiFetch.api.pengaduan.upload.post({
          file: itemUpload.value,
          folder: "syarat-dokumen",
        });

        if (updImg.status === 200) {
          // 🔥 UPDATE OBJECT LOKAL (BUKAN STATE)
          finalFormSurat.syaratDokumen = updateArrayByKey(
            finalFormSurat.syaratDokumen,
            itemUpload.id,
            updImg.data?.filename || "",
          );
        }
      }

      // 3️⃣ SET STATE SEKALI (optional, untuk UI)
      setFormSurat(finalFormSurat);

      // 4️⃣ SUBMIT KE API
      const res = await apiFetch.api.pelayanan.update.post({
        id: dataPengajuan && "id" in dataPengajuan ? dataPengajuan.id : "",
        dataPelengkap: finalFormSurat.dataPelengkap,
        syaratDokumen: finalFormSurat.syaratDokumen,
      });

      if (res.status === 200) {
        setSukses(true);
      } else {
        notification({
          title: "Gagal",
          message:
            "Pengajuan surat gagal dibuat, silahkan coba beberapa saat lagi",
          type: "error",
        });
      }
    } catch (error) {
      notification({
        title: "Gagal",
        message: "Server Error",
        type: "error",
      });
    } finally {
      setSubmitLoading(false);
    }
  }

  return (
    <>
      <FullScreenLoading visible={submitLoading} />
      <Modal
        opened={opened}
        onClose={close}
        title={"Konfirmasi"}
        overlayProps={{ backgroundOpacity: 0.55, blur: 3 }}
      >
        <Stack gap="sm">
          <Text>Apakah anda yakin ingin mengupdate pengajuan surat ini?</Text>
          <Group justify="center" grow>
            <Button variant="light" onClick={close}>
              Tidak
            </Button>
            <Button
              variant="filled"
              color="green"
              onClick={() => {
                onSubmit();
                close();
              }}
            >
              Ya
            </Button>
          </Group>
        </Stack>
      </Modal>
      {sukses ? (
        <SuccessPengajuan
          noPengajuan={noPengajuan}
          onClose={() => {
            navigate("/darmasaba/update-data-surat");
          }}
          category="update"
        />
      ) : (
        <>
          {status != "ditolak" && status != "antrian" && (
            <Alert
              variant="light"
              color="yellow"
              radius="lg"
              title={`Data pengajuan surat ini tidak dapat diupdate karena berstatus ${status}.`}
              icon={<span style={{ fontSize: "1.2rem" }}>⚠</span>}
            />
          )}
          {status == "ditolak" && (
            <Alert
              variant="light"
              color="yellow"
              radius="lg"
              title={`Data pengajuan surat ini ditolak, karena ${dataPengajuan && 'alasan' in dataPengajuan && dataPengajuan.alasan
                ? dataPengajuan.alasan
                : "alasan tidak tersedia"
                }. Silahkan perbaiki data pengajuan surat ini.`}
              icon={<span style={{ fontSize: "1.2rem" }}>⚠</span>}
            />
          )}
          <FormSection
            title="Data Yang Diperlukan"
            description="Data yang diperlukan"
            icon={<IconNotes size={16} />}
          >
            <Grid>
              {dataPelengkap.map((item: any, index: number) => (
                <Grid.Col span={6} key={index}>
                  {item.type == "enum" ? (
                    <Select
                      allowDeselect={false}
                      label={<FieldLabel label={item.name} hint={item.desc} />}
                      data={item.options ?? []}
                      placeholder={item.name}
                      onChange={(e) => {
                        validationForm({
                          kategori: "dataPelengkap",
                          value: { id: item.id, key: item.key, value: e },
                        });
                      }}
                      value={
                        formSurat.dataPelengkap.find(
                          (n: any) => n.key == item.key,
                        )?.value ||
                        dataPelengkap.find((n: any) => n.key == item.key)?.value
                      }
                    />
                  ) : item.type == "date" ? (
                    <DateInput
                      locale="id"
                      valueFormat="DD MMMM YYYY"
                      label={<FieldLabel label={item.name} hint={item.desc} />}
                      placeholder={item.name}
                      onChange={(e) => {
                        const formatted = e
                          ? dayjs(e).locale("id").format("DD MMMM YYYY")
                          : "";
                        validationForm({
                          kategori: "dataPelengkap",
                          value: {
                            id: item.id,
                            key: item.key,
                            value: formatted,
                          },
                        });
                      }}
                      value={
                        formSurat.dataPelengkap.find(
                          (n: any) => n.key === item.key,
                        )?.value
                          ? parseTanggalID(
                            formSurat.dataPelengkap.find(
                              (n: any) => n.key === item.key,
                            )?.value,
                          )
                          : parseTanggalID(item.value)
                      }
                    />
                  ) : (
                    <TextInput
                      error={errors[item.id]}
                      label={<FieldLabel label={item.name} hint={item.desc} />}
                      placeholder={item.name}
                      type={item.type}
                      onChange={(e) =>
                        validationForm({
                          kategori: "dataPelengkap",
                          value: {
                            id: item.id,
                            key: item.key,
                            value: e.target.value,
                          },
                        })
                      }
                      value={
                        formSurat.dataPelengkap.find((n) => n.id === item.id)
                          ?.value ??
                        dataPelengkap.find((n: any) => n.key == item.key)?.value
                      }
                      disabled={status != "ditolak" && status != "antrian"}
                    />
                  )}
                </Grid.Col>
              ))}
            </Grid>
          </FormSection>

          <FormSection
            title="Syarat Dokumen"
            description="Syarat dokumen yang diperlukan"
            icon={<IconFiles size={16} />}
          >
            <Grid>
              {dataSyaratDokumen.map((item: any, index: number) => (
                <Grid.Col span={6} key={index}>
                  <FileInputWrapper
                    label={item.desc}
                    placeholder={"Upload file terbaru untuk mengupdate"}
                    accept="image/*,application/pdf"
                    linkView={item.value}
                    onChange={(file) =>
                      validationForm({
                        kategori: "syaratDokumen",
                        value: { id: item.id, key: item.key, value: file },
                      })
                    }
                    name={item.name}
                    disabled={status != "ditolak" && status != "antrian"}
                  />
                </Grid.Col>
              ))}
            </Grid>
          </FormSection>

          <Group justify="right" mt="md">
            <Button
              onClick={() => {
                onChecking();
              }}
              disabled={status != "ditolak" && status != "antrian"}
            >
              Kirim
            </Button>
          </Group>
        </>
      )}
    </>
  );
}
