import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab';
import Grid from '@mui/material/Grid';
import { useEffect, useMemo, useRef, useState } from 'react';
import type { Resolver } from 'react-hook-form';
import { FormProvider, useForm } from 'react-hook-form';
import { CustomBreadcrumbs } from 'src/components/custom-breadcrumbs';
import { DashboardContent } from 'src/layouts/dashboard';
import { paths } from 'src/routes/paths';
import HeadingRekam from 'src/shared/components/HeadingRekam';
import type z from 'zod';
import FormSkeleton from 'src/shared/skeletons/FormSkeleton';
import Agreement from 'src/shared/components/agreement/Agreement';
import Stack from '@mui/material/Stack';
import { enqueueSnackbar } from 'notistack';
import { useNavigate, useParams } from 'react-router';
import useUploadDokumenLainKeluaran from '../hooks/useUploadDokumenLainKeluaran';
import { useGetDokumenLainKeluaranById } from '../hooks/useGetDokumenLainKeluaran';
import type { TDokumenLainKeluaranSchema } from '../schemas/dokumenTransaksiSchema';
import { DokumenLainKeluaranSchema } from '../schemas/dokumenTransaksiSchema';
import { useAppSelector } from 'src/store';
import useSaveDokumenLainKeluaran from '../hooks/useSaveDokumenLainKeluaran';
import ModalUploadDokumenLainKeluaran from '../components/dialog/ModalUploadDokumenLainKeluaran';
import DokumenTransaksi from '../components/rekamDokumenLainKeluaran/DokumenTransaksi';
import InformasiPembeli from '../components/rekamDokumenLainKeluaran/InformasiPembeli';
import TotalTransaksi from '../components/rekamDokumenLainKeluaran/TotalTransaksi';
import DetailTransaksi from '../components/rekamDokumenLainKeluaran/DetailTransaksi';
import dayjs from 'dayjs';

