"use client";
import { usePermission } from "@/utils/auth/permission";
import { useParseError } from "@/utils/lib/helpers";
import { zodResolver } from "@hookform/resolvers/zod";
import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query";
import { FC, useEffect, useRef, useState, memo, useMemo, useCallback } from "react";
import { FormProvider, useForm } from "react-hook-form";
import { toast } from "react-toastify";
import ActionButton from "../action-button";
import DropdownList from "../common/Dropdown";
import MoneyFormat from "../common/money";
import {
  Datepicker,
  InputField,
  Radio,
  Select,
  Textarea,
} from "../forms/Inputs";
import {
  TSinvoicePaySchema,
} from "../forms/schema/invoice-pay";
import { Modal } from "flowbite-react";
import { MdPrint } from "react-icons/md";
import { twMerge } from "tailwind-merge";
import { TSclientSchema } from "../forms/schema/client";
import { bulkInvoicePaySchema, TSBulkInvoicePaySchema } from "../forms/schema/bulk-invoice-pay";
import { postData, putData } from "@/utils/fetch";
import { TSinvoiceSchema } from "../forms/schema/invoice";
import BulkInvoicePrint from "./bulk-invoice-print";
import InvoiceDiscount from "./invoice-discount";

type InvoiceDueItem = {
  after_discount_amount: number;
  discount: number;
  line_total_discount: number;
  uuid: string;
  invoice_type: string;
  amount_paid: number;
};

type Props = {
  isOpen?: boolean;
  setOpen?: (isOpen: boolean) => void;
  client?: TSclientSchema & { invoiceDue?: InvoiceDueItem[] }
};

