import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab';
import Divider from '@mui/material/Divider';
import Grid from '@mui/material/Grid';
import Stack from '@mui/material/Stack';
import dayjs from 'dayjs';
import { enqueueSnackbar } from 'notistack';
import { Suspense, useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router';
import { useKodeNegara } from 'src/actions/master-data';
import { CustomBreadcrumbs } from 'src/components/custom-breadcrumbs';
import { Field } from 'src/components/hook-form';
import { DashboardContent } from 'src/layouts/dashboard';
import { paths } from 'src/routes/paths';
import {
  FG_FASILITAS_PPH_21,
  FG_FASILITAS_PPH_21_TEXT,
  KELAMIN,
  KELAMIN_TEXT,
  KODE_OBJEK_PAJAK,
  KODE_OBJEK_PAJAK_TEXT,
  MockNitku,
  PTKP,
  PTKP_TEXT,
  PTKP_TITLE,
  SETAHUN,
  SETAHUN_TEXT,
} from 'src/sections/bupot-21-26/constant';
import Agreement from 'src/shared/components/agreement/Agreement';
import HeadingRekam from 'src/shared/components/HeadingRekam';
import FormSkeleton from 'src/shared/skeletons/FormSkeleton';
import z from 'zod';
import DialogPenandatangan from '../components/dialog/ModalUploadTahunanA1';
import Identitas from '../components/rekam/Identitas';
import PerhitunganA1Container from '../components/rekam/PerhitunganA1';
import RincianPenghasilan from '../components/rekam/RincianPenghasilan';
import useGetTahunanA1 from '../hooks/useGetTahunanA1';
import useSaveTahunanA1 from '../hooks/useSaveTahunanA1';
import useUploadBulanan from '../hooks/useDeleteTahunanA1';
import { formatDate } from '../utils/formatDate';

const TahunanA1Schema = z
  .object({
    id: z.number().optional(),
    idBupot: z.string().optional(),
    noBupot: z.string().optional(),
    revNo: z.string().optional(),
    internal_id: z.string().optional(),

    npwp: z
      .string()
      .superRefine((val, ctx) => {
        if (!val) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            message: 'NPWP wajib diisi',
          });
        } else if (val.length !== 16) {
          ctx.addIssue({
            code: z.ZodIssueCode.custom,
            message: 'NPWP harus 16 digit',
          });
        }
      })
      .optional(),
    nitku: z.string().length(22, 'NITKU harus 22 digit'),
    nama: z.string().min(1, 'Nama wajib diisi'),
    alamat: z.string().min(1, 'Alamat wajib diisi'),
    optJnsKelamin: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'Jenis Kelamin wajib diisi',
      }),
    namaJabatan: z.string().min(1, 'Jabatan wajib diisi'),
    fgKaryawanAsing: z.boolean().optional(),
    kodeNegara: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .optional(),
    passport: z.string().optional(),
    metodePemotongan: z.string().min(1, 'Jenis   wajib diisi'),
    noBupotSebelumnya: z.string().optional(),
    tglPemotongan: z.string().min(1, 'Tanggal Pemotongan wajib diisi'),
    tahunPajak: z.string().min(1, 'Tahun Pajak wajib diisi'),
    masaPajakAwal: z
      .string('Masa Tahun Pajak Awal wajib diisi')
      .refine(
        (value) => {
          const tahunPajak = formatDate(value, 'YYYY');
          const tahunSekarang = formatDate(new Date(), 'YYYY');
          return tahunPajak <= tahunSekarang;
        },
        { message: 'Tahun Pajak tidak boleh diatas tahun berjalan' }
      )
      .refine(
        (value) => {
          const masaPajak = formatDate(value, 'YYYY-MM');
          const masaSekarang = formatDate(new Date(), 'YYYY-MM');
          return masaPajak <= masaSekarang;
        },
        { message: 'Masa Pajak Awal tidak boleh diatas masa berjalan' }
      ),
    masaPajakAkhir: z.string('Masa Pajak Akhir wajib diisi'),
    kdObjPjk: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'Kode Objek Pajak wajib diisi',
      }),
    fgFasilitas: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'Fasilitas wajib dipilih',
      }),
    noDokLainnya: z.string().optional(),
    jenisPerhitungan: z.string().optional(),
    fgPerhitungan: z.string().min(1, 'Gross/Gross Up wajib diisi'),
    statusPtkp: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'PTKP wajib dipilih',
      }),
    email: z.string().optional(),
    jumlahPenghasilan: z.array(z.object({})).optional(),
    jumlahPengurangan: z.array(z.object({})).optional(),
    idTku: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'NITKU Pemotong wajib diisi',
      }),

    rincian1: z.string().optional(),
    rincian2: z.string().optional(),
    rincian3: z.string().optional(),
    rincian4: z.string().optional(),
    rincian5: z.string().optional(),
    rincian6: z.string().optional(),
    rincian7: z.string().optional(),
    rincian8: z.string().optional(),

    rincian9: z.string().optional(),
    rincian10: z.string().optional(),
    rincian11: z.string().optional(),

    rincian12: z.string().optional(),
    rincian13: z.string().optional(),
    rincian14: z.string().optional(),
    rincian15: z.string().optional(),
    rincian16: z.string().optional(),
    rincian17: z.string().optional(),
    rincian18: z.string().optional(),
    rincian19: z.string().optional(),
    rincian20: z.string().optional(),
    rincian21: z.string().optional(),
    rincian22: z.string().optional(),
    rincian23: z.string().optional(),
  })
  .refine(
    (data) => {
      const bulan = dayjs(data.masaPajakAwal).get('month') + 1;
      const bulanAkhir = dayjs(data.masaPajakAkhir, 'MM').get('month') + 1;
      if (bulan === 12 && bulanAkhir > bulan) {
        return false;
      }
      return true;
    },
    {
      message: 'Masa Pajak Awal tidak boleh 12 dan tidak boleh lebih dari masa pajak akhir',
      path: ['masaPajakAwal'],
    }
)
  .refine(
    (data) => {
      const bulan = dayjs(data.masaPajakAwal).get('month') + 1;
      const bulanAkhir = dayjs(data.masaPajakAkhir, 'MM').get('month') + 1;
      if (bulan === 12 && bulanAkhir < bulan) {
        return false;
      }
      return true;
    },
    {
      message: 'Masa Pajak Akhir tidak boleh kurang dari masa pajak awal',
      path: ['masaPajakAkhir'],
    }
  )
  .refine(
    (data) => {
      if (data.fgKaryawanAsing === true && !data.kodeNegara) {
        return false;
      }
      return true;
    },
    {
      message: 'Kode Negara wajib diisi untuk karyawan asing',
      path: ['kodeNegara'],
    }
  )
  .refine(
    (data) => {
      if (data.fgKaryawanAsing === true && !data.passport) {
        return false;
      }
      return true;
    },
    {
      message: 'Passport wajib diisi untuk karyawan asing',
      path: ['passport'],
    }
  )
  .refine(
    (data) => {
      if (data.fgFasilitas.value !== '9' && !data.noDokLainnya) {
        return false;
      }
      return true;
    },
    {
      message: 'Nomor Dokumen Lainnya',
      path: ['noDokLainnya'],
    }
  )
  .refine(
    (data) => {
      switch (data.kdObjPjk.value) {
        case KODE_OBJEK_PAJAK.BULANAN_01:
        case KODE_OBJEK_PAJAK.BULANAN_02:
        case '21-100-32':
          return !!data.statusPtkp;
        default:
          return true;
      }
    },
    {
      message: 'PTKP wajib diisi',
      path: ['ptkp'],
    }
  );