const DokumenLainKeluaranRekamView = () => {
  const { id, type } = useParams<{ id?: string; type?: 'ubah' | 'pengganti' | 'new' }>();

  const [isCheckedAgreement, setIsCheckedAgreement] = useState<boolean>(false);
  // const [isFormPrefilled, setIsFormPrefilled] = useState<boolean>(false);
  const [formInitialized, setFormInitialized] = useState<boolean>(false);
  const [isUploadModalOpen, setIsUploadModalOpen] = useState<boolean>(false);
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const [jumlahKeterangan, setJumlahKeterangan] = useState<number>(0);

  const lastValidityRef = useRef<boolean | null>(null);

  const isEdit = type === 'ubah';
  const isPengganti = type === 'pengganti';

  const signer = useAppSelector((state) => state.user.data.signer);

  const { data: existingDlk, isLoading: isLoadingDlk } = useGetDokumenLainKeluaranById(id!, {
    enabled: !!id && (isEdit || isPengganti),
  });

  const navigate = useNavigate();

  type DokumenLainKeluaranFormData = z.infer<typeof DokumenLainKeluaranSchema>;

  const saveDokumenLainKeluaran = useSaveDokumenLainKeluaran({
    onSuccess: () => enqueueSnackbar('Data berhasil disimpan', { variant: 'success' }),
  });

  const uploadDokumenLainKeluaran = useUploadDokumenLainKeluaran();

  const defaultValues: TDokumenLainKeluaranSchema = useMemo(() => {
    const today = dayjs();
    const todayTanggal = dayjs().startOf('day').toDate();

    return {
      /* ===== Header ===== */
      isCreatedByBuyer: false,
      kdTransaksi: 'DELIVERY',
      fgPengganti: 'TD.00400',
      detailTransaksi: 'TD.00312',

      /* ===== Dokumen ===== */
      dokumenTransaksi: 'OSD.00605',
      kodeDokumen: 'OSD.00702',
      nomorDokumen: '',
      nomorDokumenDiganti: '',
      tanggalDokumen: todayTanggal,
      tanggalDokumenDiganti: null,

      /* ===== Masa Pajak ===== */
      masaPajak: today.format('MM'), // ✅ "01" - "12"
      tahunPajak: today.format('YYYY'),

      /* ===== Keterangan ===== */
      referensi: '',
      refDoc: '',
      keteranganTambahan: '',
      idKeteranganTambahan: '',
      npwpPembeli: '',
      namaPembeli: '',
      alamatPembeli: '',

      /* ===== Nilai Transaksi ===== */
      jumlahDpp: 0,
      jumlahPpn: 0,
      jumlahPpnbm: 0,
      jumlahDppLain: 0,

      totalJumlahBarang: 0,
      totalHarga: 0,
      totalDiskon: 0,
      isPpnManual: false,

      /* ===== Objek Faktur ===== */
      objekFaktur: [],

      /* ===== Keterangan tambahan (maks 5) ===== */
      keterangan1: '',
      keterangan2: '',
      keterangan3: '',
      keterangan4: '',
      keterangan5: '',

      /* ===== Approval ===== */
      approvalSign: '',
    };
  }, []);

  const methods = useForm<DokumenLainKeluaranFormData>({
    mode: 'all',
    resolver: zodResolver(DokumenLainKeluaranSchema) as Resolver<DokumenLainKeluaranFormData, any>,
    defaultValues,
    shouldUnregister: false,
  });

  const { reset, handleSubmit, setValue } = methods;

  const normalizeExistingDokumenLainKeluaran = (data: any): TDokumenLainKeluaranSchema | null => {
    if (!data) return null;

    const mapNum = (v: any) => {
      if (v === null || v === undefined || v === '') return 0;
      const n = Number(String(v).replace(/,/g, ''));
      return Number.isFinite(n) ? n : 0;
    };

    const mapStr = (v: any) => (v === null || v === undefined ? '' : String(v));

    const objekFaktur = Array.isArray(data.objekFaktur)
      ? data.objekFaktur.map((it: any, idx: number) => ({
          id: String(it.id ?? `${Date.now()}-${idx}`),

          brgJasa: it.brgJasa ?? '',
          kdBrgJasa: it.kdBrgJasa ?? '',
          namaBrgJasa: it.namaBrgJasa ?? '',
          satuanBrgJasa: it.satuanBrgJasa ?? '',

          hargaSatuan: mapNum(it.hargaSatuan),
          jmlBrgJasa: mapNum(it.jmlBrgJasa),
          totalHarga: mapNum(it.totalHarga),
          diskon: mapNum(it.diskon),

          dpp: mapNum(it.dpp),
          dppLain: mapNum(it.dppLain ?? 0), // 🔥 INI WAJIB
          cekDppLain: Boolean(it.cekDppLain), // 🔥 INI WAJIB

          tarifPpn: mapNum(it.tarifPpn),
          ppn: mapNum(it.ppn),

          tarifPpnbm: mapNum(it.tarifPpnbm),
          ppnbm: mapNum(it.ppnbm),
        }))
      : [];

    const base: TDokumenLainKeluaranSchema = {
      ...defaultValues,
    } as TDokumenLainKeluaranSchema;

    // backend has several similar field names — be permissive:
    const jumlahDppFromApi = mapNum(data.jumlahdpp ?? data.jumlahdpp ?? data.jumlahdpp ?? 0);
    const jumlahDppLainFromApi = mapNum(
      data.jumlahdpplain ?? data.jumlahdplain ?? data.jumlahDpLain ?? data.jumlahdpplain ?? 0
    );
    const jumlahPpnFromApi = mapNum(data.jumlahppn ?? data.returMaxPpn ?? 0);
    const jumlahPpnbmFromApi = mapNum(data.jumlahppnbm ?? data.returMaxPpnbm ?? 0);

    const totalHargaFromApi = mapNum(data.totalharga ?? 0);
    const totalJumlahBarangFromApi = mapNum(data.totaljumlahbarang ?? 0);
    const totalDiskonFromApi = mapNum(data.totaldiskon ?? 0);

    return {
      ...base,
      /* Header */
      kdTransaksi: mapStr(data.kdtransaksi) || base.kdTransaksi,
      fgPengganti: mapStr(data.fgpengganti) || base.fgPengganti,
      detailTransaksi: mapStr(data.detailtransaksi) || base.detailTransaksi,
      keteranganTambahan: data.keterangantambahan ?? base.keteranganTambahan,

      dokumenTransaksi: mapStr(data.dokumentransaksi) || base.dokumenTransaksi,
      kodeDokumen: mapStr(data.kodedokumen) || base.kodeDokumen,
      nomorDokumen: mapStr(data.nomordokumen) || base.nomorDokumen,
      nomorDokumenDiganti: mapStr(data.nomordokumendiganti) || base.nomorDokumenDiganti,

      tanggalDokumen: data.tanggaldokumen
        ? dayjs(data.tanggaldokumen).toDate()
        : base.tanggalDokumen,
      tanggalDokumenDiganti: data.tanggaldokumendiganti
        ? dayjs(data.tanggaldokumendiganti).toDate()
        : base.tanggalDokumenDiganti,

      masaPajak: mapStr(data.masapajak) || base.masaPajak,
      tahunPajak: mapStr(data.tahunpajak) || base.tahunPajak,
      referensi: mapStr(data.referensi) || base.referensi,

      /* Nilai (pastikan number, bukan string) */
      jumlahDpp: jumlahDppFromApi,
      jumlahDppLain: jumlahDppLainFromApi,
      jumlahPpn: jumlahPpnFromApi,
      jumlahPpnbm: jumlahPpnbmFromApi,

      totalJumlahBarang: totalJumlahBarangFromApi,
      totalHarga: totalHargaFromApi,
      totalDiskon: totalDiskonFromApi,

      // set flag so PPN autocalc won't overwrite server value
      isPpnManual: true,

      /* Pembeli */
      namaPembeli: mapStr(data.namapembeli) || base.namaPembeli,
      alamatPembeli: mapStr(data.alamatpembeli) || base.alamatPembeli,
      npwpPembeli: mapStr(data.npwppembeli) || base.npwpPembeli,

      /* Detail */
      objekFaktur,
    };
  };

  // RESET FORM SAAT MASUK CREATE (NEW)
  useEffect(() => {
    if (!isEdit && !isPengganti) {
      // clear any residual API data / validity marker when entering create mode
      reset(defaultValues);
      lastValidityRef.current = null;
      // allow form to render defaults immediately
      setFormInitialized(true);
    }
    // include reset & defaultValues to avoid stale closures
  }, [isEdit, isPengganti, reset, defaultValues]);

  useEffect(() => {
    if (!isEdit && !isPengganti) {
      setFormInitialized(true);
      return;
    }

    if (existingDlk) {
      const normalized = normalizeExistingDokumenLainKeluaran(existingDlk);

      if (normalized) {
        reset(normalized);
      }

      setFormInitialized(true);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [existingDlk, isEdit, isPengganti, reset]);

  useEffect(() => {
    if ((isEdit || isPengganti) && existingDlk) {
      const count = [1, 2, 3, 4, 5].filter((i) => existingDlk[`keterangan${i}`]).length;

      setJumlahKeterangan(count);
    }
  }, [existingDlk, isEdit, isPengganti]);

  // const buildPayload = (values: DokumenLainKeluaranFormData) => {
  //   const payload = {
  //     ...values,

  //     // 🔒 KUNCI FORMAT TANGGAL DI SINI
  //     tanggalDokumen: dayjs(values.tanggalDokumen).format('DDMMYYYY'),

  //     tanggalDokumenDiganti: values.tanggalDokumenDiganti
  //       ? dayjs(values.tanggalDokumenDiganti).format('DDMMYYYY')
  //       : null,
  //   };

  //   if (isEdit) {
  //     return {
  //       ...payload,
  //       id,
  //     };
  //   }

  //   return payload;
  // };

  const buildPayload = (values: TDokumenLainKeluaranSchema) => {
    const payload = {
      ...values,

      // 🔒 KUNCI FORMAT TANGGAL DI SINI
      tanggalDokumen: dayjs(values.tanggalDokumen).format('DDMMYYYY'),

      tanggalDokumenDiganti: values.tanggalDokumenDiganti
        ? dayjs(values.tanggalDokumenDiganti).format('DDMMYYYY')
        : null,
    } as any;

    // ✅ PASTIKAN keterangan1 - keterangan5 SELALU IKUT
    for (let i = 1; i <= 5; i++) {
      const key = `keterangan${i}`;
      payload[key] = values[key as keyof TDokumenLainKeluaranSchema] ?? '';
    }

    if (isEdit) {
      return {
        ...payload,
        id,
      };
    }

    return payload;
  };

  const onSubmit = async (values: DokumenLainKeluaranFormData) => {
    try {
      const payload = buildPayload(values);

      await saveDokumenLainKeluaran.mutateAsync(payload);

      enqueueSnackbar(
        isEdit
          ? 'Data berhasil diperbarui'
          : isPengganti
            ? 'Data pengganti berhasil disimpan'
            : 'Data berhasil disimpan',
        { variant: 'success' }
      );

      navigate('/faktur/dokumen-lain/pajak-keluaran');
    } catch (error: any) {
      enqueueSnackbar(error.message || 'Gagal menyimpan data', { variant: 'error' });
      console.error('❌ saveDokumenLainKeluaran error:', error);
    }
  };

  const handleSaveAndUpload = async (values: DokumenLainKeluaranFormData) => {
    try {
      const payload = buildPayload(values);
      const res: any = await saveDokumenLainKeluaran.mutateAsync(payload);

      const savedId = res?.id;
      if (!savedId) throw new Error('ID dokumen tidak ditemukan dari hasil save');

      await uploadDokumenLainKeluaran.mutateAsync({ id: savedId });

      enqueueSnackbar('Data berhasil disimpan dan diupload', { variant: 'success' });
      navigate('/faktur/dokumen-lain/pajak-keluaran');
    } catch (error: any) {
      enqueueSnackbar(error.message || 'Gagal save & upload data', { variant: 'error' });
      console.error('❌ Upload error:', error);
    }
  };

  const handleSaveDraft = async () => {
    try {
      const values = methods.getValues(); // ⛔ tanpa validation
      const payload = buildPayload(values);

      await saveDokumenLainKeluaran.mutateAsync(payload);

      enqueueSnackbar('Draft berhasil disimpan', { variant: 'success' });
      navigate('/faktur/dokumen-lain/pajak-keluaran');
    } catch (error: any) {
      enqueueSnackbar(error.message || 'Gagal menyimpan draft', { variant: 'error' });
    }
  };

  // Auto set tkuPembeli berdasarkan mode
  useEffect(() => {
    // mode EDIT / PENGGANTI dan data sudah ada
    if ((isEdit || isPengganti) && existingDlk) {
      setValue('approvalSign', signer);
    }
  }, [isEdit, isPengganti, existingDlk, signer, setValue]);

  if (isLoadingDlk || !formInitialized) {
    return (
      <DashboardContent>
        <CustomBreadcrumbs
          heading={
            isEdit
              ? 'Ubah Dokuman Lain Keluaran'
              : isPengganti
                ? 'Dokumen Lain Keluaran Pengganti'
                : 'Tambah Dokumen Lain Keluaran'
          }
          links={[
            { name: 'Dashboard', href: paths.dashboard.root },
            { name: 'Dokumen Lain Keluaran ', href: paths.faktur.dlk },
            { name: isEdit ? 'Ubah' : isPengganti ? 'Pengganti' : 'Tambah' },
          ]}
        />

        <HeadingRekam
          label={
            isEdit
              ? 'Ubah Data Dokumen Lain Keluaran'
              : isPengganti
                ? 'Rekam Dokumen Lain Keluaran Pengganti'
                : 'Rekam Dokumen Lain Keluaran '
          }
        />
        <FormSkeleton numberOfRows={8} />
      </DashboardContent>
    );
  }

  return (
    <DashboardContent>
      <CustomBreadcrumbs
        heading={
          isEdit
            ? 'Ubah Dokumen Lain Keluaran'
            : isPengganti
              ? 'Dokumen Lain Keluaran Pengganti'
              : 'Tambah Dokumen Lain Keluaran'
        }
        links={[
          { name: 'Dashboard', href: paths.dashboard.root },
          { name: 'Dokumen Lain Keluaran ', href: paths.faktur.dlk },
          { name: isEdit ? 'Ubah' : isPengganti ? 'Pengganti' : 'Tambah' },
        ]}
      />

      <HeadingRekam
        label={
          isEdit
            ? 'Ubah Data Dokumen Lain Keluaran'
            : isPengganti
              ? 'Rekam Dokumen Lain Keluaran Pengganti'
              : 'Rekam Dokumen Lain Keluaran '
        }
      />

      <Grid container columnSpacing={2}>
        <Grid size={{ xs: 12 }}>
          <FormProvider {...methods}>
            <form onSubmit={handleSubmit(onSubmit)}>
              <DokumenTransaksi dlkData={existingDlk} />
              <InformasiPembeli dlkData={existingDlk} />
              <DetailTransaksi dlkData={existingDlk} />
              <TotalTransaksi dlkData={existingDlk} />

              <Grid size={12}>
                <Agreement
                  isCheckedAgreement={isCheckedAgreement}
                  setIsCheckedAgreement={setIsCheckedAgreement}
                  text="Dengan ini saya menyatakan bahwa Faktur Pajak telah saya isi dengan benar, lengkap, dan jelas."
                />
              </Grid>
              <Stack direction="row" gap={2} justifyContent="end" marginTop={2}>
                <LoadingButton
                  type="button"
                  loading={saveDokumenLainKeluaran.isPending}
                  disabled={!isCheckedAgreement}
                  variant="outlined"
                  sx={{ color: '#143B88' }}
                  onClick={handleSaveDraft}
                >
                  Save as Draft
                </LoadingButton>
                <LoadingButton
                  type="button"
                  disabled={!isCheckedAgreement}
                  onClick={() => setIsUploadModalOpen(true)}
                  loading={uploadDokumenLainKeluaran.isPending}
                  variant="contained"
                  sx={{ background: '#143B88' }}
                >
                  Save and Upload
                </LoadingButton>
              </Stack>
            </form>
          </FormProvider>
        </Grid>
      </Grid>

      {isUploadModalOpen && (
        <ModalUploadDokumenLainKeluaran
          isOpenDialogUpload={isUploadModalOpen}
          setIsOpenDialogUpload={setIsUploadModalOpen}
          onConfirmUpload={() => handleSaveAndUpload(methods.getValues())}
          singleUploadPayload={methods.getValues()}
        />
      )}
    </DashboardContent>
  );
};

export default DokumenLainKeluaranRekamView;
