import { zodResolver } from '@hookform/resolvers/zod';
import { LoadingButton } from '@mui/lab';
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 { useKodeObjekPajak } from 'src/actions/master-data';
import { CustomBreadcrumbs } from 'src/components/custom-breadcrumbs';
import { DashboardContent } from 'src/layouts/dashboard';
import { paths } from 'src/routes/paths';
import {
  BUPOT_REFERENSI,
  BUPOT_REFERENSI_TEXT,
  FG_FASILITAS,
  FG_FASILITAS_PPH_21,
  FG_FASILITAS_PPH_21_TEXT,
  FG_FASILITAS_TEXT,
  KODE_OBJEK_PAJAK,
  MockNitku,
  PERHITUNGAN_BUPOT21,
  PTKP,
  PTKP_TEXT,
  PTKP_TITLE,
} 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/ModalUploadBupotFinal';
import DokumenReferensi from '../components/rekam/DokumenReferensi';
import Identitas from '../components/rekam/Identitas';
import JumlahPerhitunganForm from '../components/rekam/JumlahPerhitunganForm';
import PerhitunganPPhPasal21 from '../components/rekam/PerhitunganPPhPasal21';
import useGetBupotFinal from '../hooks/useGetBupotFinal';
import useSaveBupotFinal from '../hooks/useSaveBupotFinal';
import useUploadBupotFinal from '../hooks/useUploadeBupotFinal';

