import React, { useEffect, useMemo, useState } from 'react';
import { Stack, Button, Typography } from '@mui/material';
import { useQueryClient } from '@tanstack/react-query';
import { enqueueSnackbar } from 'notistack';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import type { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import minMax from 'dayjs/plugin/minMax';
import DialogUmum from 'src/shared/components/dialog/DialogUmum';
import DialogProgressBar from 'src/shared/components/dialog/DialogProgressBar';
import useDialogProgressBar from 'src/shared/hooks/useDialogProgressBar';
import type { GridRowSelectionModel } from '@mui/x-data-grid-premium';
import useCencelBulanan from '../hooks/useCencelBulanan';
import queryKey, { appRootKey, bulanan } from '../constant/queryKey';
import { createTableKey, useTablePagination } from '../../paginationStore';

dayjs.extend(minMax);

// Helper format tanggal ke format API (DDMMYYYY)
const formatDateDDMMYYYY = (d: Date) => {
  const dd = String(d.getDate()).padStart(2, '0');
  const mm = String(d.getMonth() + 1).padStart(2, '0');
  const yyyy = d.getFullYear();
  return `${dd}${mm}${yyyy}`;
};

interface ModalCancelDnProps {
  dataSelected?: any[];
  setSelectionModel?: React.Dispatch<React.SetStateAction<GridRowSelectionModel | undefined>>;
  tableApiRef?: React.MutableRefObject<any>;
  isOpenDialogCancel: boolean;
  setIsOpenDialogCancel: (v: boolean) => void;
  successMessage?: string;
}

const ModalCancelBulanan: React.FC<ModalCancelDnProps> = ({
  dataSelected = [],
  setSelectionModel,
  tableApiRef,
  isOpenDialogCancel,
  setIsOpenDialogCancel,
  successMessage = 'Data berhasil dibatalkan',
}) => {
  const queryClient = useQueryClient();
  const TABLE_KEY = useMemo(() => createTableKey(appRootKey, bulanan), []);
  const [paginationState] = useTablePagination(TABLE_KEY);
  
  const [tglPembatalan, setTglPembatalan] = useState<Dayjs | null>(null);
  const [isOpenDialogProgressBar, setIsOpenDialogProgressBar] = useState(false);

  const {
    numberOfData,
    setNumberOfData,
    numberOfDataFail,
    numberOfDataProcessed,
    numberOfDataSuccess,
    processSuccess,
    processFail,
    resetToDefault,
    status,
  } = useDialogProgressBar();

  const { mutateAsync } = useCencelBulanan({
    onSuccess: () => processSuccess(),
    onError: () => processFail(),
  });

  // ✅ update jumlah data di progress bar
  useEffect(() => {
    setNumberOfData(dataSelected?.length ?? 0);
  }, [dataSelected, setNumberOfData]);

  // ✅ Ambil tanggal pemotongan paling awal (untuk minDate)
  const minPembatalanDate = useMemo(() => {
    if (!dataSelected.length) return null;
    const dates = dataSelected
      .map((d) => {
        const tgl = d.tglPemotongan || d.tglpemotongan;
        return tgl ? dayjs(tgl, ['YYYY-MM-DD', 'DD/MM/YYYY']) : null;
      })
      .filter((d): d is Dayjs => !!d && d.isValid());

    return dates.length > 0 ? dayjs.min(dates) : null;
  }, [dataSelected]);

  const handleCloseModal = () => {
    setIsOpenDialogCancel(false);
    resetToDefault();
  };

  const handleSubmit = async () => {
    if (!tglPembatalan) {
      enqueueSnackbar('Tanggal pembatalan harus diisi', { variant: 'warning' });
      return;
    }

    const formattedDate = formatDateDDMMYYYY(tglPembatalan.toDate());
    const ids = dataSelected.map((item) => String(item.id ?? item.internal_id));

    try {
      setIsOpenDialogProgressBar(true);

      const results = await Promise.allSettled(
        ids.map((id) => mutateAsync({ id, tglPembatalan: formattedDate }))
      );

      const rejected = results.filter((r) => r.status === 'rejected');
      const success = results.filter((r) => r.status === 'fulfilled');

      // ✅ tampilkan pesan error detail
      if (rejected.length > 0) {
        const errorMessages = rejected
          .map((r) => (r.status === 'rejected' ? r.reason?.message : ''))
          .filter(Boolean)
          .join('\n');

        enqueueSnackbar(
          <span style={{ whiteSpace: 'pre-line' }}>
            {errorMessages || `${rejected.length} dari ${ids.length} data gagal dibatalkan.`}
          </span>,
          { variant: 'error' }
        );
        processFail();
      }

      if (success.length > 0) {
        enqueueSnackbar(successMessage, { variant: 'success' });
        processSuccess();
      }

      // ✅ update cache data lokal agar status langsung berubah
      queryClient.setQueryData(queryKey.bulanan.all(''), (old: any) => {
        if (!old?.data) return old;
        return {
          ...old,
          data: old.data.map((row: any) =>
            ids.includes(String(row.id)) ? { ...row, fgStatus: 'CANCELLED' } : row
          ),
        };
      });

      // ✅ refetch data agar sinkron
      await queryClient.invalidateQueries({ queryKey: queryKey.bulanan.all({page: paginationState.page + 1, limit: paginationState.pageSize}) });

      // ⚠️ Tidak perlu clearSelection di sini — DnListView akan sync otomatis lewat rowsSet
      handleCloseModal();
    } catch (error: any) {
      enqueueSnackbar(error?.message || 'Gagal membatalkan data', { variant: 'error' });
      processFail();
    } finally {
      setIsOpenDialogProgressBar(false);
    }
  };

  return (
    <>
      {/* ✅ Dialog reusable */}
      <DialogUmum
        isOpen={isOpenDialogCancel}
        onClose={handleCloseModal}
        title="Batal Bukti Pemotongan/Pemungutan PPh Unifikasi"
      >
        <Stack spacing={2}>
          <Typography>
            Silakan isi tanggal pembatalan. Tanggal tidak boleh sebelum tanggal pemotongan.
          </Typography>

          <DatePicker
            label="Tanggal Pembatalan"
            format="DD/MM/YYYY"
            value={tglPembatalan}
            maxDate={dayjs()}
            minDate={minPembatalanDate || undefined}
            onChange={(newValue) => setTglPembatalan(newValue)}
            slotProps={{
              textField: {
                size: 'medium',
                fullWidth: true,
                helperText:
                  minPembatalanDate && `Tanggal minimal: ${minPembatalanDate.format('DD/MM/YYYY')}`,
                InputLabelProps: { shrink: true },
                sx: {
                  '& .MuiOutlinedInput-root': {
                    borderRadius: 1.5,
                    backgroundColor: '#fff',
                    '&:hover fieldset': {
                      borderColor: '#123375 !important',
                    },
                    '&.Mui-focused fieldset': {
                      borderColor: '#123375 !important',
                      borderWidth: '1px',
                    },
                  },
                },
              },
            }}
          />

          <Stack direction="row" justifyContent="flex-end" spacing={1} mt={1}>
            <Button variant="outlined" onClick={handleCloseModal}>
              Batal
            </Button>
            <Button
              variant="contained"
              color="error"
              onClick={handleSubmit}
              disabled={!tglPembatalan}
            >
              Batalkan
            </Button>
          </Stack>
        </Stack>
      </DialogUmum>

      {/* ✅ Dialog progress bar */}
      <DialogProgressBar
        isOpen={isOpenDialogProgressBar}
        handleClose={() => {
          handleCloseModal();
          setIsOpenDialogProgressBar(false);
        }}
        numberOfData={numberOfData}
        numberOfDataProcessed={numberOfDataProcessed}
        numberOfDataFail={numberOfDataFail}
        numberOfDataSuccess={numberOfDataSuccess}
        status={status}
      />
    </>
  );
};

export default ModalCancelBulanan;
