"use client";

import Stack from "@mui/material/Stack";
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Typography from "@mui/material/Typography";
import { useTranslation } from "react-i18next";
import CardActions from "@mui/material/CardActions";
import RestartAlt from "@mui/icons-material/RestartAlt";
import Button from "@mui/material/Button";
import AddIcon from '@mui/icons-material/Add';
import EditIcon from '@mui/icons-material/Edit';
import DeleteIcon from '@mui/icons-material/DeleteOutlined';
import SaveIcon from '@mui/icons-material/Save';
import CancelIcon from '@mui/icons-material/Close';
import {
    GridRowsProp,
    GridRowModesModel,
    GridRowModes,
    GridColDef,
    GridToolbarContainer,
    GridActionsCellItem,
    GridEventListener,
    GridRowId,
    GridRowModel,
    GridRowEditStopReasons,
} from '@mui/x-data-grid';
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid";
import { useFieldArray, useFormContext } from "react-hook-form";
import { useCallback, useEffect, useMemo, useState } from "react";

interface Props {
}

interface EditToolbarProps {
    setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void;
    setRowModesModel: (
        newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
    ) => void;
}

var rowId = -1
function EditToolbar(props: EditToolbarProps) {
    const { setRows, setRowModesModel } = props;
    const { t } = useTranslation();

    const handleClick = () => {
        const id = rowId;
        rowId = rowId - 1;
        setRows((oldRows) => [{ id, name: '', phone: '', email: '', isNew: true }, ...oldRows]);
        setRowModesModel((oldModel) => ({
            ...oldModel,
            [id]: { mode: GridRowModes.Edit, fieldToFocus: 'name' },
        }));
    };

    return (
        <GridToolbarContainer>
            <Button color="primary" startIcon={<AddIcon />} onClick={handleClick}>
                {t("Add Contact Person")}
            </Button>
        </GridToolbarContainer>
    );
}

