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,
  KODE_OBJEK_PAJAK,
  KODE_OBJEK_PAJAK_TEXT,
  MockNitku,
  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/ModalUploadBulanan';
import Identitas from '../components/rekam/Identitas';
import JumlahPerhitunganForm from '../components/rekam/JumlahPerhitunganForm';
import PanduanDnRekam from '../components/rekam/PanduanDnRekam';
import PerhitunganPPhPasal21 from '../components/rekam/PerhitunganPPhPasal21';
import useGetBulanan from '../hooks/useGetBulanan';
import useSaveBulanan from '../hooks/useSaveBulanan';
import useUploadBulanan from '../hooks/useUploadeBulanan';

const bulananSchema = 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'),
    posisiJabatan: z.string().min(1, 'Jabatan wajib diisi'),
    alamat: z.string().nullable().optional(),
    fgKaryawanAsing: z.boolean().optional(),
    kodeNegara: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .optional(),
    passport: z.string().optional(),
    kdObjPjk: z
      .object({
        label: z.string(),
        value: z.string(),
      })
      .refine((data: any) => data.value !== '', {
        message: 'Kode Objek Pajak wajib diisi',
      }),
    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(),
    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(),
    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',
      }),
    tglPemotongan: z.string().min(1, 'Tanggal Pemotongan wajib diisi'),
    kap: z.string().optional(),
    kjs: z.string().optional(),
    id: z.number().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.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.fgSkb && !data.skb) {
        return false;
      }
      return true;
    },
    {
      message: 'SKB wajib diisi',
      path: ['skb'],
    }
  )
  .refine((data: any) => 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 BulananRekamView = () => {
  const { id, type } = useParams<{ id?: string; type?: 'ubah' | 'pengganti' | 'new' }>();
  const navigate = useNavigate();

  const { mutateAsync: saveBulanan, isPending: isSaving } = useSaveBulanan({
    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 } = useGetBulanan({
    params: {
      page: 1,
      limit: 1,
      id,
    },
    enabled: !!id && (isEdit || isPengganti),
  });

  type BpuFormData = z.infer<typeof bulananSchema>;

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

  const defaultValues = {
    tglPemotongan: dayjs().format('YYYY-MM-DD'),
    tahunPajak: dayjs().format('YYYY'),
    masaPajak: dayjs().format('MM'),
    npwp: '',
    nitku: '',
    namaDipotong: '',
    fgKaryawanAsing: false,
    kodeNegara: {
      value: '',
      label: '',
    },
    passport: '',
    posisiJabatan: '',
    kdObjPjk: {
      value: '',
      label: '',
    },
    fgFasilitas: {
      value: FG_FASILITAS_PPH_21.TANPA_FASILITAS,
      label: FG_FASILITAS_PPH_21_TEXT[FG_FASILITAS_PPH_21.TANPA_FASILITAS],
    },
    skb: '',
    phBruto: '',
    tarif: '',
    pph21: '',
    fgPerhitungan: '0', // 0 = Gross, 1 = Gross Up
    ptkp: {
      value: '',
      label: '',
    },
    idTku: {
      value: '',
      label: '',
    },
    kap: '',
    kjs: '',
    jenisWp: '',
  };

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

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

  useEffect(() => {
    if ((isEdit || isPengganti) && existingBulanan.data.length !== 0) {
      const dataResDetail = existingBulanan.data[0];
      const normalized = {
        ...dataResDetail,
        tglPemotongan: dataResDetail.tglpemotongan,
        tahunPajak: dataResDetail.thnPajak,
        masaPajak: dataResDetail.masaPajak,
        npwp: dataResDetail.npwp16Dipotong,
        nitku: `${dataResDetail.npwp16Dipotong}000000`,
        alamatDipotong: dataResDetail.alamat,
        email: dataResDetail.email || '',
        fgKaryawanAsing: !!dataResDetail.countryCode,
        kodeNegara: kodeNegetaOptions.filter(
          (val) => val.value === dataResDetail.countryCode
        )[0] || {
          value: '',
          label: '',
        },
        passport: dataResDetail.passportNo || '',
        kdObjPjk: dataListKOP.filter((val) => val.value === dataResDetail.kdObjPjk)[0],
        fgFasilitas: fgFasilitasOptions.filter((val) => val.value === dataResDetail.fgFasilitas)[0],
        ptkp: ptkpOptions.filter(
          (val) => val.value === `${dataResDetail.statusPtkp}/${dataResDetail.jmlPtkp}`
        )[0],
        phBruto: dataResDetail.bruto,
        pph21: dataResDetail.pphDipotong,
        idTku: MockNitku.filter((val) => val.value === dataResDetail.nitkuPemotong)[0],
      };

      if (isPengganti) {
        normalized['idBupot'] = dataResDetail.idBupot || '';
        normalized['idBupot'] = dataResDetail.noBupot || '';
        normalized['revNo'] = dataResDetail.revNo || 0;
      }

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

  const handleDraft = async (data: BpuFormData) => {
    // Transform data sesuai dengan struktur yang dibutuhkan
    const transformedData = {
      ...data,
      id: isEdit || isPengganti ? data.id : undefined,
      passportNo: data.passport || '',
      countryCode: data.kodeNegara?.value || null,
      statusPtkp: data.ptkp?.value || '',
      kdObjPjk: data.kdObjPjk.value,
      kdJnsPjk: 'PPh Pasal 21', // Sesuaikan dengan konstanta Anda
      jmlBruto: data.phBruto,
      tarif: data.tarif,
      pphDipotong: data.pph21,
      fgFasilitas: data.fgFasilitas.value,
      noDokLainnya: data.skb || '',
      fgGrossUp: parseInt(data.fgPerhitungan || '1', 10),
      idTku: data.idTku.value,
      komponen: data.jumlahPenghasilan || [],
      isPengganti,
    };

    const response = await saveBulanan(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.bulanan);
    }
  };

  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.bulanan);
    } 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 Bulanan"
          links={[
            { name: 'Dashboard', href: paths.dashboard.root },
            {
              name: 'e-Bupot PPh Pasal 21 Bulanan',
              href: paths.pph21.bulanan,
            },
            { name: 'Add Bupot PPh Pasal 21 Bulanan' },
          ]}
        />

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

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

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

                  <JumlahPerhitunganForm ptkpOptions={ptkpOptions} />

                  <Grid size={{ md: 12 }}>
                    <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 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: '#143B88' }}
                    >
                      Save as Draft
                    </LoadingButton>
                    <LoadingButton
                      type="button"
                      disabled={!isCheckedAgreement}
                      onClick={methods.handleSubmit(handleClickUpload)}
                      loading={isSaving || isUpload}
                      variant="contained"
                      sx={{ background: '#143B88' }}
                    >
                      Save and Upload
                    </LoadingButton>
                  </Stack>
                </Suspense>
              </FormProvider>
            </form>
          </Grid>
          <Grid size={{ xs: isOpenPanduan ? 4 : 1 }}>
            <PanduanDnRekam handleOpen={handleOpenPanduan} isOpen={isOpenPanduan} />
          </Grid>
        </Grid>
      </DashboardContent>
      {isOpenDialogPenandatangan && (
        <DialogPenandatangan
          isOpenDialogUpload={isOpenDialogPenandatangan}
          setIsOpenDialogUpload={setIsOpenDialogPenandatangan}
          onConfirmUpload={() => methods.handleSubmit(handleUploud)()}
        />
      )}
    </>
  );
};
