import { LoadingButton } from '@mui/lab';
import { Grid, MenuItem, Stack } from '@mui/material';
import type { GridRowSelectionModel } from '@mui/x-data-grid-premium';
import { useQueryClient } from '@tanstack/react-query';
import { enqueueSnackbar } from 'notistack';
import { useEffect, useMemo, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { Field } from 'src/components/hook-form';
import Agreement from 'src/shared/components/agreement/Agreement';
import DialogProgressBar from 'src/shared/components/dialog/DialogProgressBar';
import DialogUmum from 'src/shared/components/dialog/DialogUmum';
import useDialogProgressBar from 'src/shared/hooks/useDialogProgressBar';
import { useAppSelector } from 'src/store';
import queryKey, { appRootKey, bulanan } from '../constant/queryKey';
import useUploadBulanan from '../hooks/useUploadeBulanan';
import { createTableKey, useTablePagination } from '../../paginationStore';

interface DialogPenandatanganProps {
  dataSelected?: GridRowSelectionModel;
  setSelectionModel?: React.Dispatch<React.SetStateAction<GridRowSelectionModel | undefined>>;
  tableApiRef?: React.MutableRefObject<any>;
  isOpenDialogUpload: boolean;
  setIsOpenDialogUpload: (v: boolean) => void;
  successMessage?: string;
  onConfirmUpload?: () => Promise<void> | void;
}

const normalizeSelection = (sel?: any): (string | number)[] => {
  if (!sel) return [];
  if (Array.isArray(sel)) return sel as (string | number)[];
  if (sel instanceof Set) return Array.from(sel) as (string | number)[];
  if (typeof sel === 'object') {
    // common shape from newer MUI: { ids: Set(...), type: 'include' }
    if (sel.ids instanceof Set) return Array.from(sel.ids) as (string | number)[];
    // maybe it's a map-like object { '1': true, '2': true }
    const maybeIds = Object.keys(sel).filter((k) => k !== 'type' && k !== 'size');
    if (maybeIds.length > 0) {
      // try to convert numeric-like keys to number where applicable
      return maybeIds.map((k) => {
        const n = Number(k);
        return Number.isNaN(n) ? k : n;
      });
    }
  }
  return [];
};

const DialogPenandatangan: React.FC<DialogPenandatanganProps> = ({
  dataSelected,
  setSelectionModel,
  tableApiRef,
  isOpenDialogUpload,
  setIsOpenDialogUpload,
  successMessage = 'Data berhasil diupload',
  onConfirmUpload,
}) => {
    const TABLE_KEY = useMemo(() => createTableKey(appRootKey, bulanan), []);
    const [paginationState] = useTablePagination(TABLE_KEY);

  const [isOpenDialogProgressBar, setIsOpenDialogProgressBar] = useState(false);
  const [isCheckedAgreement, setIsCheckedAgreement] = useState<boolean>(false);
  const signer = useAppSelector((state) => state.user.data.signer);
  const queryClient = useQueryClient();

  const methods = useForm({
    defaultValues: {
      signer: signer || '',
    },
  });

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

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

  const handleMultipleDelete = async () => {
    const ids = normalizeSelection(dataSelected);
    return Promise.allSettled(ids.map(async (id) => mutateAsync({ id: String(id) })));
  };

  const clearSelection = () => {
    // clear grid selection via apiRef if available
    tableApiRef?.current?.setRowSelectionModel?.([]);
    // also clear local state if setter provided
    // set to undefined to follow the native hook type (or to empty array cast)
    setSelectionModel?.(undefined);
  };

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

  const onSubmit = async () => {
    try {
      setIsOpenDialogProgressBar(true);
      await handleMultipleDelete();
      enqueueSnackbar(successMessage, { variant: 'success' });
      handleCloseModal();
      clearSelection();
    } catch (error: any) {
      enqueueSnackbar(error?.message || 'Gagal upload data', { variant: 'error' });
    } finally {
      // sesuaikan queryKey jika perlu; tetap panggil invalidasi
      queryClient.invalidateQueries({ queryKey: queryKey.bulanan.all({page: paginationState.page + 1, limit: paginationState.pageSize}) });
    }
  };

  useEffect(() => {
    setNumberOfData(normalizeSelection(dataSelected).length);
  }, [isOpenDialogUpload, dataSelected, setNumberOfData]);

  return (
    <>
      <FormProvider {...methods}>
        <DialogUmum
          isOpen={isOpenDialogUpload}
          onClose={handleCloseModal}
          title="Upload Bukti Potong"
        >
          <Stack spacing={2} sx={{ mt: 2 }}>
            <Grid size={{ md: 12 }}>
              <Field.Select name="signer" label="NPWP/NIK Penandatangan">
                <MenuItem value={signer}>{signer}</MenuItem>
              </Field.Select>
            </Grid>
            <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" justifyContent="flex-end" spacing={1} mt={1}>
              <LoadingButton
                type="button"
                disabled={!isCheckedAgreement}
                // onClick={onSubmit}
                onClick={async () => {
                  if (onConfirmUpload) {
                    await onConfirmUpload();
                    setIsOpenDialogUpload(false);
                    return;
                  }

                  await onSubmit();
                }}
                loading={isPending}
                variant="contained"
                sx={{ background: '#143B88' }}
              >
                Save
              </LoadingButton>
            </Stack>
          </Stack>
        </DialogUmum>
      </FormProvider>

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

export default DialogPenandatangan;
