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 { Suspense, useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
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 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 Identitas from '../components/rekam/Identitas';
import JumlahPerhitunganForm from '../components/rekam/JumlahPerhitunganForm';
import PanduanDnRekam from '../components/rekam/PanduanDnRekam';
import PerhitunganPPhPasal21 from '../components/rekam/PerhitunganPPhPasal21';
import {
  FG_FASILITAS_PPH_21,
  FG_FASILITAS_PPH_21_TEXT,
  KODE_OBJEK_PAJAK,
  KODE_OBJEK_PAJAK_TEXT,
} from '../constant';
import useSaveBulanan from '../hooks/useSaveBulanan';
import DialogPenandatangan from '../components/DialogPenandatangan';
import useUploadBulanan from '../hooks/useUploadeBulanan';
import { useNavigate, useParams } from 'react-router';
import { enqueueSnackbar } from 'notistack';
import useGetBulanan from '../hooks/useGetBulanan';

const bulananSchema = z
  .object({
    tahunPajak: z.string().min(1, 'Tahun Pajak wajib diisi'),
    masaPajak: z.string().min(1, 'Masa Pajak wajib diisi'),
    feature: z.string().optional(),
    idDipotong: z.string().optional(),
    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.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 { mutate: 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 { data: existingBulanan, isLoading: isLoadingBulanan } = useGetBulanan({
    params: {
      page: 1,
      limit: 1,
      id,
    },
    enabled: !!id,
  });

  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('YYYY-MM'),
    npwp: '',
    nitku: '',
    namaDipotong: '',
    fgKaryawanAsing: false,
    kodeNegara: '',
    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,
  });

  useEffect(() => {
    if ((isEdit || isPengganti) && existingBulanan && !isLoadingBulanan) {
      const normalized = {
        ...existingBulanan,
      };

      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,
      msPajak: data.masaPajak,
      thnPajak: data.tahunPajak,
      passportNo: data.passport || '',
      countryCode: data.kodeNegara || 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 || [],
    };

    await saveBulanan(transformedData);
  };

  const handleUploud = async (data: BpuFormData) => {
    try {
      const response = await handleDraft(data);
      uploadBulanan({
        id: response?.id ?? '',
      });
      enqueueSnackbar('Berhasil Menyimpan Data', { variant: 'success' });
    } catch (error: any) {
      enqueueSnackbar(error.message, { variant: 'error' });
    } finally {
      navigate('/pph21/bulanan');
    }
  };

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

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

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

  const MockNitku = [
    {
      nama: '1091031210912281000000',
    },
    {
      nama: '1091031210912281000001',
    },
  ];

  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 />

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

                  <JumlahPerhitunganForm />

                  <Grid size={{ md: 12 }}>
                    <Field.Autocomplete
                      name="idTku"
                      label="NITKU Pemotong"
                      options={MockNitku.map((a) => ({ value: a.nama, label: a.nama }))}
                    />
                  </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)()}
        />
      )}
    </>
  );
};
