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 useSaveFakturPk from '../hooks/useSaveFakturPK';
import { enqueueSnackbar } from 'notistack';
import { useNavigate, useParams } from 'react-router';
import useUpload from '../hooks/useUpload';
import { useGetFakturPKById } from '../hooks/useGetFakturPK';
import ModalUploadFakturPK from '../components/dialog/ModalUploadFakturPK';
import DokumenTransaksi from '../components/rekamFakturPK/DokumenTransaksi';
import InformasiPembeli from '../components/rekamFakturPK/InformasiPembeli';
import type { TFakturPkSchema } from '../schemas/dokumenTransaksiSchema';
import { FakturPkSchema } from '../schemas/dokumenTransaksiSchema';
import DetailTransaksi from '../components/rekamFakturPK/DetailTransaksi';
import TotalTransaksi from '../components/rekamFakturPK/TotalTransaksi';
import UangMuka from '../components/rekamFakturPK/UangMuka';
import { Field } from 'src/components/hook-form';
import MenuItem from '@mui/material/MenuItem';
import { useAppSelector } from 'src/store';
import fakturApi from '../utils/api';
import PanduanDigunggungRekam from '../components/PanduanDigunggungRekam';
import { useQuery } from '@tanstack/react-query';
import useGetDetailUangMuka from '../hooks/useGetDetailUangMuka';

