import React, { useEffect, useMemo, useRef, useState } from 'react';
import { Controller, useFormContext, useWatch } from 'react-hook-form';
import dayjs from 'dayjs';

import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import Divider from '@mui/material/Divider';
import MenuItem from '@mui/material/MenuItem';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import FormControlLabel from '@mui/material/FormControlLabel';

import { Field } from 'src/components/hook-form';
import { jenisTransaksiOptions } from '../../constant';
import { useParams } from 'react-router';
import useGetIdTambahan from '../../hooks/useGetIdTambahan';
import useGetKeteranganTambahan from '../../hooks/useGetKeteranganTambahan';
import type { TKeteranganTambahan } from '../../types/types';
import Typography from '@mui/material/Typography';
import { RHFNumeric } from 'src/components/hook-form/rhf-numeric';
import CircularProgress from '@mui/material/CircularProgress';
import { CheckCircleRounded } from '@mui/icons-material';

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

interface DokumenTransaksiProps {
  fakturData?: any;
  isLoading?: boolean;
}

const DokumenTransaksi: React.FC<DokumenTransaksiProps> = ({ fakturData, isLoading }) => {
  const maxKeterangan = 5;
  const [jumlahKeterangan, setJumlahKeterangan] = useState(0);
  const [optionsKeterangan, setOptionsKeterangan] = useState<TKeteranganTambahan[]>([]);

  const { type } = useParams<{ id?: string; type?: 'ubah' | 'pengganti' | 'new' }>();
  const { control, setValue, getValues, watch, formState } = useFormContext<any>();

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

  const fgUangMuka = useWatch({ control, name: 'fgUangMuka' }) ?? PAYMENT_SINGLE_PAYMENT;
  const detailTransaksi = useWatch({ control, name: 'detailTransaksi' }) ?? 'TD.00301';
  const jenisFaktur = useWatch({ control, name: 'jenisFaktur' }) ?? '0';

  const penggantiOptions = isPengganti
    ? [{ label: '1 : Faktur Pajak Pengganti', id: '1' }]
    : [{ label: '0 : Faktur Pajak', id: '0' }];

  // guard to prevent re-autofill
  const isAutofillDoneRef = useRef(false);

  const isFieldDirty = (key: string) => {
    try {
      return Boolean(formState?.dirtyFields?.[key]);
    } catch {
      return false;
    }
  };

  const handleTambah = () => setJumlahKeterangan((p) => Math.min(p + 1, maxKeterangan));

  const handleHapus = () => {
    if (jumlahKeterangan <= 0) return;
    const idx = jumlahKeterangan;
    setValue(`keterangan${idx}`, '', {
      shouldDirty: true,
      shouldValidate: true,
    });
    setJumlahKeterangan((p) => Math.max(p - 1, 0));
  };

  useEffect(() => {
    setValue('fgPengganti', isPengganti ? '1' : '0', { shouldDirty: false, shouldValidate: false });
  }, [isPengganti, setValue]);

  /** ============================================
   * AUTO-FILL FAKTUR DATA (TAPI GAK TIMPA EDIT USER)
   * - includes nomorFaktur & masaTahunPajak
   * - uses setValue per-field so it doesn't clobber whole form
   ============================================ */
  useEffect(() => {
    // only run when we have data and we haven't autofilled this specific load
    if (!fakturData || isAutofillDoneRef.current) return;

    console.log('Autofill fakturData:', fakturData);

    const kArr = [
      fakturData.keterangan1 ?? '',
      fakturData.keterangan2 ?? '',
      fakturData.keterangan3 ?? '',
      fakturData.keterangan4 ?? '',
      fakturData.keterangan5 ?? '',
    ];

    const masaTahun =
      fakturData.tahunpajak !== undefined && fakturData.masapajak !== undefined
        ? `${fakturData.tahunpajak}-${String(fakturData.masapajak).padStart(2, '0')}`
        : '';

    const isPenggantiMode =
      fakturData.fgpengganti !== undefined ? fakturData.fgpengganti == 1 : isPengganti;

    const patch: Record<string, any> = {
      detailTransaksi: fakturData.detailtransaksi ?? 'TD.00301',
      refDoc: fakturData.refdoc ?? '',
      idKeteranganTambahan: fakturData.idketerangantambahan ?? '',
      referensi: fakturData.referensi ?? '',
      tanggalFaktur: fakturData.tanggalfaktur ? dayjs(fakturData.tanggalfaktur).format() : '',
      // fgPengganti:
      //   typeof fakturData.fgpengganti !== 'undefined' ? String(fakturData.fgpengganti) : '',
      fgPengganti:
        fakturData.fgpengganti !== undefined
          ? String(fakturData.fgpengganti)
          : isPengganti
            ? '1'
            : '0',
      fgUangMuka:
        typeof fakturData.fguangmuka !== 'undefined'
          ? fakturData.fgpelunasan
            ? PAYMENT_PELUNASAN
            : fakturData.fguangmuka
              ? PAYMENT_UANG_MUKA
              : PAYMENT_SINGLE_PAYMENT
          : PAYMENT_SINGLE_PAYMENT,
      nomorFaktur: fakturData.nomorfaktur ?? '',
      nomorFakturDiganti: fakturData.nomorfakturdiganti ?? '',
      masaTahunPajak: masaTahun,
    };

    if (isPenggantiMode) {
      patch.nomorFakturDiganti = fakturData.nomorfaktur ?? '';
      patch.nomorFaktur = '';
    }

    kArr.forEach((v, i) => {
      patch[`keterangan${i + 1}`] = v ?? '';
    });

    const current = getValues();

    Object.keys(patch).forEach((key) => {
      // respect user edits
      if (isFieldDirty(key)) return;

      const oldVal = typeof current?.[key] === 'undefined' ? '' : current?.[key];
      const newVal = typeof patch[key] === 'undefined' ? '' : patch[key];

      if (String(oldVal) !== String(newVal)) {
        // set without marking as user's edit
        setValue(key, newVal, { shouldDirty: false, shouldValidate: false });
      }
    });

    const nonEmpty = kArr.filter((x) => x && String(x).trim() !== '').length;
    setJumlahKeterangan((prev) => Math.max(prev, nonEmpty));

    isAutofillDoneRef.current = true;

    if (!getValues('fgPengganti')) {
      setValue('fgPengganti', isPengganti ? '1' : '0', { shouldDirty: false });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [fakturData, getValues, setValue, formState]);

  useEffect(() => {
    if (!isPengganti) return;
    if (!fakturData) return;

    // isi nomor faktur diganti
    setValue('nomorFakturDiganti', fakturData.nomorfaktur ?? '', {
      shouldDirty: false,
      shouldValidate: false,
    });

    // kosongkan nomor faktur baru
    setValue('nomorFaktur', '', {
      shouldDirty: false,
      shouldValidate: false,
    });
  }, [isPengganti, fakturData, setValue]);

  /** UPDATE JUMLAH KETERANGAN DINAMIS SAAT USER KETIK */
  useEffect(() => {
    const sub = watch((values) => {
      const count = [
        values.keterangan1,
        values.keterangan2,
        values.keterangan3,
        values.keterangan4,
        values.keterangan5,
      ].filter((k) => k && String(k).trim() !== '').length;

      setJumlahKeterangan((prev) => (count > prev ? Math.min(count, maxKeterangan) : prev));
    });

    return () => sub.unsubscribe();
  }, [watch]);

  /** jika fakturData di-clear, allow autofill next time */
  useEffect(() => {
    if (!fakturData) {
      isAutofillDoneRef.current = false;
    }
  }, [fakturData]);

  /** OTOMATIS KOSONGKAN NOMOR FAKTUR SAAT MODE SINGLE PAYMENT (only when no fakturData) */
  useEffect(() => {
    if (!fakturData && fgUangMuka === PAYMENT_SINGLE_PAYMENT) {
      setValue('nomorFaktur', '', { shouldDirty: true });
    }
  }, [fgUangMuka, fakturData, setValue]);

  const now = useMemo(() => new Date(), []);
  const startOfMonth = dayjs(new Date(now.getFullYear(), now.getMonth() - 1, 1));

  /** API HOOKS */
  const { mutate: getKeteranganTambahan } = useGetKeteranganTambahan({
    onSuccess: (res: any) => {
      setOptionsKeterangan(res.data ?? []);

      const current = getValues('idKeteranganTambahan');
      if (!current && res.data?.length === 1) {
        // pastikan string
        console.log('current idKeteranganTambahan', getValues('idKeteranganTambahan'));
        setValue('idKeteranganTambahan', String(res.data[0].kode ?? ''), {
          shouldDirty: false,
          shouldValidate: false,
        });
        console.log('current idKeteranganTambahan', getValues('idKeteranganTambahan'));
      }
    },
  });

  const { mutate: getIdTambahan } = useGetIdTambahan({
    onSuccess: (res: any) => {
      const current = getValues('idKeteranganTambahan');
      if (!current && res?.kode) {
        setValue('idKeteranganTambahan', String(res.kode), {
          shouldDirty: false,
          shouldValidate: false,
        });
      }
    },
  });

  const fetchedForRef = useRef<string | null>(null);

  useEffect(() => {
    const shouldFetch = detailTransaksi === 'TD.00307' || detailTransaksi === 'TD.00308';

    if (shouldFetch) {
      const params = { kode_awal: detailTransaksi };

      // >>> hanya cegah pemanggilan API duplikat untuk kode yang sama
      if (fetchedForRef.current !== detailTransaksi) {
        fetchedForRef.current = detailTransaksi;

        getKeteranganTambahan(params);
        getIdTambahan(params);
      }
    } else {
      // bagian 'else' tetap berjalan normal (tidak di-block)
      setOptionsKeterangan([]);
      if (!isFieldDirty('refDoc')) setValue('refDoc', '', { shouldDirty: false });
      if (!isFieldDirty('idKeteranganTambahan'))
        setValue('idKeteranganTambahan', '', { shouldDirty: false });

      // reset guard agar next time user pilih kode yang sama -> boleh fetch lagi
      fetchedForRef.current = null;
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [detailTransaksi]);

  /** DEFAULT VALUE SAAT FORM BARU */
  useEffect(() => {
    if (!fakturData) {
      if (!getValues('tanggalFaktur')) {
        setValue('tanggalFaktur', dayjs(now).format(), { shouldDirty: false });
      }

      if (!getValues('masaTahunPajak')) {
        setValue(
          'masaTahunPajak',
          `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`,
          { shouldDirty: false }
        );
      }

      if (!getValues('detailTransaksi')) {
        setValue('detailTransaksi', 'TD.00301', { shouldDirty: false });
      }

      if (!getValues('jenisFaktur')) {
        setValue('jenisFaktur', '0', { shouldDirty: false });
      }

      if (!getValues('fgUangMuka')) {
        setValue('fgUangMuka', PAYMENT_SINGLE_PAYMENT, {
          shouldDirty: false,
        });
      }
    }
  }, [now, fakturData, getValues, setValue]);

  useEffect(() => {
    if (jenisFaktur === '0') {
      setValue(
        'masaTahunPajak',
        `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`,
        { shouldDirty: false }
      );
    }
  }, [jenisFaktur, now, setValue]);

  const keterangantambahan = useWatch({
    control,
    name: 'idKeteranganTambahan',
  });

  const selectedKeterangan = optionsKeterangan.find(
    (o) => String(o.kode) === String(keterangantambahan)
  );

  return (
    <Grid container spacing={2} sx={{ mb: 3 }}>
      <Grid size={{ xs: 12 }} sx={{ mt: 3 }}>
        <Divider sx={{ fontWeight: 'bold', fontSize: '1.2rem', mb: 2 }} textAlign="center">
          Dokumen Transaksi
        </Divider>
      </Grid>

      {/* Payment Type */}
      <Grid sx={{ mt: 3 }} size={{ md: 6 }}>
        <Controller
          name="fgUangMuka"
          control={control}
          render={({ field }) => (
            <RadioGroup row {...field}>
              <FormControlLabel
                value={PAYMENT_UANG_MUKA}
                control={<Radio disabled={isPengganti} />}
                label="Uang Muka"
              />
              <FormControlLabel
                value={PAYMENT_PELUNASAN}
                control={<Radio disabled={isPengganti} />}
                label="Pelunasan"
              />
              <FormControlLabel
                value={PAYMENT_SINGLE_PAYMENT}
                control={<Radio disabled={isPengganti} />}
                label="Single Payment"
              />
            </RadioGroup>
          )}
        />
      </Grid>

      {/* Kode Transaksi */}
      <Grid size={{ md: 6 }}>
        <Field.Select
          name="detailTransaksi"
          helperText=""
          label="Kode Transaksi"
          disabled={Boolean(fakturData) && !isPengganti}
        >
          {jenisTransaksiOptions.map((opt) => (
            <MenuItem key={opt.id} value={opt.id}>
              {opt.label}
            </MenuItem>
          ))}
        </Field.Select>
      </Grid>

      {(detailTransaksi === 'TD.00307' || detailTransaksi === 'TD.00308') && (
        <Grid size={{ md: 6 }}>
          <Field.Select name="idKeteranganTambahan" label="Keterangan Tambahan">
            <MenuItem disabled value="">
              <em>Pilih keterangan</em>
            </MenuItem>

            {optionsKeterangan.map((opt) => (
              <MenuItem key={opt.kode} value={String(opt.kode)}>
                {opt.deskripsi}
              </MenuItem>
            ))}
          </Field.Select>
        </Grid>
      )}

      {(detailTransaksi === 'TD.00307' || detailTransaksi === 'TD.00308') && (
        <Grid size={{ md: 6 }}>
          <Field.Text
            name="refDoc"
            label="Nomor Dokumen Pendukung"
            disabled={Boolean(fakturData) && !isPengganti}
          />
        </Grid>
      )}

      <Grid size={{ md: 6 }}>
        {/* <Field.Select
          name="fgPengganti"
          helperText=""
          label="Jenis Faktur"
          disabled={Boolean(fakturData)}
        >
          {jenisFakturOptions.map((opt) => (
            <MenuItem key={opt.id} value={opt.id}>
              {opt.label}
            </MenuItem>
          ))}
        </Field.Select> */}
        <Field.Select
          name="fgPengganti"
          helperText=""
          label="Jenis Faktur"
          disabled={Boolean(fakturData) || isPengganti}
        >
          {penggantiOptions.map((opt) => (
            <MenuItem key={opt.id} value={opt.id}>
              {opt.label}
            </MenuItem>
          ))}
        </Field.Select>
      </Grid>

      {/* CHANGED: jika mode PENGGANTI -> tampilkan field nomorFakturDiganti (disabled) */}
      {isPengganti || getValues('fgPengganti') === '1' ? (
        <Grid size={{ md: 6 }}>
          {/* pastikan value di-set dari fakturData.nomorfaktur (lihat useEffect di bawah) */}
          <Field.Text
            name="nomorFakturDiganti"
            label="Nomor Seri Faktur Diganti"
            disabled
            helperText=""
          />
        </Grid>
      ) : (
        <Grid size={{ md: 6 }}>
          <RHFNumeric
            name="nomorFaktur"
            label="Nomor Faktur"
            allowDecimalValue={false}
            allowNegativeValue={false}
            disableFormat
            onChange={(e: any) => {
              const value = e.target.value.replace(/\D/g, '').slice(0, 17);
              setValue('nomorFaktur', value, { shouldDirty: true });
            }}
            inputProps={{ inputMode: 'numeric', pattern: '[0-9]*' }}
            InputProps={{
              endAdornment: (
                <>
                  {isLoading && <CircularProgress size={20} sx={{ mr: 1 }} />}
                  {!isLoading && fakturData && <CheckCircleRounded color="success" />}
                </>
              ),
            }}
            disabled={fgUangMuka === PAYMENT_SINGLE_PAYMENT}
            sx={{
              '& .MuiInputBase-root.Mui-disabled': {
                backgroundColor: '#f6f6f6',
              },
            }}
          />
        </Grid>
      )}

      {/* <Grid size={{ md: 6 }}>
        <RHFNumeric
          name="nomorFaktur"
          label="Nomor Faktur"
          allowDecimalValue={false}
          allowNegativeValue={false}
          disableFormat
          onChange={(e: any) => {
            const value = e.target.value.replace(/\D/g, '').slice(0, 17);
            setValue('nomorFaktur', value, { shouldDirty: true });
          }}
          inputProps={{ inputMode: 'numeric', pattern: '[0-9]*' }}
          InputProps={{
            endAdornment: (
              <>
                {isLoading && <CircularProgress size={20} sx={{ mr: 1 }} />}
                {!isLoading && fakturData && <CheckCircleRounded color="success" />}
              </>
            ),
          }}
          disabled={fgUangMuka === PAYMENT_SINGLE_PAYMENT}
          sx={{
            '& .MuiInputBase-root.Mui-disabled': {
              backgroundColor: '#f6f6f6',
            },
          }}
        />
      </Grid> */}

      <Grid size={{ md: 6 }}>
        <Field.DatePicker
          name="tanggalFaktur"
          label="Tanggal Faktur"
          slotProps={{ textField: { helperText: '' } }}
          minDate={startOfMonth}
          maxDate={dayjs()}
        />
      </Grid>

      <Grid size={{ md: 6 }}>
        <Field.Text
          name="masaTahunPajak"
          label="Masa/Tahun Pajak"
          type="month"
          disabled={jenisFaktur === '0'}
          sx={{ '& .MuiInputBase-root.Mui-disabled': { backgroundColor: '#f6f6f6' } }}
        />
      </Grid>

      <Field.Text name="referensi" label="Referensi Faktur (Optional)" />

      <Grid size={{ xs: 12 }}>
        <Box sx={{ display: 'flex', gap: 2, mb: 3 }}>
          <Box
            sx={{
              borderRadius: '18px',
              border: jumlahKeterangan >= maxKeterangan ? '1px solid #eee' : '1px solid #2e7d3280',
              color: jumlahKeterangan >= maxKeterangan ? '#eee' : '#2e7d3280',
              p: '0px 10px',
            }}
          >
            <Button disabled={jumlahKeterangan >= maxKeterangan} onClick={handleTambah}>
              Tambah Keterangan
            </Button>
          </Box>

          <Box
            sx={{
              borderRadius: '18px',
              border: jumlahKeterangan === 0 ? '1px solid #eee' : '1px solid #f44336',
              color: jumlahKeterangan === 0 ? '#eee' : '#f44336',
              p: '0px 10px',
            }}
          >
            <Button disabled={jumlahKeterangan === 0} onClick={handleHapus}>
              Hapus Keterangan
            </Button>
          </Box>
        </Box>

        <Box sx={{ mb: 3 }}>
          {Array.from({ length: jumlahKeterangan }).map((_, i) => (
            <Grid size={{ xs: 12 }} key={`keterangan${i + 1}`} sx={{ mb: 2 }}>
              <Field.Text name={`keterangan${i + 1}`} label={`Keterangan Tambahan ${i + 1}`} />
            </Grid>
          ))}
        </Box>

        {selectedKeterangan && (
          <Typography sx={{ mt: 2 }}>* {selectedKeterangan.deskripsi}</Typography>
        )}
      </Grid>
    </Grid>
  );
};

export default DokumenTransaksi;