const bupotFinalSchema = z
  .object({
    idBupot: z.string().optional(),
    noBupot: z.string().optional(),
    revNo: z.number().optional(),
    tahunPajak: z.string().min(1, 'Tahun Pajak wajib diisi'),
    masaPajak: z.string().min(1, 'Masa Pajak wajib diisi'),
    npwp: z.string().min(1, 'NPWP wajib diisi'),
    nitku: z.string().length(22, 'NITKU harus 22 digit'),
    namaDipotong: z.string().min(1, 'Nama wajib diisi'),
    alamatDipotong: z.string().min(1, 'Alamat wajib diisi'),
    alamat: z.string().nullable().optional(),
    kdObjPjk: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'Kode Objek Pajak wajib diisi',
      }),
    pasalPPh: z.string().optional(),
    jenisHitung: z.string().optional(),
    fgFasilitas: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'Fasilitas wajib dipilih',
      }),
    fgSkb: z.boolean().optional(),
    skb: z.string().optional(),
    jenisPerhitungan: z.string().optional(),
    penghasilanKotorSebelumnya: z.string().optional(),
    phBruto: z.string().min(1, 'Jumlah Penghasilan Bruto wajib diisi'),
    tarif: z.string().min(1, 'Tarif wajib diisi'),
    pph21: z.string().min(1, 'PPh 21 wajib diisi'),
    fgPerhitungan: z.string().min(1, 'Gross/Gross Up wajib diisi'),
    ptkp: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'PTKP wajib dipilih',
      }),
    email: z.string().optional(),
    namaDokumenReferensi: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .optional(),
    nomorDokumenReferensi: z.string().optional(),
    idTku: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'NITKU Pemotong wajib diisi',
      }),
    tglPemotongan: z.string().min(1, 'Tanggal Pemotongan wajib diisi'),
    kap: z.string().optional(),
    kjs: z.string().optional(),
    id: z.number().optional(),
    noDokLainnya: z.string().optional(),
    internal_id: z.string().optional(),
  })
  .refine(
    (data) => {
      const bulan = dayjs(data.masaPajak).get('month') + 1;
      if (bulan === 12) {
        return false;
      }
      return true;
    },
    {
      message: 'Masa Pajak tidak boleh 12',
      path: ['masaPajak'],
    }
  )
  .refine(
    (data) => {
      if (data.fgSkb && !data.skb) {
        return false;
      }
      return true;
    },
    {
      message: 'SKB wajib diisi',
      path: ['skb'],
    }
  )
  .refine(
    (data: any) => {
      if (data.jenisHitung === PERHITUNGAN_BUPOT21.HARIAN_TER) {
        return parseInt(data.phBruto || 0, 10) < 2_500_000;
      }

      return parseInt(data.phBruto || '0', 10) >= 0;
    },
    {
      message: 'Jumlah Penghasilan Bruto tidak boleh minus',
      path: ['phBruto'],
    }
  )
  .refine((data: any) => parseInt(data.tarif || '0', 10) <= 100, {
    message: 'Tarif tidak boleh lebih dari 100',
    path: ['tarif'],
  })
  .refine(
    (data) => {
      switch (data.kdObjPjk.value) {
        case KODE_OBJEK_PAJAK.BULANAN_01:
        case KODE_OBJEK_PAJAK.BULANAN_02:
        case '21-100-32':
          return !!data.ptkp;
        default:
          return true;
      }
    },
    {
      message: 'PTKP wajib diisi',
      path: ['ptkp'],
    }
  );

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

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

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

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

  const kodeObjekPajak = useKodeObjekPajak('kop_21');

  const kodeObjekPajakOption = useMemo(() => {
    if (!kodeObjekPajak.kodeObjekPajak) return [];

    const KOP = kodeObjekPajak.kodeObjekPajak.map((val: any) => ({
      value: val.kode,
      label: `${val.kode} : ${val.nama}`,
      ...val,
    }));

    return KOP;
  }, [kodeObjekPajak.kodeObjekPajak]);

  const fgFasilitasOptions = useMemo(
    () =>
      Object.entries(FG_FASILITAS).map(([_, value]) => ({
        label: FG_FASILITAS_TEXT[value],
        value,
      })),
    []
  );

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

  const JnsDokRefOptions = Object.entries(BUPOT_REFERENSI).map(([key, value]) => ({
    value,
    label: BUPOT_REFERENSI_TEXT[value],
  }));

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

  type BpuFormData = z.infer<typeof bupotFinalSchema>;

  const defaultValues = {
    tglPemotongan: dayjs().format('YYYY-MM-DD'),
    tahunPajak: dayjs().format('YYYY'),
    masaPajak: dayjs().format('MM'),
    npwp: '',
    nitku: '',
    namaDipotong: '',
    kdObjPjk: {
      value: '',
      label: '',
    },
    pasalPPh: '',
    fgFasilitas: {
      value: FG_FASILITAS_PPH_21.TANPA_FASILITAS,
      label: FG_FASILITAS_PPH_21_TEXT[FG_FASILITAS_PPH_21.TANPA_FASILITAS],
    },
    phBruto: '',
    dppPersen: '100',
    tarif: '',
    pph21: '',
    fgPerhitungan: '0', // 0 = Gross, 1 = Gross Up
    ptkp: {
      value: '',
      label: '',
    },
    idTku: {
      value: '',
      label: '',
    },
    jenisWp: '',
    namaDokumenReferensi: {
      value: '',
      label: '',
    },
    nomorDokumenReferensi: '',
  };

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

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

  useEffect(() => {
    if ((isEdit || isPengganti) && existingBulanan.data.length !== 0 && kodeObjekPajakOption) {
      const dataResDetail = existingBulanan.data[0];

      const kdObjPjk = kodeObjekPajakOption.filter(
        (val: any) => val.value === dataResDetail.kodeObjekPajak
      )[0];

      const normalized = {
        ...dataResDetail,
        idBupot: '',
        noBupot: '',
        revNo: 0,
        tglPemotongan: dataResDetail.tglpemotongan,
        tahunPajak: dataResDetail.tahunPajak,
        masaPajak: dataResDetail.masaPajak,
        nitku: dataResDetail.nik,
        namaDipotong: dataResDetail.nama,
        alamatDipotong: dataResDetail.alamat,
        email: dataResDetail.email || '',
        kdObjPjk,
        jenisHitung: kdObjPjk?.jenisHitung,
        dppPersen: kdObjPjk?.dpp,
        pasalPPh: kdObjPjk?.pasal,
        statusPph: kdObjPjk?.statuspph,
        kap: kdObjPjk?.kap,
        kjs: kdObjPjk?.kjs,
        fgFasilitas: fgFasilitasOptions.filter(
          (val) => val.value === dataResDetail.sertifikatInsentifDipotong
        )[0],
        noDokLainnya: dataResDetail.nomorSertifikatInsentif,
        ptkp: ptkpOptions.filter((val) => val.value === `${dataResDetail.statusPPh}`)[0],
        phBruto: dataResDetail.penghasilanKotor,
        tunjanganPPh: dataResDetail.tunjanganPPh || 0,
        pph21: dataResDetail.pphDipotong,
        namaDokumenReferensi: JnsDokRefOptions.filter(
          (val) => val.value === dataResDetail.dokumen_referensi[0].dokReferensi
        )[0] || { value: '', label: '' },
        idTku: MockNitku.filter((val) => val.value === dataResDetail.idTku)[0],
      };

      console.log('🚀 ~ FinalTidakFinalRekamView ~ normalized:', normalized);

      if (isPengganti) {
        normalized['idBupot'] = dataResDetail.idBupot || '';
        normalized['noBupot'] = dataResDetail.noBupot || '';
        normalized['revNo'] = parseInt(`${dataResDetail.revNo}`, 10) || 0;
      }

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

  const handleDraft = async (data: BpuFormData) => {
    // Transform data sesuai dengan struktur yang dibutuhkan
    const transformedData = {
      ...data,
      id: isEdit || isPengganti ? data.id : undefined,
      statusPtkp: data.ptkp?.value || '',
      kdObjPjk: data.kdObjPjk.value,
      namaDokumenReferensi: data.namaDokumenReferensi?.value || '',
      pphDipotong: data.pph21,
      fgFasilitas: data.fgFasilitas.value,
      fgGrossUp: parseInt(data.fgPerhitungan || '1', 10),
      idTku: data.idTku.value,
      isPengganti,
    };

    const response = await saveBupotFnlTdkFnl(transformedData);

    return response;
  };

  const handleUploud = async (data: BpuFormData) => {
    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.bupotFinal);
    }
  };

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

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

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

  return (
    <>
      <DashboardContent>
        <CustomBreadcrumbs
          heading="Add Bupot PPh Pasal 21 Final / Tidak Final"
          links={[
            { name: 'Dashboard', href: paths.dashboard.root },
            {
              name: 'e-Bupot PPh Pasal 21 Final / Tidak Final',
              href: paths.pph21.bupotFinal,
            },
            { name: 'Add Bupot PPh Pasal 21 Final / Tidak Final' },
          ]}
        />

        <HeadingRekam label="Rekam Bupot PPh Pasal 21 Final/Tidak Final" />

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

                  <Suspense fallback={<FormSkeleton />}>
                    <PerhitunganPPhPasal21
                      kodeObjectPajak={kodeObjekPajakOption}
                      fgFasilitasOptions={fgFasilitasOptions}
                    />
                  </Suspense>

                  <JumlahPerhitunganForm ptkpOptions={ptkpOptions} />

                  <DokumenReferensi JnsDokRefOptions={JnsDokRefOptions} />

                  <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="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)()}
        />
      )}
    </>
  );
};