const genderOptions = [
  { value: KELAMIN.LAKI, label: KELAMIN_TEXT[KELAMIN.LAKI] },
  { value: KELAMIN.PEREMPUAN, label: KELAMIN_TEXT[KELAMIN.PEREMPUAN] },
];

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

  const { mutateAsync: saveTahunanA1, isPending: isSaving } = useSaveTahunanA1({
    onSuccess: () => enqueueSnackbar('Data berhasil disimpan', { variant: 'success' }),
  });
  const { mutate: uploadBulanan, isPending: isUpload } = useUploadBulanan();

  // const [isOpenPanduan, setIsOpenPanduan] = useState<boolean>(false);
  const [isCheckedAgreement, setIsCheckedAgreement] = useState<boolean>(false);
  const [isOpenDialogPenandatangan, setIsOpenDialogPenandatangan] = useState(false);

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

  const dataListKOP = useMemo(
    () =>
      [KODE_OBJEK_PAJAK.BULANAN_01, KODE_OBJEK_PAJAK.BULANAN_02, KODE_OBJEK_PAJAK.BULANAN_03].map(
        (value) => ({
          value,
          label: `${value} : ${KODE_OBJEK_PAJAK_TEXT[value]}`,
        })
      ),
    []
  );

  const { kodeNegara } = useKodeNegara();

  const kodeNegetaOptions = useMemo(
    () => kodeNegara.map((val) => ({ label: val.nama, value: val.kode })),
    [kodeNegara]
  );

  const fgFasilitasOptions = useMemo(
    () =>
      [
        FG_FASILITAS_PPH_21.DTP,
        FG_FASILITAS_PPH_21.FASILITAS_LAINNYA,
        FG_FASILITAS_PPH_21.TANPA_FASILITAS,
      ].map((value) => ({
        value,
        label: FG_FASILITAS_PPH_21_TEXT[value],
      })),
    []
  );

  const ptkpOptions = useMemo(
    () =>
      Object.entries(PTKP)
        .map(([key, value]) => ({ value, label: PTKP_TEXT[value] }))
        .filter((option) => !option.value.includes(PTKP_TITLE.HB)),
    []
  );

  const { data: existingBulanan, isLoading: isLoadingBulanan } = useGetTahunanA1({
    params: {
      page: 1,
      limit: 1,
      id,
    },
    enabled: !!id && (isEdit || isPengganti),
  });

  type TahunanA1FormData = z.infer<typeof TahunanA1Schema>;

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

  const defaultValues: TahunanA1FormData = {
    npwp: '',
    nitku: '',
    nama: '',
    alamat: '',
    optJnsKelamin: { value: '', label: '' },
    fgKaryawanAsing: false,
    kodeNegara: {
      value: '',
      label: '',
    },
    passport: '',
    namaJabatan: '',
    tglPemotongan: '',
    tahunPajak: dayjs().format('YYYY'),
    masaPajakAwal: `${dayjs().month(0)}`,
    masaPajakAkhir: `${dayjs().month(11)}`,
    metodePemotongan: SETAHUN.SETAHUN,
    kdObjPjk: {
      value: '',
      label: '',
    },
    fgFasilitas: {
      value: FG_FASILITAS_PPH_21.TANPA_FASILITAS,
      label: FG_FASILITAS_PPH_21_TEXT[FG_FASILITAS_PPH_21.TANPA_FASILITAS],
    },
    noDokLainnya: '',
    fgPerhitungan: '0', // 0 = Gross, 1 = Gross Up
    statusPtkp: {
      value: '',
      label: '',
    },
    idTku: {
      value: '',
      label: '',
    },
    rincian1: '0',
    rincian2: '0',
    rincian3: '0',
    rincian4: '0',
    rincian5: '0',
    rincian6: '0',
    rincian7: '0',
    rincian8: '0',
    rincian9: '0',
    rincian10: '0',
    rincian11: '0',
    rincian12: '0',
    rincian13: '0',
    rincian14: '0',
    rincian15: '0',
    rincian16: '0',
    rincian17: '0',
    rincian18: '0',
    rincian19: '0',
    rincian20: '0',
    rincian21: '0',
    rincian22: '0',
  };

  const methods = useForm<TahunanA1FormData>({
    mode: 'all',
    resolver: zodResolver(TahunanA1Schema),
    defaultValues,
  });

  console.log('🚀 ~ TahunanA1RekamView:', {
    data: methods.getValues(),
    error: methods.formState.errors,
  });

  useEffect(() => {
    if ((isEdit || isPengganti) && existingBulanan.data.length !== 0) {
      const dataResDetail = existingBulanan.data[0];
      const jnsKelamin = dataResDetail.jnsKelamin === 'M' ? '0' : '1';
      const statusPtkp = `${dataResDetail.statusPtkp}/${dataResDetail.jmlPtkp}`;

      const normalized: TahunanA1FormData = {
        ...dataResDetail,
        masaPajakAwal: `${dayjs(dataResDetail.masaPajakAwal, 'MM')}`,
        masaPajakAkhir: `${dayjs(dataResDetail.masaPajakAkhir, 'MM')}`,
        idBupot: dataResDetail.idBupot || '',
        noBupot: dataResDetail.noBupot || '',
        revNo: dataResDetail.revNo || '',
        nitku: dataResDetail.nik,
        optJnsKelamin: genderOptions.filter((val) => val.value === jnsKelamin)[0] || {
          value: '',
          label: '',
        },
        namaJabatan: dataResDetail.posisiJabatan,
        email: dataResDetail.email || '',
        statusPtkp: ptkpOptions.filter((val) => val.value === statusPtkp)[0] || {
          value: '',
          label: '',
        },
        fgKaryawanAsing: dataResDetail.fgKaryawanAsing === 'true',
        kodeNegara: kodeNegetaOptions.filter(
          (val) => val.value === dataResDetail.kdNegara
        )[0] || {
          value: '',
          label: '',
        },
        metodePemotongan: `${dataResDetail.fgStatusPemotonganPph}`,
        fgPerhitungan: dataResDetail.tunjanganPPhGrossUp === 'NO' ? '0' : '1',

        kdObjPjk: dataListKOP.filter((val) => val.value === dataResDetail.kodeObjekPajak)[0],
        fgFasilitas: fgFasilitasOptions.filter((val) => val.value === dataResDetail.fgFasilitas)[0],
        noDokLainnya: dataResDetail.noDokFasilitas || '',

        // Financial Details (Rincian)
        rincian1: `${dataResDetail.gajiPensiun || 0}`,
        rincian2: `${dataResDetail.tunjanganPPh || 0}`,
        rincian3: `${dataResDetail.tunjanganLainnyaLembur || 0}`,
        rincian4: `${dataResDetail.honorarium || 0}`,
        rincian5: `${dataResDetail.premiAsuransi || 0}`,
        rincian6: `${dataResDetail.natura || 0}`,
        rincian7: `${dataResDetail.tantiemBonus || 0}`,
        rincian8: `${dataResDetail.totalPenghasilanBruto || 0}`,
        rincian9: `${dataResDetail.biayaJabatan || 0}`,
        rincian10: `${dataResDetail.iuranPensiun || 0}`,
        rincian11: `${dataResDetail.zakat || 0}`,
        rincian12: `${dataResDetail.totalPengurang || 0}`,
        rincian13: `${dataResDetail.totalPenghasilanNeto || 0}`,
        rincian14: `${dataResDetail.totalPenghasilanNetoDariBupotSebelumnya || 0}`,
        rincian15: `${dataResDetail.totalPenghasilanNetoPph21 || 0}`,
        rincian16: `${dataResDetail.nominalPtkp || 0}`,
        rincian17: `${dataResDetail.pkpSetahunDisetahunkan || 0}`,
        rincian18: `${dataResDetail.pph21SetahunDisetahunkan || 0}`,
        rincian19: `${dataResDetail.pph21Terutang || 0}`,
        rincian20: `${dataResDetail.pph21DariBupotSebelumnya || 0}`,
        rincian21: `${dataResDetail.pph21DapatDikreditkan || 0}`,
        rincian22: `${dataResDetail.pph21WithheldDtp || 0}`,
        rincian23: `${dataResDetail.pph21KurangLebihBayar || 0}`,

        idTku: MockNitku.filter((val) => val.value === dataResDetail.idTku)[0],
      } as unknown as TahunanA1FormData;

      if (isPengganti) {
        normalized['id'] = undefined;
        normalized['idBupot'] = dataResDetail.idBupot || '';
        normalized['idBupot'] = dataResDetail.noBupot || '';
        normalized['revNo'] = `${Number(dataResDetail.revNo) || 0}`;
      }

      methods.reset(normalized as any);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isEdit, isPengganti, existingBulanan, isLoadingBulanan]);

  const handleDraft = async (data: TahunanA1FormData) => {
    // Transform data sesuai dengan struktur yang dibutuhkan
    const transformedData = {
      ...data,
      id: isEdit || isPengganti ? data.id : undefined,
      fgTransaction: isPengganti ? 'EDIT' : 'NEW',
      kdNegara: data.kodeNegara?.value || null,
      statusPtkp: data.statusPtkp?.value || '',
      kdObjPjk: data.kdObjPjk.value,
      kdJnsPjk: 'PPh Pasal 21', // Sesuaikan dengan konstanta Anda
      fgFasilitas: data.fgFasilitas.value,
      fgGrossUp: parseInt(data.fgPerhitungan || '1', 10),
      idTku: data.idTku.value,
      komponen: data.jumlahPenghasilan || [],
      isPengganti,
    };

    console.log('🚀 ~ handleDraft ~ transformedData:', transformedData);

    const response = await saveTahunanA1(transformedData);

    return response;
  };

  const handleUploud = async (data: TahunanA1FormData) => {
    try {
      const response = await handleDraft(data);
      uploadBulanan({
        id: `${response[0].id}`,
      });
      enqueueSnackbar('Berhasil Menyimpan Data', { variant: 'success' });
    } catch (error: any) {
      enqueueSnackbar(error.message, { variant: 'error' });
    } finally {
      navigate(paths.pph21.tahunan);
    }
  };

  const handleClickUpload = async () => {
    setIsOpenDialogPenandatangan(true);
  };

  const SubmitRekam = async (data: TahunanA1FormData) => {
    try {
      await handleDraft(data);
      enqueueSnackbar(
        isEdit
          ? 'Data berhasil diperbarui'
          : isPengganti
            ? 'Data pengganti berhasil disimpan'
            : 'Data berhasil disimpan',
        { variant: 'success' }
      );

      navigate(paths.pph21.tahunan);
    } catch (error: any) {
      enqueueSnackbar(error.message || 'Gagal menyimpan data', { variant: 'error' });
      console.error('❌ SaveDn error:', error);
    }
  };

  return (
    <>
      <DashboardContent>
        <CustomBreadcrumbs
          heading={`${isPengganti ? 'Pengganti' : isEdit ? 'Edit' : 'Rekam'} Bupot PPh Pasal 21 Tahunan A1`}
          links={[
            { name: 'Dashboard', href: paths.dashboard.root },
            {
              name: 'e-Bupot PPh Pasal 21 Tahunan A1',
              href: paths.pph21.tahunan,
            },
            {
              name: `${isPengganti ? 'Pengganti' : isEdit ? 'Edit' : 'Rekam'} Bupot PPh Pasal 21 Tahunan A1`,
            },
          ]}
        />

        <HeadingRekam
          label={`${isPengganti ? 'Pengganti' : isEdit ? 'Edit' : 'Rekam'} Bupot PPh Pasal 21 Tahunan A1`}
        />

        <Grid container columnSpacing={2}>
          <Grid size={{ xs: 12 }}>
            <form onSubmit={methods.handleSubmit(SubmitRekam)}>
              <FormProvider {...methods}>
                <Suspense fallback={<FormSkeleton />}>
                  <Identitas
                    isPengganti={isPengganti}
                    kodeNegetaOptions={kodeNegetaOptions}
                    ptkpOptions={ptkpOptions}
                  />

                  <Suspense fallback={<FormSkeleton />}>
                    <RincianPenghasilan
                      kodeObjectPajak={dataListKOP}
                      fgFasilitasOptions={fgFasilitasOptions}
                      isPengganti={isPengganti}
                    />
                  </Suspense>

                  <PerhitunganA1Container />

                  <Grid size={{ md: 12 }} mt={3}>
                    <Field.Autocomplete name="idTku" label="NITKU Pemotong" options={MockNitku} />
                  </Grid>

                  <Divider />

                  <Grid size={12}>
                    <Agreement
                      isCheckedAgreement={isCheckedAgreement}
                      setIsCheckedAgreement={setIsCheckedAgreement}
                      text="Dengan ini saya menyatakan bahwa Bukti Potong A1 telah saya isi dengan benar, lengkap, dan jelas"
                    />
                  </Grid>

                  <Stack direction="row" gap={2} justifyContent="end" marginTop={2}>
                    <LoadingButton
                      type="submit"
                      loading={isSaving}
                      disabled={!isCheckedAgreement}
                      variant="outlined"
                      sx={{ color: 'var(--palette-primary-main)' }}
                    >
                      Save as Draft
                    </LoadingButton>
                    <LoadingButton
                      type="button"
                      disabled={!isCheckedAgreement}
                      onClick={methods.handleSubmit(handleClickUpload)}
                      loading={isSaving || isUpload}
                      variant="contained"
                      sx={{ background: 'var(--palette-primary-main)' }}
                    >
                      Save and Upload
                    </LoadingButton>
                  </Stack>
                </Suspense>
              </FormProvider>
            </form>
          </Grid>
        </Grid>
      </DashboardContent>
      {isOpenDialogPenandatangan && (
        <DialogPenandatangan
          isOpenDialogUpload={isOpenDialogPenandatangan}
          setIsOpenDialogUpload={setIsOpenDialogPenandatangan}
          onConfirmUpload={() => methods.handleSubmit(handleUploud)()}
        />
      )}
    </>
  );
};
