"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 { errorDialog, submitDialog, successDialog, warningDialog } from "../Swal/CustomAlerts";
import { Customer, SubsidiaryType } from "@/app/api/subsidiary";
import { SubsidiaryFormInputs, fetchSubsidiary, saveSubsidiary } from "@/app/api/subsidiary/actions";
import { differenceBy } from "lodash";
import SubsidiaryInfo from "./SubsidiaryInfo";
import CustomerAllocation from "./CustomerAllocation";

export interface Props {
    customers: Customer[],
    subsidiaryTypes: SubsidiaryType[],
}

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

const SubsidiaryDetail: React.FC<Props> = ({
    customers,
    subsidiaryTypes,
}) => {
    const [serverError, setServerError] = useState("");
    const [tabIndex, setTabIndex] = useState(0);
    const [refSubsidiary, setRefSubsidiary] = useState<SubsidiaryFormInputs>()
    const { t } = useTranslation();
    const router = useRouter();
    const searchParams = useSearchParams()

    const fetchCurrentSubsidiary = async () => {
        const id = searchParams.get('id')
        try {
            const defaultSubsidiary = {
                id: null,
                code: "",
                name: "",
                brNo: null,
                address: null,
                district: null,
                typeId: 1,
                addContacts: [],
                addCustomerIds: [],
                deleteCustomerIds: [],
                deleteContactIds: [],
                isGridEditing: false
            }

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

                const subsidiary = await fetchSubsidiary(parseInt(id))

                if (subsidiary !== null && Object.keys(subsidiary).length > 0 && !Object.values(subsidiary.subsidiary).every(x => x === null)) {
                    const tempSubsidiaryInput = {
                        id: subsidiary.subsidiary.id,
                        code: subsidiary.subsidiary.code ?? "",
                        name: subsidiary.subsidiary.name ?? "",
                        brNo: subsidiary.subsidiary.brNo ?? null,
                        address: subsidiary.subsidiary.address ?? null,
                        district: subsidiary.subsidiary.district ?? null,
                        typeId: subsidiary.subsidiary.subsidiaryType.id,
                        addContacts: subsidiary.contacts ?? [],
                        addCustomerIds: subsidiary.customerIds ?? [],
                        deleteCustomerIds: [],
                        deleteContactIds: [],
                        isGridEditing: false
                    }
                    setRefSubsidiary(tempSubsidiaryInput)
                } else {
                    setRefSubsidiary(defaultSubsidiary)
                }
            } else {
                setRefSubsidiary(defaultSubsidiary)
            }
        } catch (e) {
            console.log(e)
            setServerError(t("An error has occurred. Please try again later."));
        }
    }

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

    const formProps = useForm<SubsidiaryFormInputs>();

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

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

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

    const onSubmit = useCallback<SubmitHandler<SubsidiaryFormInputs>>(
        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.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(refSubsidiary?.addContacts.map(contact => contact.id)!!, data.addContacts.map(contact => contact.id)!!)
                data.deleteCustomerIds = differenceBy(refSubsidiary?.addCustomerIds!!, data.addCustomerIds)

                setServerError("");

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

                    if (response.message === "Success") {
                        successDialog(t("Submit Success"), t).then(() => {
                            router.replace("/settings/subsidiary");
                        })
                    } 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, refSubsidiary],
    );

    const onSubmitError = useCallback<SubmitErrorHandler<SubsidiaryFormInputs>>(
        (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}>
            {refSubsidiary && <Stack
                spacing={2}
                component="form"
                onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
            >
                <Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable">
                    <Tab
                        label={t("Subsidiary Info")}
                        icon={
                            hasErrorsInTab(0, errors) ? (
                                <Error sx={{ marginInlineEnd: 1 }} color="error" />
                            ) : undefined
                        }
                        iconPosition="end"
                    />
                    <Tab label={t("Customer Allocation")} iconPosition="end" />
                </Tabs>
                {serverError && (
                    <Typography variant="body2" color="error" alignSelf="flex-end">
                        {serverError}
                    </Typography>
                )}
                {tabIndex === 0 && <SubsidiaryInfo subsidiaryTypes={subsidiaryTypes} />}
                {tabIndex === 1 && <CustomerAllocation customers={customers} />}

                <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("Confirm")}
                    </Button>
                </Stack>
            </Stack>}
        </FormProvider>
    );
};

export default SubsidiaryDetail;