"use client";

import Check from "@mui/icons-material/Check";
import Close from "@mui/icons-material/Close";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import Tab from "@mui/material/Tab";
import Tabs, { TabsProps } from "@mui/material/Tabs";
import { useRouter, useSearchParams } from "next/navigation";
import React, { useCallback, useEffect, useLayoutEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import {
    FieldErrors,
    FormProvider,
    SubmitErrorHandler,
    SubmitHandler,
    useForm,
} from "react-hook-form";
import { Error } from "@mui/icons-material";
import { Typography } from "@mui/material";
import { CustomerFormInputs, fetchCustomer, saveCustomer } from "@/app/api/customer/actions";
import CustomerInfo from "./CustomerInfo";
import SubsidiaryAllocation from "./SubsidiaryAllocation";
import { CustomerType, Subsidiary } from "@/app/api/customer";
import { errorDialog, submitDialog, successDialog, warningDialog } from "../Swal/CustomAlerts";
import { differenceBy } from "lodash";

export interface Props {
    subsidiaries: Subsidiary[],
    customerTypes: CustomerType[],
    maxCustomerCode: string
}

const hasErrorsInTab = (
    tabIndex: number,
    errors: FieldErrors<CustomerFormInputs>,
) => {
    switch (tabIndex) {
        case 0:
            return Object.keys(errors).length > 0;
        default:
            false;
    }
};

const CustomerSave: React.FC<Props> = ({
    subsidiaries,
    customerTypes,
    maxCustomerCode
}) => {
    const [serverError, setServerError] = useState("");
    const [tabIndex, setTabIndex] = useState(0);
    const [refCustomer, setRefCustomer] = useState<CustomerFormInputs>()
    const { t } = useTranslation();
    const router = useRouter();
    const searchParams = useSearchParams()

    const fetchCurrentCustomer = async () => {
        const id = searchParams.get('id')
        try {
            const defaultCustomer = {
                id: null,
                code: maxCustomerCode ?? "",
                name: "",
                brNo: null,
                address: null,
                district: null,
                typeId: 1,
                addContacts: [],
                addSubsidiaryIds: [],
                deleteSubsidiaryIds: [],
                deleteContactIds: [],
                isGridEditing: false
            }

            if (id !== null && parseInt(id) > 0) {

                const customer = await fetchCustomer(parseInt(id))

                console.log(customer)

                if (customer !== null && Object.keys(customer).length > 0 && !Object.values(customer.customer).every(x => x === null)) {
                    const tempCustomerInput = {
                        id: customer.customer.id,
                        code: customer.customer.code ?? "",
                        name: customer.customer.name ?? "",
                        brNo: customer.customer.brNo ?? null,
                        address: customer.customer.address ?? null,
                        district: customer.customer.district ?? null,
                        typeId: customer.customer.customerType.id,
                        addContacts: customer.contacts ?? [],
                        addSubsidiaryIds: customer.subsidiaryIds ?? [],
                        deleteSubsidiaryIds: [],
                        deleteContactIds: [],
                        isGridEditing: false
                    }
                    setRefCustomer(tempCustomerInput)
                } else {
                    setRefCustomer(defaultCustomer)
                }
            } else {
                setRefCustomer(defaultCustomer)
            }
        } catch (e) {
            console.log(e)
            setServerError(t("An error has occurred. Please try again later."));
        }
    }

    useLayoutEffect(() => {
        fetchCurrentCustomer()
    }, [])

    const formProps = useForm<CustomerFormInputs>({
        // defaultValues: useMemo(() => {
        //     return refCustomer;
        // }, [refCustomer])
        // defaultValues: {
        //     id: null,
        //     code: "",
        //     name: "",
        //     brNo: null,
        //     address: null,
        //     district: null,
        //     typeId: 1,
        //     addContacts: [],
        //     addSubsidiaryIds: [],
        //     deleteSubsidiaryIds: [],
        //     deleteContactIds: [],
        //     isGridEditing: false
        // }
    });

    useEffect(() => {
        if (refCustomer !== null && refCustomer !== undefined) {
            formProps.reset(refCustomer)
        }
    }, [refCustomer])

    const handleCancel = () => {
        router.back();
    };

    const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
        (_e, newValue) => {
            setTabIndex(newValue);
        },
        [],
    );

    const onSubmit = useCallback<SubmitHandler<CustomerFormInputs>>(
        async (data) => {
            try {
                if (data.isGridEditing) {
                    warningDialog(t("Please save all the rows before submitting"), t)
                    return false
                }

                console.log(data);

                let haveError = false
                if (data.name.length === 0) {
                    haveError = true
                    formProps.setError("name", { message: "Name is empty", type: "required" })
                }

                if (data.code.length === 0) {
                    haveError = true
                    formProps.setError("code", { message: "Code is empty", type: "required" })
                }

                // if (data.email && data.email?.length > 0 && !/^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/.test(data.email)) {
                //     haveError = true
                //     formProps.setError("email", { message: "Email format is not valid", type: "custom" })
                // }

                if (data.brNo && data.brNo?.length > 0 && !/[0-9]{8}/.test(data.brNo)) {
                    haveError = true
                    formProps.setError("brNo", { message: "Br No. format is not valid", type: "custom" })
                }

                if (data.addContacts.length === 0 || data.addContacts.filter(row => String(row.name).trim().length === 0).length > 0) {
                    haveError = true
                    formProps.setError("addContacts", { message: "Contact info includes empty fields", type: "required" })
                }

                // if (data.addContacts.length > 0 
                //     && data.addContacts.filter(row => !/^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$/.test(String(row.email))).length > 0 
                //     && data.addContacts.filter(row => !/^[+0-9][0-9\s]*$/.test(String(row.phone))).length > 0) {
                //     haveError = true
                //     formProps.setError("addContacts", { message: "Contact info includes invalid email or phone", type: "format" })
                // }

                if (haveError) {
                    // go to the error tab
                    setTabIndex(0)
                    return false
                }

                data.deleteContactIds = differenceBy(refCustomer?.addContacts.map(contact => contact.id)!!, data.addContacts.map(contact => contact.id)!!)
                data.deleteSubsidiaryIds = differenceBy(refCustomer?.addSubsidiaryIds!!, data.addSubsidiaryIds)

                setServerError("");

                submitDialog(async () => {
                    const response = await saveCustomer(data);

                    if (response.message === "Success") {
                        successDialog(t("Submit Success"), t).then(() => {
                            router.replace("/settings/customer");
                        })
                    } else {
                        errorDialog(t("Submit Fail"), t).then(() => {
                            formProps.setError("code", { message: response.message, type: "custom" })
                            setTabIndex(0)
                            return false
                        })
                    }
                }, t)
            } catch (e) {
                console.log(e)
                setServerError(t("An error has occurred. Please try again later."));
            }
        },
        [router, t, refCustomer],
    );

    const onSubmitError = useCallback<SubmitErrorHandler<CustomerFormInputs>>(
        (errors) => {
            // Set the tab so that the focus will go there
            if (Object.keys(errors).length > 0) {
                setTabIndex(0);
            }
        },
        [],
    );

    const errors = formProps.formState.errors;

    return (
        <FormProvider {...formProps}>
            {refCustomer && <Stack
                spacing={2}
                component="form"
                onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
            >
                <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable">
                    <Tab
                        label={t("Customer Info")}
                        icon={
                            hasErrorsInTab(0, errors) ? (
                                <Error sx={{ marginInlineEnd: 1 }} color="error" />
                            ) : undefined
                        }
                        iconPosition="end"
                    />
                    <Tab label={t("Subsidiary Allocation")} iconPosition="end" />
                </Tabs>
                {serverError && (
                    <Typography variant="body2" color="error" alignSelf="flex-end">
                        {serverError}
                    </Typography>
                )}
                {tabIndex === 0 && <CustomerInfo customerTypes={customerTypes} />}
                {tabIndex === 1 && <SubsidiaryAllocation subsidiaries={subsidiaries} />}

                <Stack direction="row" justifyContent="flex-end" gap={1}>
                    <Button
                        variant="outlined"
                        startIcon={<Close />}
                        onClick={handleCancel}
                    >
                        {t("Cancel")}
                    </Button>
                    <Button variant="contained" startIcon={<Check />} type="submit" disabled={Boolean(formProps.watch("isGridEditing"))}>
                        {t("Save")}
                    </Button>
                </Stack>
            </Stack>}
        </FormProvider>
    );
};

export default CustomerSave;