const PAYMENT_SINGLE_PAYMENT = 'single_payment';
const PAYMENT_UANG_MUKA = 'uang_muka';
const PAYMENT_PELUNASAN = 'pelunasan';

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

  const [isOpenPanduan, setIsOpenPanduan] = useState<boolean>(false);
  const [isCheckedAgreement, setIsCheckedAgreement] = useState<boolean>(false);
  // const [isFormPrefilled, setIsFormPrefilled] = useState<boolean>(false);
  const [formInitialized, setFormInitialized] = useState<boolean>(false);
  const [isUploadModalOpen, setIsUploadModalOpen] = useState<boolean>(false);

  const [fakturData, setFakturData] = useState<any>(null);
  const [loading, setLoading] = useState(false);

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

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

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

  const { data: existingFakturPK, isLoading: isLoadingFaktur } = useGetFakturPKById(id!, {
    enabled: !!id && (isEdit || isPengganti),
  });

  const navigate = useNavigate();

  type FakturPkFormData = z.infer<typeof FakturPkSchema>;

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

  const uploadFakturPk = useUpload();

  const handleOpenPanduan = () => setIsOpenPanduan(!isOpenPanduan);

  const defaultValues: TFakturPkSchema = useMemo(
    () => ({
      detailTransaksi: 'TD.00301',
      idKeteranganTambahan: '',
      refDoc: '',
      fgPengganti: '0',
      nomorFaktur: '',
      tanggalFaktur: '',
      masaTahunPajak: '',
      referensi: '',
      npwpPembeli: '',
      namaPembeli: '',
      tkuPembeli: '',
      alamatPembeli: '',
      idLainPembeli: '0',
      fgUangMuka: '',
      kdNegaraPembeli: '',
      totalJumlahBarang: 0,
      totalHarga: 0,
      totalDiskon: 0,
      totalDpp: 0,
      totalDppLain: 0,
      totalPpn: 0,
      totalPpnbm: 0,
      keterangan1: '',
      keterangan2: '',
      keterangan3: '',
      keterangan4: '',
      keterangan5: '',
      approvalSign: '',
    }),
    []
  );

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

  const { reset, handleSubmit, watch, setValue } = methods;

  const nomorFaktur = String(watch('nomorFaktur') ?? '').replace(/[^\d]/g, '');

  const resolveFgUangMuka = (raw: any) => {
    const isUangMuka = Boolean(raw.fguangmuka);
    const isPelunasan = Boolean(raw.fgpelunasan);

    if (isUangMuka) return PAYMENT_UANG_MUKA;
    if (isPelunasan) return PAYMENT_PELUNASAN;
    return PAYMENT_SINGLE_PAYMENT;
  };

  const normalizeExistingFaktur = (data: any) => {
    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 objekFakturMapped = Array.isArray(data.objekFaktur)
      ? data.objekFaktur.map((it: any, idx: number) => ({
          id: String(it.id ?? `${Date.now()}-${idx}`),
          brgJasa: it.brgJasa ?? it.type ?? '',
          namaBrgJasa: it.namaBrgJasa ?? it.nama ?? '',
          kdBrgJasa: it.kdBrgJasa ?? it.kode ?? '',
          jmlBrgJasa: mapNum(it.jmlBrgJasa),
          satuanBrgJasa: it.satuanBrgJasa ?? it.satuan ?? '',
          hargaSatuan: mapNum(it.hargaSatuan),
          totalHarga: mapNum(it.totalHarga),
          diskon: mapNum(it.diskon),
          dpp: mapNum(it.dpp),
          dppLain: mapNum(it.dppLain),
          ppn: mapNum(it.ppn),
          ppnbm: mapNum(it.ppnbm),
          tarifPpn: mapNum(it.tarifPpn),
          tarifPpnbm: mapNum(it.tarifPpnbm),
          cekDppLain: it.cekDppLain ?? false,
        }))
      : [];

    return {
      fgUangMuka: resolveFgUangMuka(data),
      detailTransaksi: data.detailtransaksi ?? '',
      idKeteranganTambahan: data.idketerangantambahan ?? '',
      refDoc: data.refdoc ?? '',
      fgPengganti: String(data.fgpengganti ?? '0'),
      nomorFaktur: data.nomorfaktur ?? '',
      tanggalFaktur: data.tanggalfaktur ?? '',
      masaTahunPajak: `${data.tahunpajak ?? ''}-${data.masapajak?.toString().padStart(2, '0')}`,
      referensi: data.referensi ?? '',
      npwpPembeli: data.npwppembeli ?? '',
      namaPembeli: data.namapembeli ?? '',
      tkuPembeli: data.namatokopenjual ?? data.tkupembeli ?? '',
      alamatPembeli: data.alamatpembeli ?? '',
      idLainPembeli: data.idlainpembeli ?? '0',
      totalJumlahBarang: objekFakturMapped?.[0]?.jmlBrgJasa ?? 0,
      totalHarga: objekFakturMapped?.[0]?.totalHarga ?? 0,
      totalDiskon: objekFakturMapped?.[0]?.diskon ?? 0,
      totalDpp: objekFakturMapped?.[0]?.dpp ?? 0,
      totalDppLain: objekFakturMapped?.[0]?.dppLain ?? 0,
      totalPpn: objekFakturMapped?.[0]?.ppn ?? 0,
      totalPpnbm: objekFakturMapped?.[0]?.ppnbm ?? 0,
      keterangan1: data.keterangan1 ?? '',
      keterangan2: data.keterangan2 ?? '',
      keterangan3: data.keterangan3 ?? '',
      keterangan4: data.keterangan4 ?? '',
      keterangan5: data.keterangan5 ?? '',
      // penting: sertakan objekFaktur yg sudah dipetakan
      objekFaktur: objekFakturMapped,
    };
  };

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

  const [debouncedNomor, setDebouncedNomor] = useState<string>('');
  useEffect(() => {
    const t = setTimeout(() => setDebouncedNomor((nomorFaktur ?? '').trim()), 500);
    return () => clearTimeout(t);
  }, [nomorFaktur]);

  // derive fgUangMuka value from form
  const fgUangMukaForm = String(watch('fgUangMuka') ?? PAYMENT_SINGLE_PAYMENT);

  const shouldUseUangMukaApi =
    fgUangMukaForm === PAYMENT_UANG_MUKA || fgUangMukaForm === PAYMENT_PELUNASAN;

  const isValidNomor = debouncedNomor.length === 17;

  const {
    data: uangMukaDetail,
    isLoading: isLoadingUangMuka,
    isFetching: isFetchingUangMuka,
  } = useGetDetailUangMuka(debouncedNomor, {
    enabled: isValidNomor && shouldUseUangMukaApi,
  });

  // query: regular faktur lookup (replaces manual fakturApi.getFakturPK in effect)
  const {
    data: fakturSearchResult,
    isLoading: isLoadingFakturSearch,
    isFetching: isFetchingFakturSearch,
  } = useQuery({
    queryKey: ['faktur', 'byNomor', debouncedNomor],
    queryFn: async () => {
      const res = await fakturApi.getFakturPK({ params: { nomorFaktur: debouncedNomor } });
      const data = Array.isArray(res?.data) ? res.data[0] : res?.data;
      return data ?? null;
    },
    enabled: isValidNomor && !shouldUseUangMukaApi && !isPengganti,
    refetchOnWindowFocus: false,
  });

  useEffect(() => {
    // if nomor invalid -> clear minimal state
    if (!isValidNomor) {
      if (fakturData) setFakturData(null);
      setValue('idLainPembeli', '0', { shouldDirty: false });
      setLoading(false);
      lastValidityRef.current = false;
      return;
    }

    // avoid duplicate handling if validity hasn't changed and data present
    if (lastValidityRef.current !== true) lastValidityRef.current = true;

    // aggregate loading
    const loadingNow = shouldUseUangMukaApi
      ? isLoadingUangMuka || isFetchingUangMuka
      : isLoadingFakturSearch || isFetchingFakturSearch;

    setLoading(Boolean(loadingNow));

    // prefer uangMukaDetail when appropriate
    if (shouldUseUangMukaApi) {
      if (uangMukaDetail) {
        setFakturData({ ...uangMukaDetail, _ts: Date.now() });
        setLoading(false);
        return;
      }

      // if not loading and no data -> clear
      if (!loadingNow) setFakturData(null);
      return;
    }

    // regular faktur search
    if (fakturSearchResult) {
      setFakturData({ ...fakturSearchResult, _ts: Date.now() });
      setLoading(false);
      return;
    }

    if (!loadingNow) setFakturData(null);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    debouncedNomor,
    shouldUseUangMukaApi,
    uangMukaDetail,
    fakturSearchResult,
    isLoadingUangMuka,
    isFetchingUangMuka,
    isLoadingFakturSearch,
    isFetchingFakturSearch,
  ]);

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

    if (existingFakturPK) {
      const normalized = normalizeExistingFaktur(existingFakturPK);

      if (normalized) {
        if (isEdit || isPengganti) {
          setFakturData({ ...existingFakturPK, _ts: Date.now() });
        }
        reset(normalized);
        // setIsFormPrefilled(true);
      }

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

  const buildPayload = (values: FakturPkFormData) => {
    if (isEdit) {
      return {
        ...values,
        id,
      };
    }

    return {
      ...values,
    };
  };

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

      await saveFakturPk.mutateAsync(payload);

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

      navigate('/faktur/pk/');
    } catch (error: any) {
      enqueueSnackbar(error.message || 'Gagal menyimpan data', { variant: 'error' });
      console.error('❌ saveFakturPk error:', error);
    }
  };

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

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

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

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

  // Auto set tkuPembeli berdasarkan mode
  useEffect(() => {
    // mode NEW
    if (!isEdit && !isPengganti) {
      setValue('tkuPembeli', signer);
      return;
    }

    // mode EDIT / PENGGANTI dan data sudah ada
    if ((isEdit || isPengganti) && existingFakturPK) {
      setValue('approvalSign', signer);
    }
  }, [isEdit, isPengganti, existingFakturPK, signer, setValue]);

  if (isLoadingFaktur || !formInitialized) {
    return (
      <DashboardContent>
        <CustomBreadcrumbs
          heading={
            isEdit
              ? 'Ubah Faktur Pajak Keluaran'
              : isPengganti
                ? 'Faktur Pajak Keluaran Pengganti'
                : 'Tambah Faktur Pajak Keluaran'
          }
          links={[
            { name: 'Dashboard', href: paths.dashboard.root },
            { name: 'e-Faktur Pajak Keluaran ', href: paths.faktur.pk },
            { name: isEdit ? 'Ubah' : isPengganti ? 'Pengganti' : 'Tambah' },
          ]}
        />

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

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

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

      <Grid container columnSpacing={2}>
        <Grid size={{ xs: isOpenPanduan ? 8 : 11 }}>
          <FormProvider {...methods}>
            <form onSubmit={handleSubmit(onSubmit)}>
              <DokumenTransaksi fakturData={fakturData} isLoading={loading} />

              <InformasiPembeli fakturData={fakturData} isLoading={loading} />
              <DetailTransaksi fakturData={fakturData} isLoading={loading} />

              <TotalTransaksi />
              <UangMuka fakturData={fakturData} />
              <Grid size={{ md: 12 }}>
                <Field.Select name="approvalSign" label="NPWP/NIK Penandatangan">
                  <MenuItem value={signer}>{signer}</MenuItem>
                </Field.Select>
              </Grid>

              <Grid size={12}>
                <Agreement
                  isCheckedAgreement={isCheckedAgreement}
                  setIsCheckedAgreement={setIsCheckedAgreement}
                  text="Dengan ini saya menyatakan bahwa Bukti Pemotongan/Pemungutan Unifikasi telah saya isi dengan benar secara elektronik sesuai dengan"
                />
              </Grid>
              <Stack direction="row" gap={2} justifyContent="end" marginTop={2}>
                <LoadingButton
                  type="button"
                  loading={saveFakturPk.isPending}
                  disabled={!isCheckedAgreement}
                  variant="outlined"
                  sx={{ color: '#143B88' }}
                  onClick={methods.handleSubmit((data) => {
                    const raw = methods.getValues(); // 🔥 ambil full form

                    const final = {
                      ...data,
                      objekFaktur: raw.objekFaktur, // merge manual
                    };
                    onSubmit(final);
                  })}
                >
                  Save as Draft
                </LoadingButton>
                <LoadingButton
                  type="button"
                  disabled={!isCheckedAgreement}
                  onClick={() => setIsUploadModalOpen(true)}
                  loading={uploadFakturPk.isPending}
                  variant="contained"
                  sx={{ background: '#143B88' }}
                >
                  Save and Upload
                </LoadingButton>
              </Stack>
            </form>
          </FormProvider>
        </Grid>
        <Grid size={{ xs: isOpenPanduan ? 4 : 1 }}>
          <PanduanDigunggungRekam handleOpen={handleOpenPanduan} isOpen={isOpenPanduan} />
        </Grid>
      </Grid>

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

export default FakturPkRekamView;
