import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Modal, Box, Typography, Button, TextField, FormControl, InputLabel, Select, MenuItem, Paper, SxProps, ModalProps, Tooltip } from '@mui/material';
import { useForm, Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil';
import dayjs from 'dayjs';
import { DatePicker } from '@mui/x-date-pickers';
import { GridRenderEditCellParams, FooterPropsOverrides, GridEventListener, GridRowEditStopParams, GridRowEditStopReasons, GridRowIdGetter, GridRowModel, GridRowModes, GridRowModesModel, GridToolbarContainer, useGridApiRef, GridEditSingleSelectCell, GridCellParams, GridRowId } from '@mui/x-data-grid';
import StyledDataGrid from '../StyledDataGrid';
import AddIcon from '@mui/icons-material/Add';
import SaveIcon from '@mui/icons-material/Save';
import DeleteIcon from '@mui/icons-material/Delete';
import CancelIcon from '@mui/icons-material/Cancel';
import EditIcon from '@mui/icons-material/Edit'; 
import { GridActionsCellItem } from '@mui/x-data-grid';
import waitForCondition from '../utils/waitFor';
import { StaffEntryError, validateRowAndRowBefore } from './validateDates';
import { salaryEffectiveInfo } from '@/app/api/staff/actions';
import { comboItem } from "../CreateStaff/CreateStaff";
import { Add } from '@mui/icons-material';
import { GridEditDateCell } from '@mui/x-data-grid';

interface SalaryEffectiveModelProps {
  open: boolean;
  onClose: () => void;
  modalSx?: SxProps;
  combos: comboItem;
}

const modalSx: SxProps = {
    position: "absolute",
    top: "50%",
    left: "50%",
    transform: "translate(-50%, -50%)",
    width: "90%",
    maxWidth: "auto",
    maxHeight: "auto",
    padding: 3,
    display: "flex",
    flexDirection: "column",
    gap: 2,
  };

export type SeModalRow = Partial<
salaryEffectiveInfo & {
  _isNew: boolean
  _error: StaffEntryError;
}
>  
export class ProcessRowUpdateError<T> extends Error {
  public readonly prevRow: T | null;
  public readonly currRow: T;
  public readonly errors: StaffEntryError | undefined;
  constructor(
    prevRow: T | null,
    currRow: T,
    message?: string,
    errors?: StaffEntryError,
  ) {
    super(message);
    this.prevRow = prevRow;
    this.currRow = currRow;
    this.errors = errors;

    Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
  }
}
const thisField = "salaryEffectiveInfo"
const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClose, modalSx: mSx, combos }) => {
  const {
    t,
    // i18n: { language },
  } = useTranslation();
  const { setValue, getValues } = useFormContext();
  const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
  const apiRef = useGridApiRef()
  const [_rows, setRows] = useState(() => {
    const list: SeModalRow[] = getValues(thisField)
    return list && list.length > 0 ? list : []
  });
  const originalRows = useMemo(() => _rows.filter(rw => rw._isNew !== true), [_rows])
  const [_delRows, setDelRows] = useState<number[]>([]);

  const getRowId = useCallback<GridRowIdGetter<SeModalRow>>(
    (row) => row.id!!,
    [],
  );

  const isSaved = useCallback(() => {
    const saved = Object.keys(rowModesModel).every(key => {
      rowModesModel[key].mode === GridRowModes.Edit
    })
    return saved
  }, [rowModesModel])

  const doSave = useCallback(async () => {
    try {
      if (isSaved()) {
        setValue(thisField, _rows)
        onClose()
      }
    } catch (error) {
      console.error(error);
    }
  }, [isSaved, onClose, _rows]);

  const onCancel = useCallback(() => {
    setRows(originalRows)
    onClose();
  }, [onClose, originalRows]);

    const handleClose = useCallback<NonNullable<ModalProps["onClose"]>>(
      (_, reason) => {
        if (reason !== "backdropClick") {
          onClose();
        }
    }, [onClose]); 
    
  const onProcessRowUpdateError = useCallback(
    (updateError: ProcessRowUpdateError<SeModalRow>) => {
      const errors = updateError.errors;
      const currRow = updateError.currRow;
      console.log(errors)
      apiRef.current.updateRows([{ ...currRow, _error: errors }]);
    },
    [apiRef, rowModesModel],
  );  
  const processRowUpdate = useCallback((
    newRow: GridRowModel<SeModalRow>, 
    originalRow: GridRowModel<SeModalRow>
  ) => {
    const rowIndex = _rows.findIndex((row: SeModalRow) => row.id === newRow.id);
    const prevRow: SeModalRow | null = rowIndex > 0 ? _rows[rowIndex - 1] : null;
    const errors = validateRowAndRowBefore(prevRow, newRow)
    console.log(errors)
    if (errors) {
      throw new ProcessRowUpdateError(
        prevRow,
        newRow,
        "validation error",
        errors
      )
    }
    const { _isNew, _error, ...updatedRow } = newRow;
    const rowToSave = {
      ...updatedRow,
      _isNew,
    }
    console.log(_rows)
    if (_rows.length != 0) {
      setRows((prev) => prev?.map((row) => (row.id === newRow.id ? rowToSave : row)).sort((a, b) => {
        if (!a.date || !b.date) return 0;
        return new Date(a.date).getTime() - new Date(b.date).getTime();
      }));
    }
    return rowToSave;
  }
  , [validateRowAndRowBefore, _rows])

  // useEffect(()=> {
  //   console.log(_rows)
  //   setValue(thisField, _rows)
  // }, [_rows])

  useEffect(()=> {
    console.log(_delRows)
    setValue('delSalaryEffectiveInfo', _delRows)
  }, [_delRows])

  const handleSave = useCallback((id: GridRowId) => () => {
      setRowModesModel((prevRowModesModel) => ({
        ...prevRowModesModel,
        [id]: { mode: GridRowModes.View }
      }));
    },
    [setRowModesModel]
  );
  
  const handleCancel = useCallback(
    (id: GridRowId) => () => {
      setRowModesModel((prevRowModesModel) => ({
        ...prevRowModesModel,
        [id]: { mode: GridRowModes.View, ignoreModifications: true }
      }));
    },
    [setRowModesModel]
  );

  const handleDelete = useCallback(
    (id: GridRowId) => () => {
      setRows((prevRows) => prevRows.filter((row: any) => row.id !== id));
      setDelRows((prevRowsId: number[]) => [...prevRowsId, id as number])
    },
    []
  );

  
  const columns = useMemo(
    () => [
      {
      field: 'salaryPoint',
      headerName: 'salaryPoint',
      flex: 1,
      editable: true,
      type: 'singleSelect',
      valueOptions: combos.salary.map((item) => item.label),
      renderEditCell(params: GridRenderEditCellParams<SeModalRow>) {
        const errorMessage = params.row._error?.[params.field as keyof StaffEntryError]
        const content = (
          <GridEditSingleSelectCell variant="outlined" {...params} />
        );
        return errorMessage ? (
          <Tooltip title={errorMessage}>
            <Box width="100%">{content}</Box>
          </Tooltip>
        ) : (
          content
        );
      }
      },
      {
      field: 'date',
      headerName: 'date',
      flex: 1,
      editable: true,
      type: 'date',
      renderEditCell(params: GridRenderEditCellParams<SeModalRow>) {
        const errorMessage = params.row._error?.[params.field as keyof StaffEntryError]
        const content = <GridEditDateCell {...params} />;
        return errorMessage ? (
          <Tooltip title={errorMessage}>
            <Box width="100%">{content}</Box>
          </Tooltip>
        ) : (
          content
        );
      }
      },
      {
        field: 'actions',
        type: 'actions',
        headerName: 'edit',
        width: 100,
        cellClassName: 'actions',
        getActions: ({ id }: { id: number }) => {
          const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
          if (isInEditMode) {
            return [
              <GridActionsCellItem
                icon={<SaveIcon />}
                label="Save"
                key="edit"
                sx={{
                  color: 'primary.main'
                }}
                onClick={handleSave(id)}
              />,
              <GridActionsCellItem
                icon={<CancelIcon />}
                label="Cancel"
                key="edit"
                onClick={handleCancel(id)}
              />
            ];
          }
          return [
            <GridActionsCellItem 
              icon={<DeleteIcon />} 
              label="Delete" 
              sx={{
                color: 'error.main'
              }}
              onClick={handleDelete(id)} color="inherit" key="edit" />
          ];
        }
      }
  ], [combos, rowModesModel, handleSave, handleCancel, handleDelete])

  const addRow = useCallback(() => {
    const newEntry = { id: Date.now(), _isNew: true } satisfies SeModalRow;
    setRows((prev) => [...prev, newEntry])
    setRowModesModel((model) => ({
      ...model,
      [getRowId(newEntry)]: {
        mode: GridRowModes.Edit,
        fieldToFocus: "team",
      }
    }))
  }, [getRowId]);

  const footer = (
    <Box display="flex" gap={2} alignItems="center">
      <Button
        disableRipple
        variant="outlined"
        startIcon={<Add />}
        onClick={addRow}
        size="small"
      >
        {t("Add Record")}
      </Button>
    </Box>
    )

  return (
    <Modal open={open} onClose={handleClose}>
    <Paper sx={{ ...modalSx, ...mSx }}>
        <Typography variant="h6" component="h2">
          {t('Salary Effective Date Change')}
        </Typography>
          <StyledDataGrid
                getRowId={getRowId}
                apiRef={apiRef}
                rows={_rows}
                columns={columns}
                editMode="row"
                autoHeight
                sx={{
                  "--DataGrid-overlayHeight": "100px",
                  ".MuiDataGrid-row .MuiDataGrid-cell.hasError": {
                    border: "1px solid",
                    borderColor: "error.main",
                  },
                  ".MuiDataGrid-row .MuiDataGrid-cell.hasWarning": {
                    border: "1px solid",
                    borderColor: "warning.main",
                  },
                }}
                disableColumnMenu
                rowModesModel={rowModesModel}
                onRowModesModelChange={setRowModesModel}
                onProcessRowUpdateError={onProcessRowUpdateError}
                processRowUpdate={processRowUpdate}
                getCellClassName={(params: GridCellParams<SeModalRow>) => {
                  let classname = "";
                  if (params.row._error) {
                    classname = "hasError"
                  }
                  return classname;
                }}
                slots={{
                  footer: FooterToolbar,
                  noRowsOverlay: NoRowsOverlay,
                }}
                slotProps={{
                  footer: { child: footer },
                }}
              />
        <Box display="flex" justifyContent="flex-end" gap={2}>
          <Button variant="text" onClick={onCancel}>
            {t('Cancel')}
          </Button>
          <Button variant="contained" onClick={doSave}>
                {t("Save")}
            </Button>
        </Box>
        {/* </FormControl> */}
    </Paper>
    </Modal>
  );
};
const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => {
  return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>;
};
const NoRowsOverlay: React.FC = () => {
  const { t } = useTranslation("home");
  return (
    <Box
      display="flex"
      justifyContent="center"
      alignItems="center"
      height="100%"
    >
      <Typography variant="caption">{t("Add some entries!")}</Typography>
    </Box>
  );
};
export default SalaryEffectiveModel;