import React, { useContext, useEffect, useRef, useState } from "react";
import AuthenticatedLayout from "@/Layouts/AuthenticatedLayout";
import { FilterMatchMode } from "primereact/api";
import { DataTable } from "primereact/datatable";
import { Column } from "primereact/column";
import { InputText } from "primereact/inputtext";
import { Button } from "primereact/button";
import { Dialog } from "primereact/dialog";
import { Dropdown } from "primereact/dropdown";
import { classNames } from "primereact/utils";
import { useForm, Controller } from "react-hook-form";
import axios from "axios";
import { Toast } from "primereact/toast";
import { ConfirmPopup, confirmPopup } from "primereact/confirmpopup";
import { authUser } from "@/Components/AuthProvider";

const durationTypeOptions = [
    { label: "Monthly", value: "monthly" },
    { label: "Yearly", value: "yearly" },
];

export default function LoanType({ auth }) {
    const { permission } = useContext(authUser);
    const [status, setStatus] = useState("create");
    const [visible, setVisible] = useState(false);
    const [loanTypes, setLoanTypes] = useState([]);
    const [currentId, setid] = useState(null);
    const [loading, setLoading] = useState(false);
    const [totalRecords, setTotalRecords] = useState(0);
    const [lazyParams, setLazyParams] = useState({
        first: 0,
        rows: 10,
        page: 0,
        search: "",
    });
    const searchTimeout = useRef(null);
    const [filters, setFilters] = useState({
        global: { value: null, matchMode: FilterMatchMode.CONTAINS },
        name: { value: null, matchMode: FilterMatchMode.STARTS_WITH },
    });
    const [globalFilterValue, setGlobalFilterValue] = useState("");
    const defaultValues = {
        name: "",
        duration_type: "monthly",
        interest_rate: "",
        duration: "",
    };
    const toast = useRef(null);
    const {
        control,
        formState: { errors },
        handleSubmit,
        reset,
        setError,
    } = useForm({ defaultValues });

    const fetchLoanTypes = (params = lazyParams) => {
        setLoading(true);
        axios
            .get(route("loan-type.view"), {
                params: {
                    rows: params.rows,
                    page: params.page ?? Math.floor(params.first / params.rows),
                    search: params.search || "",
                },
            })
            .then((res) => {
                setLoanTypes(res.data.loanTypes || []);
                setTotalRecords(
                    res.data.totalRecords ??
                        (res.data.loanTypes ? res.data.loanTypes.length : 0)
                );
            })
            .catch(() => {
                setLoanTypes([]);
                setTotalRecords(0);
            })
            .finally(() => setLoading(false));
    };

    useEffect(() => {
        fetchLoanTypes();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    const onPage = (event) => {
        const params = {
            ...lazyParams,
            first: event.first,
            rows: event.rows,
            page: event.page,
        };
        setLazyParams(params);
        fetchLoanTypes(params);
    };

    const onGlobalFilterChange = (e) => {
        const value = e.target.value;
        let _filters = { ...filters };

        _filters["global"].value = value;
        setFilters(_filters);
        setGlobalFilterValue(value);

        if (searchTimeout.current) {
            clearTimeout(searchTimeout.current);
        }

        searchTimeout.current = setTimeout(() => {
            const params = {
                ...lazyParams,
                first: 0,
                page: 0,
                search: value,
            };
            setLazyParams(params);
            fetchLoanTypes(params);
        }, 400);
    };

    const renderHeader = () => {
        return (
            <div
                className={`w-100% flex ${
                    permission.includes("loan_type_create")
                        ? "justify-between"
                        : "justify-end"
                } `}
            >
                {permission.includes("loan_type_create") && (
                    <Button
                        type="button"
                        icon={<span className="pi pi-plus text-sm pr-1" />}
                        label="Add"
                        onClick={() => {
                            setVisible(true);
                            setStatus("create");
                            reset(defaultValues);
                        }}
                        className="p-button-success h-[41px]  text-[14px] "
                    />
                )}

                <span className="p-input-icon-left h-10 ">
                    <i className="pi pi-search" />
                    <InputText
                        className="h-[41px] w-48"
                        value={globalFilterValue}
                        onChange={onGlobalFilterChange}
                        placeholder="Search"
                    />
                </span>
            </div>
        );
    };
    const header = renderHeader();

    const footerContent = (
        <div className="flex justify-end">
            <Button
                label="Cancel"
                icon="pi pi-times"
                onClick={() => {
                    setVisible(false);
                    reset(defaultValues);
                }}
                className="p-button-text w-13 text-sm"
            />
            <Button
                label="Save"
                icon="pi pi-check"
                onClick={() =>
                    status === "create"
                        ? handleSubmit(onSubmit)()
                        : handleSubmit(HandelUpdate)()
                }
                className="p-button-text w-13 text-sm"
            />
        </div>
    );

    const getFormErrorMessage = (name) => {
        return (
            errors[name] && (
                <small className="p-error">{errors[name].message}</small>
            )
        );
    };

    const onSubmit = (data) => {
        axios
            .post(route("loan-type.store"), data)
            .then((response) => {
                toast.current.show({
                    severity: "success",
                    summary: response.data.success,
                    detail: "Data inserted",
                    life: 3000,
                    className: "custom-toast-class",
                });
                setVisible(false);
                reset(defaultValues);
                const params = { ...lazyParams, first: 0, page: 0 };
                setLazyParams(params);
                fetchLoanTypes(params);
            })
            .catch((error) => {
                let errors = error.response.data.errors;
                Object.keys(errors).forEach((field) => {
                    setError(field, {
                        type: "manual",
                        message: errors[field][0],
                    });
                });
            });
    };

    const handelEdit = (rowData) => {
        reset({
            name: rowData.name,
            duration_type: rowData.duration_type,
            interest_rate: rowData.interest_rate,
            duration: rowData.duration,
        });
        setid(rowData.id);
        setStatus("update");
        setVisible(true);
    };

    const handelDelete = (event) => {
        const id = event.currentTarget.getAttribute("data-id");
        confirmPopup({
            target: event.currentTarget,
            message: "Do you want to delete this record?",
            icon: "pi pi-info-circle",
            acceptClassName: "p-button-danger",
            accept() {
                axios
                    .delete(route("loan-type.destroy", id), {
                        params: {
                            rows: lazyParams.rows,
                            page: lazyParams.page,
                            search: lazyParams.search,
                        },
                    })
                    .then((response) => {
                        fetchLoanTypes(lazyParams);

                        toast.current.show({
                            severity: "info",
                            summary: "Confirmed",
                            detail: response.data.success,
                            life: 3000,
                        });
                    })
                    .catch((error) => {
                        toast.current.show({
                            severity: "warn",
                            summary: "Rejected",
                            detail: error.response?.data?.error,
                            life: 3000,
                        });
                    });
            },
            reject() {
                toast.current.show({
                    severity: "warn",
                    summary: "Rejected",
                    detail: "You have rejected",
                    life: 3000,
                });
            },
        });
    };

    const HandelUpdate = (data) => {
        axios
            .put(route("loan-type.update", currentId), data)
            .then((response) => {
                toast.current.show({
                    severity: "success",
                    summary: response.data.success,
                    detail: "Data updated",
                    life: 3000,
                    className: "custom-toast-class",
                });
                setVisible(false);
                reset(defaultValues);
                fetchLoanTypes(lazyParams);
            })
            .catch((error) => {
                let errors = error.response.data.errors;
                Object.keys(errors).forEach((field) => {
                    setError(field, {
                        type: "manual",
                        message: errors[field][0],
                    });
                });
            });
    };

    const durationTypeTemplate = (rowData) => {
        const label =
            durationTypeOptions.find(
                (opt) => opt.value === rowData.duration_type
            )?.label || "";
        return <span className="capitalize">{label}</span>;
    };

    const interestRateTemplate = (rowData) => {
        return <span>{Number(rowData.interest_rate).toFixed(2)}%</span>;
    };

    const durationTemplate = (rowData) => {
        const label =
            durationTypeOptions.find(
                (opt) => opt.value === rowData.duration_type
            )?.label || "";
        return (
            <span>
                {rowData.duration} {label ? label.toLowerCase() : ""}
            </span>
        );
    };

    return (
        <AuthenticatedLayout
            user={auth.user}
            header={
                <>
                    <h2 className="text-skin-header font-medium ">Loan Types</h2>{" "}
                    <p className="text-skin-sub-header font-semibold text-xs">
                        Home - Loan Types
                    </p>
                </>
            }
            headerButton={<></>}
        >
            <Toast ref={toast} />
            <div className="card">
                <DataTable
                    className="defulattable"
                    value={loanTypes}
                    paginator
                    lazy
                    loading={loading}
                    showGridlines
                    rows={lazyParams.rows}
                    first={lazyParams.first}
                    rowsPerPageOptions={[10, 20, 50]}
                    totalRecords={totalRecords}
                    onPage={onPage}
                    dataKey="id"
                    header={header}
                    filters={filters}
                    emptyMessage="No loan type found."
                >
                    <Column field="name" header="Loan Type" />
                    <Column
                        field="duration_type"
                        header="Duration Type"
                        body={durationTypeTemplate}
                    />
                    <Column
                        field="interest_rate"
                        header="Interest Rate"
                        body={interestRateTemplate}
                    />
                    <Column
                        field="duration"
                        header="Duration"
                        body={durationTemplate}
                    />

                    <Column
                        header="Action"
                        body={(rowData) => (
                            <>
                                <ConfirmPopup />
                                {permission.includes("loan_type_edit") && (
                                    <Button
                                        icon="pi pi-pencil"
                                        onClick={() => {
                                            handelEdit(rowData);
                                        }}
                                        className="p-button-rounded p-button-success mr-2 px-3 py-2  w-10 h-10 font-medium"
                                    />
                                )}
                                {permission.includes("loan_type_delete") && (
                                    <Button
                                        icon="pi pi-trash"
                                        data-id={rowData.id}
                                        onClick={handelDelete}
                                        className="p-button-rounded p-button-warning px-3 py-2  w-10 h-10  font-medium"
                                    />
                                )}
                            </>
                        )}
                        className="p-button-rounded p-button-success mr-2 px-3 py-2  w-10 h-10 font-medium"
                        bodyClassName="text-center"
                        style={{ minWidth: "14rem" }}
                    />
                </DataTable>
            </div>

            <Dialog
                header={() => (status == "create" ? "Create" : "Update")}
                visible={visible}
                style={{ width: "500px" }}
                onHide={() => {
                    setVisible(false);
                    reset(defaultValues);
                }}
                footer={footerContent}
            >
                <form className="p-fluid" method="POST">
                    <div className="field mt-5">
                        <label
                            htmlFor="name"
                            className={classNames({ "p-error": errors.name })}
                        >
                            Loan Type<span className="text-red-500">*</span>
                        </label>
                        <span className="p-float-label">
                            <Controller
                                name="name"
                                control={control}
                                rules={{ required: "Loan type is required." }}
                                render={({ field, fieldState }) => (
                                    <InputText
                                        id={field.name}
                                        {...field}
                                        className={
                                            classNames({
                                                "p-invalid": fieldState.invalid,
                                            }) + ` h-11 w-full block`
                                        }
                                        placeholder="Loan type name"
                                    />
                                )}
                            />
                        </span>
                        {getFormErrorMessage("name")}
                    </div>

                    <div className="field mt-5">
                        <label
                            htmlFor="duration_type"
                            className={classNames({
                                "p-error": errors.duration_type,
                            })}
                        >
                            Duration Type<span className="text-red-500">*</span>
                        </label>
                        <span className="p-float-label">
                            <Controller
                                name="duration_type"
                                control={control}
                                rules={{ required: "Duration type is required." }}
                                render={({ field, fieldState }) => (
                                    <Dropdown
                                        id={field.name}
                                        {...field}
                                        options={durationTypeOptions}
                                        optionLabel="label"
                                        optionValue="value"
                                        placeholder="Select duration type"
                                        className={
                                            classNames({
                                                "p-invalid": fieldState.invalid,
                                            }) + ` w-full`
                                        }
                                    />
                                )}
                            />
                        </span>
                        {getFormErrorMessage("duration_type")}
                    </div>

                    <div className="field mt-5">
                        <label
                            htmlFor="interest_rate"
                            className={classNames({
                                "p-error": errors.interest_rate,
                            })}
                        >
                            Interest Rate (%)
                            <span className="text-red-500">*</span>
                        </label>
                        <span className="p-float-label">
                            <Controller
                                name="interest_rate"
                                control={control}
                                rules={{
                                    required: "Interest rate is required.",
                                    min: { value: 0, message: "Must be positive." },
                                }}
                                render={({ field, fieldState }) => (
                                    <InputText
                                        id={field.name}
                                        {...field}
                                        type="number"
                                        step="0.01"
                                        className={
                                            classNames({
                                                "p-invalid": fieldState.invalid,
                                            }) + ` h-11 w-full block`
                                        }
                                        placeholder="Interest rate (%)"
                                    />
                                )}
                            />
                        </span>
                        {getFormErrorMessage("interest_rate")}
                    </div>

                    <div className="field mt-5">
                        <label
                            htmlFor="duration"
                            className={classNames({
                                "p-error": errors.duration,
                            })}
                        >
                            Duration Value<span className="text-red-500">*</span>
                        </label>
                        <span className="p-float-label">
                            <Controller
                                name="duration"
                                control={control}
                                rules={{
                                    required: "Duration is required.",
                                    min: { value: 1, message: "Minimum 1." },
                                }}
                                render={({ field, fieldState }) => (
                                    <InputText
                                        id={field.name}
                                        {...field}
                                        type="number"
                                        className={
                                            classNames({
                                                "p-invalid": fieldState.invalid,
                                            }) + ` h-11 w-full block`
                                        }
                                        placeholder="Duration (months/years)"
                                    />
                                )}
                            />
                        </span>
                        {getFormErrorMessage("duration")}
                    </div>
                </form>
            </Dialog>
        </AuthenticatedLayout>
    );
}
