import React, { useEffect, useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { enqueueSnackbar } from 'notistack';
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 useUpload from '../../hooks/useUpload';
import DialogUmum from 'src/shared/components/dialog/DialogUmum';
import Stack from '@mui/material/Stack';
import Grid from '@mui/material/Grid';
import { Field } from 'src/components/hook-form';
import MenuItem from '@mui/material/MenuItem';
import { useSelector } from 'react-redux';
import type { RootState } from 'src/store';
import Agreement from 'src/shared/components/agreement/Agreement';
import { FormProvider, useForm } from 'react-hook-form';
import Button from '@mui/material/Button';

interface ModalUploadSspProps {
  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;

  singleUploadPayload?: any;
}

/**
 * Normalize various possible shapes of grid selection model into array of ids.
 * Handles:
 *  - array of ids: [1, 2, 'a']
 *  - Set-of-ids: new Set([1,2])
 *  - object like { ids: Set(...), type: 'include' }
 *  - fallback: tries to extract keys if it's an object map
 */
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 ModalUploadSsp: React.FC<ModalUploadSspProps> = ({
  dataSelected,
  setSelectionModel,
  tableApiRef,
  isOpenDialogUpload,
  setIsOpenDialogUpload,
  successMessage = 'Data berhasil diupload',
  onConfirmUpload,
  singleUploadPayload,
}) => {
  const queryClient = useQueryClient();

  const uploadSsp = useUpload();
  // custom hooks for progress state
  const {
    numberOfData,
    setNumberOfData,
    numberOfDataFail,
    numberOfDataProcessed,
    numberOfDataSuccess,
    processSuccess,
    processFail,
    resetToDefault,
    status,
  } = useDialogProgressBar();

  const [isOpenDialogProgressBar, setIsOpenDialogProgressBar] = useState(false);
  const [isCheckedAgreement, setIsCheckedAgreement] = useState<boolean>(false);
  const signer = useSelector((state: RootState) => state.user.data.signer);

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

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

  // fungsi multiple delete -- gunakan normalized array of ids
  const handleMultipleUpload = async () => {
    if (singleUploadPayload) {
      setNumberOfData(1);
      return Promise.allSettled([mutateAsync(singleUploadPayload)]);
    }

    const ids = normalizeSelection(dataSelected);
    setNumberOfData(ids.length);
    return Promise.allSettled(ids.map((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 handleMultipleUpload();
      enqueueSnackbar(successMessage, { variant: 'success' });

      // ✅ refetch langsung setelah sukses
      await onConfirmUpload?.();

      handleCloseModal();
      clearSelection();
    } catch (error: any) {
      enqueueSnackbar(error?.message || 'Gagal upload data', { variant: 'error' });
    } finally {
      // sesuaikan queryKey jika perlu; tetap panggil invalidasi
      queryClient.invalidateQueries({ queryKey: ['unifikasi', 'nr'] });
    }
  };

  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}>
              <Button
                type="button"
                disabled={!isCheckedAgreement}
                onClick={onSubmit}
                loading={uploadSsp.isPending}
                variant="contained"
                sx={{ background: '#143B88' }}
              >
                Save
              </Button>
            </Stack>
          </Stack>
        </DialogUmum>
      </FormProvider>

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

export default ModalUploadSsp;
