import React, { useEffect, useRef } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import Grid from '@mui/material/Grid';
import Divider from '@mui/material/Divider';
import Typography from '@mui/material/Typography';
import { RHFNumeric } from 'src/components/hook-form/rhf-numeric';

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

// pembulatan ke integer (Math.round) dengan safety EPSILON
const roundInt = (v: number) => Math.round(v + Number.EPSILON);

type Props = {
  fakturData?: any | null; // optional, dari parent
  sisapelunasan?: string | number | null; // alternatif jika mau kirim hanya nilai
};

const UangMuka: React.FC<Props> = ({ fakturData = null, sisapelunasan = null }) => {
  const {
    control,
    setValue,
    setError,
    clearErrors,
    formState: { errors },
  } = useFormContext();

  // watchers
  const fgUangMuka = useWatch({ control, name: 'fgUangMuka' }) ?? PAYMENT_SINGLE_PAYMENT;
  const jumlahUangMukaRaw = Number(useWatch({ control, name: 'jumlahUangMuka' }) ?? 0);

  // totals come from form and we watch them
  const totalDpp = Number(useWatch({ control, name: 'totalDpp' }) ?? 0);
  const totalDppLain = Number(useWatch({ control, name: 'totalDppLain' }) ?? 0);
  const totalPpnbm = Number(useWatch({ control, name: 'totalPpnbm' }) ?? 0);

  // <-- CHANGED: watch uangMukaDpp so validation reacts when user types
  const uangMukaDppWatch = Number(useWatch({ control, name: 'uangMukaDpp' }) ?? 0); // <<< CHANGED

  // also watch the other uang muka fields so we can validate them in pelunasan mode
  const uangMukaDppLainWatch = Number(useWatch({ control, name: 'uangMukaDppLain' }) ?? 0);
  const uangMukaPpnWatch = Number(useWatch({ control, name: 'uangMukaPpn' }) ?? 0);
  const uangMukaPpnbmWatch = Number(useWatch({ control, name: 'uangMukaPpnbm' }) ?? 0);

  // prev refs to avoid unnecessary setValue loops
  const prevValuesRef = useRef({
    jumlahUangMuka: undefined as number | undefined,
    uangMukaDpp: undefined as number | undefined,
    uangMukaDppLain: undefined as number | undefined,
    uangMukaPpn: undefined as number | undefined,
    uangMukaPpnbm: undefined as number | undefined,
  });

  // --- NEW: parse sisapelunasan from props/fakturData as fallback ---
  // but prefer value from form (useWatch for sisaPelunasan) later
  const rawSisapelunasanFromProp =
    sisapelunasan ??
    (fakturData &&
      (fakturData.sisapelunasan ?? fakturData.sisaPelunasan ?? fakturData.sisa_pelunasan)) ??
    null; // <<< CHANGED (renamed variable to clarify)

  // safer parser: remove non-digit characters (handles "27.458.333", "27458333", "Rp 27.458.333")
  const parseRupiahToNumber = (v: any) => {
    if (v === null || v === undefined) return null;
    const str = String(v).trim();
    if (str === '') return null;
    // remove everything except digits
    const cleaned = str.replace(/[^\d]/g, '');
    if (cleaned === '') return null;
    return Number(cleaned);
  }; // <<< CHANGED: new helper

  const sisapelunasanNumFromProp = parseRupiahToNumber(rawSisapelunasanFromProp); // <<< CHANGED

  // <<< ADDED: persist sisaPelunasan into RHF so Zod and form validation can use it
  useEffect(() => {
    if (sisapelunasanNumFromProp != null) {
      // set into form (number) — shouldDirty: false so it doesn't mark as user-edited
      setValue('sisaPelunasan', sisapelunasanNumFromProp, { shouldDirty: false }); // <<< ADDED
    }
  }, [sisapelunasanNumFromProp, setValue]); // <<< ADDED

  const formatRupiah = (v: number | null | undefined) =>
    v === null || v === undefined ? '' : new Intl.NumberFormat('id-ID').format(Math.round(v));

  // <-- CHANGED: prefer sisaPelunasan from form if set; fallback to prop parsed value
  const sisaPelunasanWatch = Number(
    useWatch({ control, name: 'sisaPelunasan' }) ?? sisapelunasanNumFromProp ?? 0
  ); // <<< CHANGED

  // --- NEW WATCHERS for various sisa values (try form names, fallback to fakturData props) ---
  // const sisaDppWatchFromForm = useWatch({ control, name: 'sisadpp' });
  // const sisaDpp = Number(sisaDppWatchFromForm ?? fakturData?.sisadpp ?? fakturData?.sisadpp ?? 0);

  const sisaDppLainWatchFromForm = useWatch({ control, name: 'sisadpplain' });
  const sisaDppLain = Number(
    sisaDppLainWatchFromForm ?? fakturData?.sisadpplain ?? fakturData?.sisadp_plain ?? 0
  );

  const sisaPpnWatchFromForm = useWatch({ control, name: 'sisappn' });
  const sisaPpn = Number(sisaPpnWatchFromForm ?? fakturData?.sisappn ?? 0);

  const totalPpnbmWatchFromForm = useWatch({ control, name: 'totalppnbm' });
  // try form -> fakturData -> fallback to totalPpnbm (total field)
  const totalPpnbmWatch = Number(
    totalPpnbmWatchFromForm ?? fakturData?.totalppnbm ?? totalPpnbm ?? 0
  );
  // --- end new watchers ---

  // reset when mode changes
  useEffect(() => {
    setValue('jumlahUangMuka', 0, { shouldDirty: false });
    setValue('uangMukaDpp', 0, { shouldDirty: false });
    setValue('uangMukaDppLain', 0, { shouldDirty: false });
    setValue('uangMukaPpn', 0, { shouldDirty: false });
    setValue('uangMukaPpnbm', 0, { shouldDirty: false });
    clearErrors(['jumlahUangMuka', 'uangMukaDpp']);
    // reset prev cache
    prevValuesRef.current = {
      jumlahUangMuka: undefined,
      uangMukaDpp: undefined,
      uangMukaDppLain: undefined,
      uangMukaPpn: undefined,
      uangMukaPpnbm: undefined,
    };
  }, [fgUangMuka, setValue, clearErrors]);

  // uang_muka mode: compute everything per formula and round to integer
  useEffect(() => {
    if (fgUangMuka !== PAYMENT_UANG_MUKA) return;

    const jRounded = roundInt(jumlahUangMukaRaw);

    // --- NEW RULE #1: minimal 1
    if (jRounded < 1) {
      setError('jumlahUangMuka', {
        type: 'manual',
        message: 'Jumlah Uang Muka minimal adalah 1.',
      });
      return; // stop lanjut validate lainnya
    }

    // --- NEW RULE #2: tidak boleh >= sisaPelunasan
    if (sisaPelunasanWatch > 0 && jRounded >= sisaPelunasanWatch) {
      setError('jumlahUangMuka', {
        type: 'manual',
        message: `Jumlah Uang Muka harus lebih kecil dari Sisa Pelunasan (${formatRupiah(
          sisaPelunasanWatch
        )}).`,
      });
    } else {
      clearErrors('jumlahUangMuka');
    }

    // lanjut perhitungan existing seperti sebelumnya
    const uangMukaDpp = jRounded;

    const uangMukaDppLainRaw = totalDpp > 0 ? (totalDppLain / totalDpp) * jRounded : 0;
    const uangMukaDppLain = roundInt(uangMukaDppLainRaw);

    const uangMukaPpnRaw = (uangMukaDppLainRaw * 12) / 100;
    const uangMukaPpn = roundInt(uangMukaPpnRaw);

    const uangMukaPpnbm = roundInt(totalPpnbm);

    const prev = prevValuesRef.current;

    if (prev.jumlahUangMuka !== jRounded) {
      setValue('jumlahUangMuka', jRounded, { shouldDirty: true });
      prev.jumlahUangMuka = jRounded;
    }

    if (prev.uangMukaDpp !== uangMukaDpp) {
      setValue('uangMukaDpp', uangMukaDpp, { shouldDirty: true });
      prev.uangMukaDpp = uangMukaDpp;
    }

    if (prev.uangMukaDppLain !== uangMukaDppLain) {
      setValue('uangMukaDppLain', uangMukaDppLain, { shouldDirty: true });
      prev.uangMukaDppLain = uangMukaDppLain;
    }

    if (prev.uangMukaPpn !== uangMukaPpn) {
      setValue('uangMukaPpn', uangMukaPpn, { shouldDirty: true });
      prev.uangMukaPpn = uangMukaPpn;
    }

    if (prev.uangMukaPpnbm !== uangMukaPpnbm) {
      setValue('uangMukaPpnbm', uangMukaPpnbm, { shouldDirty: true });
      prev.uangMukaPpnbm = uangMukaPpnbm;
    }
  }, [
    fgUangMuka,
    jumlahUangMukaRaw,
    totalDpp,
    totalDppLain,
    totalPpnbm,
    setValue,
    setError,
    clearErrors,
    sisaPelunasanWatch,
  ]);

  // === AUTO FILL SAAT EDIT MODE ===
  useEffect(() => {
    if (!fakturData) return; // create mode -> skip

    // Jika fakturData ada dan jumlahuangmuka valid → autofill
    if (fakturData.jumlahuangmuka != null) {
      const jm = Number(fakturData.jumlahuangmuka) || 0;

      setValue('jumlahUangMuka', jm, { shouldDirty: false });
      prevValuesRef.current.jumlahUangMuka = jm;
    }
  }, [fakturData, setValue]);

  // pelunasan mode: validate uangMukaDpp must equal sisaPelunasan
  useEffect(() => {
    if (fgUangMuka !== PAYMENT_PELUNASAN) return;

    // <-- CHANGED: use watched uangMukaDpp and watched sisaPelunasan
    const val = uangMukaDppWatch; // <<< CHANGED

    // if sisa not available yet, skip validation (avoid erroneous error)
    if (!sisaPelunasanWatch || sisaPelunasanWatch <= 0) {
      clearErrors('uangMukaDpp');
      return;
    }

    if (val !== sisaPelunasanWatch) {
      setError('uangMukaDpp', {
        type: 'manual',
        message: `Pelunasan DPP harus sama dengan Sisa Pelunasan (${formatRupiah(
          sisaPelunasanWatch
        )}).`,
      });
    } else {
      clearErrors('uangMukaDpp');
    }
  }, [fgUangMuka, uangMukaDppWatch, sisaPelunasanWatch, setError, clearErrors]); // <<< CHANGED

  // --- NEW: Auto-fill fields for pelunasan (so value equals wording)
  useEffect(() => {
    if (fgUangMuka !== PAYMENT_PELUNASAN) return;

    // set uangMukaDppLain from sisaDppLain
    setValue('uangMukaDppLain', sisaDppLain ?? 0, { shouldDirty: true });

    // set uangMukaPpn from sisaPpn
    setValue('uangMukaPpn', sisaPpn ?? 0, { shouldDirty: true });

    // set uangMukaPpnbm from totalPpnbmWatch
    setValue('uangMukaPpnbm', totalPpnbmWatch ?? 0, { shouldDirty: true });
  }, [fgUangMuka, sisaDppLain, sisaPpn, totalPpnbmWatch, setValue]);

  // --- NEW: Validate that the pelunasan fields equal their respective sisa values
  useEffect(() => {
    if (fgUangMuka !== PAYMENT_PELUNASAN) return;

    // uangMukaDppLain
    if (uangMukaDppLainWatch !== sisaDppLain) {
      setError('uangMukaDppLain', {
        type: 'manual',
        message: `Pelunasan DPP Lain harus sama dengan ${formatRupiah(sisaDppLain)}.`,
      });
    } else {
      clearErrors('uangMukaDppLain');
    }

    // uangMukaPpn
    if (uangMukaPpnWatch !== sisaPpn) {
      setError('uangMukaPpn', {
        type: 'manual',
        message: `Pelunasan PPN harus sama dengan ${formatRupiah(sisaPpn)}.`,
      });
    } else {
      clearErrors('uangMukaPpn');
    }

    // uangMukaPpnbm
    if (uangMukaPpnbmWatch !== totalPpnbmWatch) {
      setError('uangMukaPpnbm', {
        type: 'manual',
        message: `Pelunasan PPnBM harus sama dengan ${formatRupiah(totalPpnbmWatch)}.`,
      });
    } else {
      clearErrors('uangMukaPpnbm');
    }
  }, [
    fgUangMuka,
    uangMukaDppLainWatch,
    uangMukaPpnWatch,
    uangMukaPpnbmWatch,
    sisaDppLain,
    sisaPpn,
    totalPpnbmWatch,
    setError,
    clearErrors,
  ]);

  // hide component if not uang_muka or pelunasan
  if (!(fgUangMuka === PAYMENT_UANG_MUKA || fgUangMuka === PAYMENT_PELUNASAN)) {
    return null;
  }

  const fieldSize = fgUangMuka === PAYMENT_PELUNASAN ? { md: 3 } : { md: 2.5 };
  const fieldSizePpnbm = fgUangMuka === PAYMENT_PELUNASAN ? { md: 3 } : { md: 2 };
  const labelDpp = fgUangMuka === PAYMENT_PELUNASAN ? 'Pelunasan DPP (Rp)' : 'Uang Muka DPP (Rp)';

  // formatted sisapelunasan string (or empty) <-- prefer watched value for display too
  const sisapelunasanFormatted =
    sisaPelunasanWatch && sisaPelunasanWatch > 0 ? formatRupiah(sisaPelunasanWatch) : '';

  // helper to format sisa values for display
  const fmt = (v: number) => (v && v > 0 ? formatRupiah(v) : '');

  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">
          Uang Muka / Pelunasan
        </Divider>
      </Grid>

      {/* jumlahUangMuka hanya untuk uang_muka */}
      {fgUangMuka === PAYMENT_UANG_MUKA && (
        <Grid size={{ md: 2.5 }}>
          <RHFNumeric
            name="jumlahUangMuka"
            label="Jumlah Uang Muka (Rp)"
            allowDecimalValue
            decimalScale={2}
            helperText={(errors as any)?.jumlahUangMuka?.message}
          />
          {/* show sisapelunasan under jumlahUangMuka when mode = uang_muka */}
          {sisapelunasanFormatted ? (
            <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}>
              Sisa Pelunasan {sisapelunasanFormatted}
            </Typography>
          ) : null}
        </Grid>
      )}

      {/* uangMukaDpp */}
      <Grid size={fieldSize}>
        <RHFNumeric
          name="uangMukaDpp"
          label={labelDpp}
          allowDecimalValue
          decimalScale={0} // show integer (no decimals)
          readOnly={fgUangMuka === PAYMENT_UANG_MUKA}
          helperText={(errors as any)?.uangMukaDpp?.message}
        />
        {/* show sisapelunasan under uangMukaDpp when mode = pelunasan */}
        {fgUangMuka === PAYMENT_PELUNASAN && sisapelunasanFormatted ? (
          <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}>
            Sisa Pelunasan {sisapelunasanFormatted}
          </Typography>
        ) : null}
      </Grid>

      {/* uangMukaDppLain */}
      <Grid size={fieldSize}>
        <RHFNumeric
          name="uangMukaDppLain"
          label={
            fgUangMuka === PAYMENT_PELUNASAN ? 'Pelunasan DPP Lain (Rp)' : 'Uang Muka DPP Lain (Rp)'
          }
          allowDecimalValue
          decimalScale={0}
          readOnly={fgUangMuka === PAYMENT_UANG_MUKA}
        />
        {/* show wording + value under field when pelunasan */}
        {fgUangMuka === PAYMENT_PELUNASAN && fmt(sisaDppLain) ? (
          <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}>
            Sisa DPP Lain {fmt(sisaDppLain)}
          </Typography>
        ) : null}
      </Grid>

      {/* uangMukaPpn */}
      <Grid size={fieldSize}>
        <RHFNumeric
          name="uangMukaPpn"
          label={fgUangMuka === PAYMENT_PELUNASAN ? 'Pelunasan PPN (Rp)' : 'Uang Muka PPN (Rp)'}
          allowDecimalValue
          decimalScale={0}
          readOnly={fgUangMuka === PAYMENT_UANG_MUKA}
        />
        {/* show wording + value under field when pelunasan */}
        {fgUangMuka === PAYMENT_PELUNASAN && fmt(sisaPpn) ? (
          <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}>
            Sisa PPN {fmt(sisaPpn)}
          </Typography>
        ) : null}
      </Grid>

      {/* uangMukaPpnbm */}
      <Grid size={fieldSizePpnbm}>
        <RHFNumeric
          name="uangMukaPpnbm"
          label={fgUangMuka === PAYMENT_PELUNASAN ? 'Pelunasan PPnBM (Rp)' : 'Uang Muka PPnBM (Rp)'}
          allowDecimalValue
          decimalScale={0}
          readOnly={fgUangMuka === PAYMENT_UANG_MUKA}
        />
        {/* show wording + value under field when pelunasan */}
        {fgUangMuka === PAYMENT_PELUNASAN && fmt(totalPpnbmWatch) ? (
          <Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 1 }}>
            Total PPnBM {fmt(totalPpnbmWatch)}
          </Typography>
        ) : null}
      </Grid>
    </Grid>
  );
};

export default UangMuka;