const BulkInvoicePayModal: FC<Props> = memo(({ isOpen = false, setOpen = () => { }, client }) => {
  const queryClient = useQueryClient();
  const [status, setStatus] = useState("paid");
  const [showPrint, setShowPrint] = useState(false);
  const [checkedItems, setCheckedItems] = useState<Set<string>>(new Set());
  const [invoices, setInvoices] = useState<TSinvoiceSchema[]>([]);
  const hasInitialized = useRef(false);

  // Move usePermission hooks to top level (hooks must not be called inside JSX)
  const hasInvoiceShowPermission = usePermission("invoices.show");
  const hasInvoiceEditPermission = usePermission("invoices.edit");

  // Get invoiceDue from client object
  const invoiceDue = useMemo(() => client?.invoiceDue ?? [], [client?.invoiceDue]);

  // Initialize checked items only once when modal opens
  useEffect(() => {
    if (isOpen && !hasInitialized.current && invoiceDue.length > 0) {
      const invoiceUuids = invoiceDue.map(item => item.uuid);
      setCheckedItems(new Set(invoiceUuids));
      hasInitialized.current = true;
    }
    // Reset initialization flag when modal closes
    if (!isOpen) {
      hasInitialized.current = false;
    }
  }, [isOpen, invoiceDue]);

  // Memoize calculations to prevent unnecessary recalculations
  const totalDue = useMemo(() => {
    return invoiceDue
      .filter(item => checkedItems.has(item.uuid))
      .reduce((sum, item) => sum + item.after_discount_amount - item.amount_paid, 0);
  }, [invoiceDue, checkedItems]);

  const grandTotal = useMemo(() => {
    return invoiceDue
      .filter(item => checkedItems.has(item.uuid))
      .reduce((sum, item) => sum + item.total_amount, 0);
  }, [invoiceDue, checkedItems]);

  const totalPaid = useMemo(() => {
    return invoiceDue
      .filter(item => checkedItems.has(item.uuid))
      .reduce((sum, item) => sum + item.amount_paid, 0);
  }, [invoiceDue, checkedItems]);

  const totalDiscount = useMemo(() => {
    return invoiceDue
      .filter(item => checkedItems.has(item.uuid))
      .reduce((sum, item) => sum + item.discount + item.line_total_discount, 0);
  }, [invoiceDue, checkedItems]);

  const handleCheckboxChange = useCallback((uuid: string) => {
    setCheckedItems(prev => {
      const newSet = new Set(prev);
      if (newSet.has(uuid)) {
        newSet.delete(uuid);
      } else {
        newSet.add(uuid);
      }
      setValue("invoice_ids", Array.from(newSet));
      return newSet;
    });
  }, []);

  // Stable callback for modal close
  const handleClose = useCallback(() => {
    setOpen(false);
  }, [setOpen]);


  const zoneForm = useForm<TSBulkInvoicePaySchema>({
    resolver: zodResolver(bulkInvoicePaySchema),
    mode: "onChange",
    defaultValues: {
      fund_id: null,
      payment_date: new Date().toISOString().split('T')[0],
      status: "paid",
      partial_amount: null,
      confirmation_sms: null,
      note: null,
    },
  });

  const inputRef = useRef<HTMLInputElement>(null);

  const {
    handleSubmit,
    setValue,
    setError,
    formState: { errors },
  } = zoneForm;

  // Set invoice_ids in form when modal opens and checkedItems is initialized
  useEffect(() => {
    if (isOpen && checkedItems.size > 0) {
      setValue("invoice_ids", Array.from(checkedItems));
    }
  }, [isOpen, checkedItems, setValue]);

  const {
    mutate: submitInvoice,
    isPending,
  } = useMutation({
    mutationFn: async (invoiceData: TSinvoicePaySchema) => {
      const api_url = `/api/v1/invoices/bulk-pay`;
      const invoices = await postData(api_url, invoiceData);
      console.log(invoices);
      if (invoices?.errors?.length > 0 || invoices?.error) {
        throw invoices;
      }
      return invoices?.data ?? [];
    },
    onSuccess: (data) => {
      setInvoices(data);
      toast.success(`Invoice complete successfully!`);
      queryClient.invalidateQueries({ queryKey: ["invoices"] });
    },
    onError: (error: any) => {
      if (useParseError(error)) {
        toast.error(useParseError(error));
      } else {
        toast.error(
          "Unable to complete the request, please check all information is correct and try again"
        );
      }
    },
  });
  const onSubmit = async (data: TSinvoicePaySchema) => {
    delete data.id;
    console.log(data);
    //return;
    if (data.status === "partial" && data?.partial_amount <= 0) {
      setError("partial_amount", {
        type: "manual",
        message: "Amount must be grater then 0",
      });
      return;
    }
    submitInvoice(data);
  };

  const onError = async (data: any) => {
    console.log(data);
  };

  useEffect(() => {
    if (invoices.length > 0) {
      setShowPrint(true);
      setInvoices(invoices);
    }

  }, [invoices]);

  const [isShow, setShow] = useState(false);
  return (
    <>
      <Modal onClose={handleClose} show={isOpen}>
        <Modal.Header className="border-b border-gray-200 p-3 dark:border-gray-700">
          <div>
            <div className="flex">
              <div>Invoice pay</div>
              <div>
                {hasInvoiceShowPermission && showPrint && (
                  <>
                    <ActionButton
                      type="any"
                      color="white"
                      className="bg-white hover:!bg-gray-300 dark:bg-gray-800 dark:hover:!bg-gray-700 mr-1"
                      size={"xs"}
                      onClick={() => setShow(true)}
                    >
                      <MdPrint className="text-lg" />
                    </ActionButton>
                    <BulkInvoicePrint
                      invoices={invoices}
                      isShow={isShow}
                      setShow={setShow}
                    />
                  </>
                )}
              </div>
            </div>
            <div className="text-xs font-medium text-gray-500 w-full">
              <div className="flex gap-3 justify-around mt-1 w-full">
                <div className="flex"><div>Name :</div> {client?.name}</div>
                <div className="flex"><div>Phone :</div> {client?.phone}</div>
              </div>
            </div>

          </div>

        </Modal.Header>
        <Modal.Body className="p-4">
          <div>
            <div className=" bg-white">
              <div className=" border-b pb-2">
                {invoiceDue && invoiceDue.length > 0 && (
                  <div className="w-full">
                    <div className="space-y-2">
                      <div className="space-y-1">
                        {invoiceDue.map((item) => {
                          const isChecked = checkedItems.has(item.uuid);
                          return (
                            <div
                              key={item.uuid}
                              className={`flex justify-between gap-2 p-2 rounded border cursor-pointer transition-all ${isChecked
                                ? "bg-white border-gray-300"
                                : "bg-gray-100 border-gray-200 opacity-50"
                                }`}
                            >
                              <div className="flex items-center gap-2">
                                <input
                                  type="checkbox"
                                  checked={isChecked}
                                  onChange={() => handleCheckboxChange(item.uuid)}
                                  className="w-4 h-4 text-purple-600 rounded border-gray-300 focus:ring-purple-500"
                                />
                                <div className="text-sm font-medium line-clamp-1">{`${item.trackID} - ${item.invoice_type}`}</div>
                              </div>
                              <div className="text-xs flex gap-0.5 text-gray-900 items-center">
                                <div>
                                  <span className="hidden md:block lg:block">Discount:</span> <span className="block md:hidden lg:hidden">Disc:</span>
                                </div>
                                <MoneyFormat amount={item.discount + item.line_total_discount} className="w-full text-xs font-medium" icon={false} />
                              </div>
                              <div className="text-xs flex gap-0.5 text-gray-900 items-center">
                                <div>
                                  <span className="hidden md:block lg:block">Paid:</span> <span className="block md:hidden lg:hidden">Pd:</span>
                                </div>
                                <MoneyFormat amount={item?.amount_paid} className="w-full text-xs font-medium" icon={false} />
                              </div>
                              <div className={twMerge("flex justify-end items-center", !isChecked ? "line-through text-gray-400" : "")}>
                                <div className="flex gap-0.5 justify-end w-full text-gray-900">
                                  <div className="text-xs font-medium">
                                    <span className="hidden md:block lg:block">Amount:</span> <span className="block md:hidden lg:hidden">Amt:</span>
                                  </div>
                                  <MoneyFormat amount={item.total_amount} className="text-xs text-right font-medium w-full" icon={false} />
                                  {hasInvoiceEditPermission && (
                                    <div className="flex items-center ml-1">
                                      <InvoiceDiscount invoice={item} onDiscountUpdated={() => {
                                        queryClient.invalidateQueries({ queryKey: ['client-info', { clientId: client?.id }] });
                                      }} />
                                    </div>
                                  )}
                                </div>
                              </div>
                            </div>
                          );
                        })}
                      </div>
                      <div className="flex justify-end">
                        <div className="">
                          <div className="flex font-medium text-gray-900 justify-end gap-0.5 w-full">
                            <div className="flex justify-end gap-0.5">
                              <div className="text-sm text-nowrap">Total due: </div>{" "}
                              <MoneyFormat className="!w-full text-sm justify-end" amount={grandTotal} icon={false} />
                            </div>
                          </div>
                          <div className="flex font-medium text-green-600 justify-end text-sm gap-0.5">
                            <div className="flex justify-end gap-0.5">
                              <div className="text-sm">Paid: </div>{" "}
                              <MoneyFormat amount={totalPaid} className="w-full" icon={false} />
                            </div>
                          </div>
                          <div className="flex font-medium border-b border-gray-500 pb-1 text-green-600 justify-end text-sm gap-0.5">
                            <div className="flex justify-end gap-0.5">
                              <div className="text-sm">Discount: </div>{" "}
                              <MoneyFormat
                                amount={totalDiscount}
                                className="w-full"
                                icon={false}
                              />
                            </div>
                          </div>
                          <div className="flex justify-end font-medium text-red-600 mt-1 gap-0.5">
                            <hr />
                            <div className="flex justify-end gap-0.5">
                              <div className="text-sm"> Due:</div>
                              <MoneyFormat amount={totalDue} className="w-full text-right text-sm" icon={false} />
                            </div>
                          </div>
                        </div>
                      </div>

                    </div>
                  </div>
                )}
              </div>
              <FormProvider {...zoneForm}>
                <form onSubmit={handleSubmit(onSubmit, onError)} className="mt-3">
                  <div className="grid grid-cols-1 gap-6 sm:grid-cols-2">
                    <div className="left">
                      <div className="mt-1">
                        <label htmlFor="" className="block mb-2">
                          Payment Method (Fund)
                        </label>
                        <DropdownList
                          name="fund"
                          idName="fund_id"
                          getLabel={(method: any) => method?.name}
                          placeholder="Fund"
                          isMulti={false}
                        />
                      </div>
                      <div className="mt-1">
                        <Datepicker
                          name="payment_date"
                          labelText="Payment Date"
                        />
                      </div>
                    </div>
                    <div className="right">
                      <div className="mt-1">
                        <Select
                          defaultValue={status}
                          options={[
                            { value: "paid", label: "Paid" },
                            { value: "partial", label: "Partial Paid" },
                          ]}
                          labelText="Status"
                          name="status"
                          errors={errors}
                          onChange={(e) => setStatus(e.target.value)}
                        />
                      </div>
                      {status === "partial" && (
                        <div className="mt-1">
                          <InputField
                            labelText="Partial Amount paid"
                            name="partial_amount"
                            placeholder="Partial amount"
                            errors={errors}
                          />
                        </div>
                      )}
                      <div className="mt-8">
                        <Radio
                          groupLabel="Send SMS"
                          name="confirmation_sms"
                          options={[
                            { label: "Yes", value: 1 },
                            { label: "No", value: 0 },
                          ]}
                          defaultValue={1}
                          labelFlex={true}
                        />
                      </div>
                    </div>
                  </div>
                  <div className="mt-2">
                    <Textarea
                      labelText="Note"
                      name="note"
                      rows={2}
                      placeholder="Note"
                    />
                  </div>
                  <div className="grid grid-cols-1 gap-6 sm:grid-cols-1"></div>
                  <input className="opacity-0" type="submit" ref={inputRef} />
                </form>
              </FormProvider>
            </div>
          </div>

        </Modal.Body>
        <Modal.Footer className="flex justify-between">
          {hasInvoiceEditPermission && (
            <ActionButton
              isLoading={isPending}
              isDisabled={checkedItems.size === 0 || isPending}
              type="submit"
              onClick={() => inputRef.current?.click()}
            />
          )}
          <div>
            {hasInvoiceShowPermission && showPrint && (
              <>
                <ActionButton
                  type="any"
                  color="white"
                  className="bg-white hover:!bg-gray-300 dark:bg-gray-800 dark:hover:!bg-gray-700 mr-1"
                  size={"xs"}
                  onClick={() => setShow(true)}
                >
                  <MdPrint className="text-lg" />
                </ActionButton>
              </>
            )}
          </div>
        </Modal.Footer>
      </Modal>
    </>
  );
});

export default BulkInvoicePayModal;
