"use client";
import {
  Dispatch,
  MutableRefObject,
  SetStateAction,
  useCallback,
  useEffect,
  useMemo,
  useState,
} from "react";
import StyledDataGrid from "../StyledDataGrid";
import {
  FooterPropsOverrides,
  GridActionsCellItem,
  GridCellParams,
  GridColDef,
  GridEventListener,
  GridRowEditStopReasons,
  GridRowId,
  GridRowIdGetter,
  GridRowModel,
  GridRowModes,
  GridRowModesModel,
  GridRowSelectionModel,
  GridToolbarContainer,
  GridValidRowModel,
  useGridApiRef,
} from "@mui/x-data-grid";
import { set, useFormContext } from "react-hook-form";
import SaveIcon from "@mui/icons-material/Save";
import DeleteIcon from "@mui/icons-material/Delete";
import CancelIcon from "@mui/icons-material/Cancel";
import { Add } from "@mui/icons-material";
import { Box, Button, Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
import {
  GridApiCommunity,
  GridSlotsComponentsProps,
} from "@mui/x-data-grid/internals";
import { dummyQcData_A1 as dummyQCData } from "../Qc/dummyQcTemplate";
// T == CreatexxxInputs map of the form's fields
// V == target field input inside CreatexxxInputs, e.g. qcChecks: ItemQc[], V = ItemQc
// E == error
interface ResultWithId {
  id: string | number;
}
// export type InputGridProps = {
//   [key: string]: any
// }
interface DefaultResult<E> {
  _isNew: boolean;
  _error: E;
}

interface SelectionResult<E> {
  active: boolean;
  _isNew: boolean;
  _error: E;
}
type Result<E> = DefaultResult<E> | SelectionResult<E>;

export type TableRow<V, E> = Partial<
  V & {
    isActive: boolean | undefined;
    _isNew: boolean;
    _error: E;
  } & ResultWithId
>;

export interface InputDataGridProps<T, V, E> {
  apiRef: MutableRefObject<GridApiCommunity>;
//   checkboxSelection: false | undefined;
  _formKey: keyof T;
  columns: GridColDef[];
  validateRow: (newRow: GridRowModel<TableRow<V, E>>) => E;
  needAdd?: boolean;
}

export interface SelectionInputDataGridProps<T, V, E> {
  // thinking how do
  apiRef: MutableRefObject<GridApiCommunity>;
//   checkboxSelection: true;
  _formKey: keyof T;
  columns: GridColDef[];
  validateRow: (newRow: GridRowModel<TableRow<V, E>>) => E;
}

export type Props<T, V, E> =
  | InputDataGridProps<T, V, E>
  | SelectionInputDataGridProps<T, V, E>;
export class ProcessRowUpdateError<T, E> extends Error {
  public readonly row: T;
  public readonly errors: E | undefined;
  constructor(row: T, message?: string, errors?: E) {
    super(message);
    this.row = row;
    this.errors = errors;

    Object.setPrototypeOf(this, ProcessRowUpdateError.prototype);
  }
}
// T == CreatexxxInputs map of the form's fields
// V == target field input inside CreatexxxInputs, e.g. qcChecks: ItemQc[], V = ItemQc
// E == error
function InputDataGrid<T, V, E>({
  apiRef,
//   checkboxSelection = false,
  _formKey,
  columns,
  validateRow,
}: Props<T, V, E>) {
  const {
    t,
    // i18n: { language },
  } = useTranslation(["purchaseOrder","dashboard"]);
  const formKey = _formKey.toString();
  const { setValue, getValues } = useFormContext();
  const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
  // const apiRef = useGridApiRef();
  const getRowId = useCallback<GridRowIdGetter<TableRow<V, E>>>(
    (row) => row.id! as number,
    [],
  );
  const formValue = getValues(formKey)
  const list: TableRow<V, E>[] = !formValue || formValue.length == 0 ? dummyQCData : getValues(formKey);
  console.log(list)
  const [rows, setRows] = useState<TableRow<V, E>[]>(() => {
    // const list: TableRow<V, E>[] = getValues(formKey);
    console.log(list)
    return list && list.length > 0 ? list : [];
  });
  console.log(rows)
  // const originalRows = list && list.length > 0 ? list : [];
  const originalRows = useMemo(() => (
    list && list.length > 0 ? list : []
  ), [list])
  
  // const originalRowModel = originalRows.filter((li) => li.isActive).map(i => i.id) as GridRowSelectionModel
  const [rowSelectionModel, setRowSelectionModel] =
    useState<GridRowSelectionModel>(() => {
      // const rowModel = list.filter((li) => li.isActive).map(i => i.id) as GridRowSelectionModel
      const rowModel: GridRowSelectionModel = getValues(
        `${formKey}_active`,
      ) as GridRowSelectionModel;
      console.log(rowModel);
      return rowModel;
    });

    useEffect(() => {
        for (let i = 0; i < rows.length; i++) {
            const currRow = rows[i]
            setRowModesModel((prevRowModesModel) => ({
                ...prevRowModesModel,
            [currRow.id as number]: { mode: GridRowModes.View },
      }));
        }
    }, [rows])

  const handleSave = useCallback(
    (id: GridRowId) => () => {
      setRowModesModel((prevRowModesModel) => ({
        ...prevRowModesModel,
        [id]: { mode: GridRowModes.View },
      }));
    },
    [],
  );
  const onProcessRowUpdateError = useCallback(
    (updateError: ProcessRowUpdateError<T, E>) => {
      const errors = updateError.errors;
      const row = updateError.row;
      console.log(errors);
      apiRef.current.updateRows([{ ...row, _error: errors }]);
    },
    [apiRef],
  );

  const processRowUpdate = useCallback(
    (
      newRow: GridRowModel<TableRow<V, E>>,
      originalRow: GridRowModel<TableRow<V, E>>,
    ) => {
      /////////////////
      // validation here
      const errors = validateRow(newRow);
      console.log(newRow);
      if (errors) {
        throw new ProcessRowUpdateError(
          originalRow,
          "validation error",
          errors,
        );
      }
      /////////////////
      const { _isNew, _error, ...updatedRow } = newRow;
      const rowToSave = {
        ...updatedRow,
      } as TableRow<V, E>; /// test
      console.log(rowToSave);
      setRows((rw) =>
        rw.map((r) => (getRowId(r) === getRowId(originalRow) ? rowToSave : r)),
      );
      return rowToSave;
    },
    [validateRow, getRowId],
  );

  const addRow = useCallback(() => {
    const newEntry = { id: Date.now(), _isNew: true } as TableRow<V, E>;
    setRows((prev) => [...prev, newEntry]);
    setRowModesModel((model) => ({
      ...model,
      [getRowId(newEntry)]: {
        mode: GridRowModes.Edit,
        // fieldToFocus: "team", /// test
      },
    }));
  }, [getRowId]);

  const reset = useCallback(() => {
    setRowModesModel({});
    setRows(originalRows);
  }, [originalRows]);

  const handleCancel = useCallback(
    (id: GridRowId) => () => {
      setRowModesModel((model) => ({
        ...model,
        [id]: { mode: GridRowModes.View, ignoreModifications: true },
      }));
      const editedRow = rows.find((row) => getRowId(row) === id);
      if (editedRow?._isNew) {
        setRows((rw) => rw.filter((r) => getRowId(r) !== id));
      } else {
        setRows((rw) =>
          rw.map((r) => (getRowId(r) === id ? { ...r, _error: undefined } : r)),
        );
      }
    },
    [rows, getRowId],
  );

  const handleDelete = useCallback(
    (id: GridRowId) => () => {
      setRows((prevRows) => prevRows.filter((row) => getRowId(row) !== id));
    },
    [getRowId],
  );

  const _columns = useMemo<GridColDef[]>(
    () => [
      ...columns,
      {
        field: "actions",
        type: "actions",
        headerName: "",
        flex: 0.5,
        cellClassName: "actions",
        getActions: ({ id }: { id: GridRowId }) => {
          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"
            />,
          ];
        },
      },
    ],
    [columns, rowModesModel, handleSave, handleCancel, handleDelete],
  );
  // sync useForm
  useEffect(() => {
    // console.log(formKey)
    // console.log(rows)
    setValue(formKey, rows);
  }, [formKey, rows, setValue]);

  const footer = (
    <Box display="flex" gap={2} alignItems="center">
      <Button
        disableRipple
        variant="outlined"
        startIcon={<Add />}
        onClick={addRow}
        size="small"
      >
        新增
        {/* {t("Add Record")} */}
      </Button>
      <Button
        disableRipple
        variant="outlined"
        startIcon={<Add />}
        onClick={reset}
        size="small"
      >
        {/* {t("Clean Record")} */}
        清除
      </Button>
    </Box>
  );
  //   const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
  //     if (params.reason === GridRowEditStopReasons.rowFocusOut) {
  //       event.defaultMuiPrevented = true;
  //     }
  //   };

  return (
    <StyledDataGrid
      // {...props}
      // getRowId={getRowId as GridRowIdGetter<GridValidRowModel>}
      rowSelectionModel={rowSelectionModel}
      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
      processRowUpdate={processRowUpdate as any}
      //   onRowEditStop={handleRowEditStop}
      rowModesModel={rowModesModel}
      onRowModesModelChange={setRowModesModel}
      onProcessRowUpdateError={onProcessRowUpdateError}
      getCellClassName={(params: GridCellParams<TableRow<T, E>>) => {
        let classname = "";
        if (params.row._error) {
          classname = "hasError";
        }
        return classname;
      }}
      slots={{
            //   footer: FooterToolbar,
              noRowsOverlay: NoRowsOverlay,
            }}
    //   slotProps={{
    //           footer: { child: footer },
    //         }
    //   }
    />
  );
}
const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => {
  return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>;
};
const NoRowsOverlay: React.FC = () => {
  const { t } = useTranslation("purchaseOrder");
  return (
    <Box
      display="flex"
      justifyContent="center"
      alignItems="center"
      height="100%"
    >
      <Typography variant="caption">{t("Add some entries!")}</Typography>
    </Box>
  );
};
export default InputDataGrid;