const ContactInfo: React.FC<Props> = ({
}) => {
    const { t } = useTranslation();

    const { control, setValue, getValues, formState: { errors, defaultValues }, setError, clearErrors, reset, watch, resetField } = useFormContext();
    const { fields } = useFieldArray({
        control,
        name: "addContacts"
    })

    const initialRows: GridRowsProp = fields.map((item, index) => {
        return ({
            id: Number(getValues(`addContacts[${index}].id`)),
            name: getValues(`addContacts[${index}].name`),
            phone: getValues(`addContacts[${index}].phone`),
            email: getValues(`addContacts[${index}].email`),
            isNew: false,
        })
    })

    const [rows, setRows] = useState<GridRowsProp>([]);
    const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});

    useEffect(() => {
        if (initialRows.length > 0 && rows.length === 0) {
            setRows(initialRows)
        }
    }, [initialRows.length > 0])

    const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
        if (params.reason === GridRowEditStopReasons.rowFocusOut) {
            event.defaultMuiPrevented = true;
        }
    };

    const handleEditClick = (id: GridRowId) => () => {
        setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } });
    };

    const handleSaveClick = (id: GridRowId) => () => {
        setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } });
    };

    const handleDeleteClick = (id: GridRowId) => () => {
        const updatedRows = rows.filter((row) => row.id !== id)
        setRows(updatedRows);
        setValue("addContacts", updatedRows)
    };

    const handleCancelClick = (id: GridRowId) => () => {
        setRowModesModel({
            ...rowModesModel,
            [id]: { mode: GridRowModes.View, ignoreModifications: true },
        });

        const editedRow = rows.find((row) => row.id === id);
        if (editedRow!.isNew) {
            setRows(rows.filter((row) => row.id !== id));
        }
    };

    const processRowUpdate = useCallback((newRow: GridRowModel) => {
        const updatedRow = { ...newRow };

        const updatedRows = rows.map((row) => (row.id === newRow.id ? updatedRow : row))
        setRows(updatedRows);
        setValue("addContacts", updatedRows)
        return updatedRow;
    }, [rows]);

    const handleRowModesModelChange = useCallback((newRowModesModel: GridRowModesModel) => {
        setRowModesModel(newRowModesModel);
    }, [rows]);

    const resetContact = useCallback(() => {
        if (defaultValues !== undefined) {
            resetField("addContacts")
            // reset({addContacts: defaultValues.addContacts})
            setRows((prev) => defaultValues.addContacts)
            setRowModesModel(rows.reduce((acc, row) => ({...acc, [row.id]: { mode: GridRowModes.View } }), {}))
        }
    }, [defaultValues])

    const columns = useMemo<GridColDef[]>(
        () => [
            {
                field: 'name',
                headerName: t('Contact Name'),
                editable: true,
                flex: 1,
            },
            {
                field: 'phone',
                headerName: t('Contact Phone'),
                editable: true,
                flex: 1,
            },
            {
                field: 'email',
                headerName: t('Contact Email'),
                editable: true,
                flex: 1,
            },
            {
                field: 'actions',
                type: 'actions',
                headerName: '',
                flex: 0.6,
                // width: 100,
                cellClassName: 'actions',
                getActions: ({ id, ...params }) => {
                    const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;

                    if (isInEditMode) {
                        return [
                            <GridActionsCellItem
                                icon={<SaveIcon />}
                                label="Save"
                                sx={{
                                    color: 'primary.main',
                                }}
                                onClick={handleSaveClick(id)}
                            />,
                            <GridActionsCellItem
                                icon={<CancelIcon />}
                                label="Cancel"
                                className="textPrimary"
                                onClick={handleCancelClick(id)}
                                color="inherit"
                            />,
                        ];
                    }

                    return [
                        <GridActionsCellItem
                            icon={<EditIcon />}
                            label="Edit"
                            className="textPrimary"
                            onClick={handleEditClick(id)}
                            color="inherit"
                        />,
                        <GridActionsCellItem
                            icon={<DeleteIcon />}
                            label="Delete"
                            onClick={handleDeleteClick(id)}
                            color="inherit"
                        />,
                    ];
                },
            },
        ],
        [rows, rowModesModel, t],
    );

    // check error
    useEffect(() => {
        if (getValues("addContacts") === undefined || getValues("addContacts") === null) {
            return;
        }

        if (getValues("addContacts").length === 0) {
            clearErrors("addContacts")
        } else {
            const errorRows = rows.filter(row => String(row.name).trim().length === 0 || String(row.phone).trim().length === 0 || String(row.email).trim().length === 0)

            if (errorRows.length > 0) {
                setError("addContacts", { message: "Contact details include empty fields", type: "required" })
            } else {
                const errorRows_EmailFormat = rows.filter(row => !/^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/.test(String(row.email)))

                if (errorRows_EmailFormat.length > 0) {
                    setError("addContacts", { message: "Contact details include empty fields", type: "email_format" })
                } else {
                    clearErrors("addContacts")
                }
            }
        }
    }, [rows])

    // check editing
    useEffect(() => {
        const filteredByKey = Object.fromEntries(
            Object.entries(rowModesModel).filter(([key, value]) => rowModesModel[key].mode === 'edit'))

        if (Object.keys(filteredByKey).length > 0) {
            setValue("isGridEditing", true)
        } else {
            setValue("isGridEditing", false)
        }
    }, [rowModesModel])

    return (
        <Card sx={{ display: "block" }}>
            <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}>
                <Stack gap={2}>
                    {/* <div> */}
                    <Typography variant="overline" display='inline-block' noWrap>
                        {t("Contact Info")}
                    </Typography>
                    {Boolean(errors.addContacts?.type === "required") && <Typography sx={(theme) => ({ color: theme.palette.error.main })} variant="overline" display='inline-block' noWrap>
                        {t("Please ensure at least one row is created, and all the fields are inputted and saved")}
                    </Typography>}
                    {Boolean(errors.addContacts?.type === "email_format") && <Typography sx={(theme) => ({ color: theme.palette.error.main })} variant="overline" display='inline-block' noWrap>
                        {t("Please ensure all the email formats are correct")}
                    </Typography>}
                    {/* </div> */}
                    <CustomDatagrid
                        rows={[...rows]}
                        columns={columns}
                        editMode="row"
                        rowModesModel={rowModesModel}
                        onRowEditStop={handleRowEditStop}
                        processRowUpdate={processRowUpdate}
                        // onProcessRowUpdateError={handleProcessRowUpdateError}
                        onRowModesModelChange={handleRowModesModelChange}
                        slots={{
                            toolbar: EditToolbar,
                        }}
                        slotProps={{
                            toolbar: { setRows, setRowModesModel },
                        }}
                        sx={{
                            height: '100%'
                        }}
                    />
                    <CardActions sx={{ justifyContent: "flex-end" }}>
                        <Button variant="text" startIcon={<RestartAlt />} onClick={resetContact} disabled={Boolean(watch("isGridEditing"))}>
                            {t("Reset")}
                        </Button>
                    </CardActions>
                </Stack>
            </CardContent>
        </Card>
    );
};

export default ContactInfo;