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 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';
import { useReturDokumenLainMasukan } from '../../hooks/useReturDokumenLainMasukan';
import useUploadDokumenLainMasukan from '../../hooks/useUploadDokumenLainKeluaran';

interface ModalUploadDokumenLainMasukanProps {
  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;
  isRetur?: boolean;
}

/**
 * Normalize selection -> array of ids
 */
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') {
    if (sel.ids instanceof Set) return Array.from(sel.ids) as (string | number)[];
    const maybeIds = Object.keys(sel).filter((k) => k !== 'type' && k !== 'size');
    if (maybeIds.length > 0) {
      return maybeIds.map((k) => {
        const n = Number(k);
        return Number.isNaN(n) ? k : n;
      });
    }
  }
  return [];
};

const ModalUploadDokumenLainMasukan: React.FC<ModalUploadDokumenLainMasukanProps> = ({
  dataSelected,
  setSelectionModel,
  tableApiRef,
  isOpenDialogUpload,
  setIsOpenDialogUpload,
  successMessage = 'Data berhasil diupload',
  onConfirmUpload,
  singleUploadPayload,
  isRetur,
}) => {
  const queryClient = useQueryClient();

  // progress state helpers
  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);

  // upload mutation (ke API upload)
  const { mutateAsync: uploadMutateAsync, isPending: uploadIsPending } =
    useUploadDokumenLainMasukan({
      onSuccess: () => processSuccess(),
      onError: () => processFail(),
    });

  // retur mutation (dipanggil sebelum upload jika isRetur && singleUploadPayload)
  // NOTE: useReturDokumenLainKeluaran expects { dlkData, onSuccess? } — jangan kirim onError di sini.
  const returMutation = useReturDokumenLainMasukan({
    dlkData: singleUploadPayload ?? {},
    onSuccess: () => processSuccess(),
  });

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

  const handleMultipleUpload = async () => {
    if (singleUploadPayload) {
      setNumberOfData(1);
      return Promise.allSettled([uploadMutateAsync(singleUploadPayload)]);
    }

    const ids = normalizeSelection(dataSelected);
    setNumberOfData(ids.length);
    return Promise.allSettled(ids.map((id) => uploadMutateAsync({ id: String(id) })));
  };

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

  const onSubmit = async () => {
    try {
      setIsOpenDialogProgressBar(true);

      // jika mode retur dan payload single (dari rekam view), panggil retur dulu
      if (isRetur && singleUploadPayload) {
        await returMutation.mutateAsync(singleUploadPayload);
      }

      // lanjut ke upload (bisa singleUploadPayload atau multiple selection)
      await handleMultipleUpload();

      enqueueSnackbar(successMessage, { variant: 'success' });
      await onConfirmUpload?.();
    } catch (error: any) {
      enqueueSnackbar(error?.message || 'Gagal proses data', { variant: 'error' });
    } finally {
      // refresh relevant cache
      queryClient.invalidateQueries({ queryKey: ['dlk'] });
    }
  };

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

  // combine loading state: upload OR retur in-flight
  const isLoading =
    Boolean(uploadIsPending) ||
    Boolean((returMutation as any).isLoading || (returMutation as any).isPending);

  return (
    <>
      <FormProvider {...methods}>
        <DialogUmum
          isOpen={isOpenDialogUpload}
          onClose={handleCloseModal}
          title="Upload Dokumen Lain Masukan"
        >
          <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 data yang saya masukkan adalah benar dan saya bertanggung jawab atas kebenaran data yang saya masukkan sesuai dengan Syarat dan Ketentuan serta Kebijakan Privasi dari PajakExpress."
              />
            </Grid>

            <Stack direction="row" justifyContent="flex-end" spacing={1} mt={1}>
              <Button
                type="button"
                disabled={!isCheckedAgreement || isLoading}
                onClick={onSubmit}
                variant="contained"
                sx={{ background: '#143B88' }}
              >
                {isLoading ? 'Processing...' : '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 ModalUploadDokumenLainMasukan;
