import React, { useEffect, useMemo, useState } from "react";
import { useProjectName } from "../../hooks/useProjects";
import Label from "../common/Label";
import { Controller, useForm } from "react-hook-form";
import {
  useCurrencies,
  useExpenseCategory,
} from "../../hooks/masterHook/useMaster";
import DatePicker from "../common/DatePicker";
import {
  useCreatePaymentRequest,
  usePayee,
  usePaymentRequestDetail,
  useUpdatePaymentRequest,
} from "../../hooks/useExpense";

import { zodResolver } from "@hookform/resolvers/zod";
import { formatFileSize, localToUtc } from "../../utils/appUtils";
import {
  defaultPaymentRequest,
  PaymentRequestSchema,
} from "./PaymentRequestSchema";
import {
  EXPENSE_DRAFT,
  EXPENSE_STATUS,
  INR_CURRENCY_CODE,
} from "../../utils/constants";
import Filelist from "../Expenses/Filelist";
import InputSuggestions from "../common/InputSuggestion";
import { useProfile } from "../../hooks/useProfile";
import { blockUI } from "../../utils/blockUI";
import { SelectProjectField } from "../common/Forms/SelectFieldServerSide";

function ManagePaymentRequest({ closeModal, requestToEdit = null }) {
  const {
    data,
    isLoading,
    isError,
    error: requestError,
  } = usePaymentRequestDetail(requestToEdit);

  const { profile } = useProfile();
  const {
    projectNames,
    loading: projectLoading,
    error,
    isError: isProjectError,
  } = useProjectName();

  const {
    data: currencyData,
    isLoading: currencyLoading,
    isError: currencyError,
  } = useCurrencies();

  const {
    expenseCategories,
    loading: ExpenseLoading,
    error: ExpenseError,
  } = useExpenseCategory();

  const {
    data: Payees,
    isLoading: isPayeeLoaing,
    isError: isPayeeError,
    error: payeeError,
  } = usePayee();
  const schema = PaymentRequestSchema(expenseCategories);
  const {
    register,
    control,
    watch,
    handleSubmit,
    setValue,
    reset,
    formState: { errors },
  } = useForm({
    resolver: zodResolver(schema),
    defaultValues: defaultPaymentRequest,
  });

  const [isItself, setisItself] = useState(false);
  const isDraft = useMemo(() => {
    if (!data) return false;
    return EXPENSE_STATUS.daft === data?.expenseStatus.id;
  }, [data]);
  const isProcessed = useMemo(() => {
    if (!data) return false;
    return EXPENSE_STATUS.payment_processed === data?.expenseStatus.id;
  }, [data]);
  const files = watch("billAttachments");
  const onFileChange = async (e) => {
    const newFiles = Array.from(e.target.files);
    if (newFiles?.length === 0) return;

    const existingFiles = watch("billAttachments") || [];

    const parsedFiles = await Promise.all(
      newFiles?.map(async (file) => {
        const base64Data = await toBase64(file);
        return {
          fileName: file.name,
          base64Data,
          contentType: file.type,
          fileSize: file.size,
          description: "",
          isActive: true,
        };
      })
    );

    const combinedFiles = [
      ...existingFiles,
      ...parsedFiles.filter(
        (newFile) =>
          !existingFiles.some(
            (f) =>
              f.fileName === newFile.fileName && f.fileSize === newFile.fileSize
          )
      ),
    ];

    setValue("billAttachments", combinedFiles, {
      shouldDirty: true,
      shouldValidate: true,
    });
  };

  const toBase64 = (file) =>
    new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = () => resolve(reader.result.split(",")[1]);
      reader.onerror = (error) => reject(error);
    });
  const removeFile = (index) => {
    if (requestToEdit) {
      const newFiles = files.map((file, i) => {
        if (file.documentId !== index) return file;
        return {
          ...file,
          isActive: false,
        };
      });
      setValue("billAttachments", newFiles, { shouldValidate: true });
    } else {
      const newFiles = files.filter((_, i) => i !== index);
      setValue("billAttachments", newFiles, { shouldValidate: true });
    }
  };

  const handleClose = () => {
    reset();
    closeModal();
  };

  const { mutate: CreatePaymentRequest, isPending: createPending } =
    useCreatePaymentRequest(() => {
      handleClose();
    });
  const { mutate: PaymentRequestUpdate, isPending } = useUpdatePaymentRequest(
    () => handleClose()
  );

  useEffect(() => {
    if (requestToEdit && data) {
      reset({
        title: data.title || "",
        description: data.description || "",
        payee: data.payee || "",
        currencyId: data.currency.id || "",
        amount: data.amount || "",
        dueDate: data.dueDate?.slice(0, 10) || "",
        projectId: data.project.id || "",
        expenseCategoryId: data.expenseCategory.id || "",
        isAdvancePayment: data.isAdvancePayment || false,
        billAttachments: data.attachments
          ? data?.attachments?.map((doc) => ({
              fileName: doc.fileName,
              base64Data: null,
              contentType: doc.contentType,
              documentId: doc.id,
              fileSize: 0,
              description: "",
              preSignedUrl: doc.preSignedUrl,
              isActive: doc.isActive ?? true,
            }))
          : [],
      });
    }
  }, [data, reset]);

  useEffect(() => {
    if (!requestToEdit && currencyData && currencyData?.length > 0) {
      const inrCurrency = currencyData.find((c) => c.id === INR_CURRENCY_CODE);
      if (inrCurrency) {
        setValue("currencyId", INR_CURRENCY_CODE, { shouldValidate: true });
      }
    }
  }, [currencyData, requestToEdit, setValue]);

  const onSubmit = (fromdata) => {
    let payload = {
      ...fromdata,
      dueDate: localToUtc(fromdata.dueDate),
      payee: isItself
        ? `${profile?.employeeInfo?.firstName}  ${profile?.employeeInfo?.lastName}`
        : fromdata.payee,
    };
    if (requestToEdit) {
      const editPayload = {
        ...payload,
        id: data.id,
        payee: isItself
          ? `${profile?.employeeInfo?.firstName}  ${profile?.employeeInfo?.lastName}`
          : fromdata.payee,
      };
      PaymentRequestUpdate({ id: data.id, payload: editPayload });
    } else {
      CreatePaymentRequest(payload);
    }
  };
  const handleSetItSelf = (e) => {
    setisItself(e.target.value);
    let name = `${profile?.employeeInfo.firstName} ${profile?.employeeInfo.lastName}`;

    setValue("payee", name);
  };
  return (
    <div className="container p-3 ">
      <h5 className="m-0">
        {requestToEdit ? "Update Payment Request " : "Create Payment Request"}
      </h5>
      <form id="expenseForm" onSubmit={handleSubmit(onSubmit)}>
        {/* Project and Category */}
        <div className="row my-2 text-start">
          <div className="col-md-6">
            {/* <Label className="form-label" required>
              Select Project
            </Label> */}
            {/* <select
              className="form-select form-select-sm"
              {...register("projectId")}
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            >
              <option value="">Select Project</option>
              {projectLoading ? (
                <option>Loading...</option>
              ) : (
                projectNames?.map((project) => (
                  <option key={project.id} value={project.id}>
                    {project.name}
                  </option>
                ))
              )}
            </select> */}
            <SelectProjectField
              label="Project"
              required
              placeholder="Select Project"
              value={watch("projectId")}
              onChange={(val) =>
                setValue("projectId", val, {
                  shouldDirty: true,
                  shouldValidate: true,
                })
                
              }
                disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            />
            {errors.projectId && (
              <small className="danger-text">{errors.projectId.message}</small>
            )}
          </div>

          <div className="col-md-6">
            <Label htmlFor="expenseCategoryId" className="form-label" required>
              Expense Category
            </Label>
            <select
              className="form-select form-select-sm"
              id="expenseCategoryId"
              {...register("expenseCategoryId")}
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            >
              <option value="" disabled>
                Select Category
              </option>
              {ExpenseLoading ? (
                <option disabled>Loading...</option>
              ) : (
                expenseCategories?.map((expense) => (
                  <option key={expense.id} value={expense.id}>
                    {expense.name}
                  </option>
                ))
              )}
            </select>
            {errors.expenseCategoryId && (
              <small className="danger-text">
                {errors.expenseCategoryId.message}
              </small>
            )}
          </div>
        </div>

        {/* Title and Advance Payment  */}
        <div className="row my-2 text-start">
          <div className="col-md-6">
            <Label htmlFor="title" className="form-label" required>
              Title
            </Label>
            <input
              type="text"
              id="title"
              className="form-control form-control-sm"
              {...register("title")}
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            />
            {errors.title && (
              <small className="danger-text">{errors.title.message}</small>
            )}
          </div>

          <div className="col-md-6 ">
            <Label htmlFor="isAdvance" className="form-label">
              Is Advance Payment
            </Label>

            <Controller
              name="isAdvancePayment"
              control={control}
              defaultValue={defaultPaymentRequest.isAdvancePayment ?? false}
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
              render={({ field }) => (
                <div className="d-flex align-items-center gap-3">
                  <div className="form-check d-flex flex-row m-0 gap-2">
                    <input
                      type="radio"
                      id="isAdvancePayment"
                      className="form-check-input m-0"
                      // mark checked when the controlled value is true
                      checked={field.value === true}
                      onChange={() => field.onChange(true)} // send boolean true
                    />
                    <Label className="form-check-label">Yes</Label>
                  </div>

                  <div className="form-check d-flex flex-row m-0 gap-2">
                    <input
                      type="radio"
                      id="isVariableFalse"
                      className="form-check-input m-0"
                      checked={field.value === false}
                      onChange={() => field.onChange(false)} // send boolean false
                    />
                    <Label className="form-check-label">No</Label>
                  </div>
                </div>
              )}
            />

            {errors.isVariable && (
              <small className="danger-text">{errors.isVariable.message}</small>
            )}
          </div>
        </div>

        {/* Date and Amount */}
        <div className="row my-2 text-start">
          <div className="col-md-6">
            <Label htmlFor="dueDate" className="form-label" required>
              Due Date
            </Label>
            <DatePicker
              name="dueDate"
              control={control}
              minDate={new Date()}
              className="w-100"
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            />

            {errors.dueDate && (
              <small className="danger-text">{errors.dueDate.message}</small>
            )}
          </div>

          <div className="col-md-6">
            <Label htmlFor="amount" className="form-label" required>
              Amount
            </Label>
            <input
              type="number"
              id="amount"
              className="form-control form-control-sm"
              min="1"
              step="0.01"
              inputMode="decimal"
              {...register("amount", { valueAsNumber: true })}
            />
            {errors.amount && (
              <small className="danger-text">{errors.amount.message}</small>
            )}
          </div>
        </div>

        {/* Payee and Currency  */}
        <div className="row my-2 text-start">
          <div className="col-md-6">
            <Label htmlFor="payee" className="form-label" required>
              Payee (Supplier Name/Transporter Name/Other)
            </Label>
            <InputSuggestions
              organizationList={Payees}
              value={watch("payee") || ""}
              onChange={(val) =>
                setValue("payee", val, { shouldValidate: true })
              }
              error={errors.payee?.message}
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            />

            {/* Checkbox below input */}
            <div className="form-check mt-2">
              <input
                type="checkbox"
                id="sameAsSupplier"
                className="form-check-input"
                value={isItself}
                onChange={handleSetItSelf}
                disabled={
                  data?.recurringPayment?.isVariable && !isDraft && !isProcessed
                }
              />
              <Label htmlFor="sameAsSupplier" className="form-check-label">
                It self
              </Label>
            </div>
          </div>

          <div className="col-md-6">
            <Label htmlFor="currencyId" className="form-label" required>
              Currency
            </Label>
            <select
              id="currencyId"
              className="form-select form-select-sm"
              {...register("currencyId")}
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            >
              <option value="">Select Currency</option>

              {currencyLoading && <option>Loading...</option>}

              {!currencyLoading &&
                !currencyError &&
                currencyData?.map((currency) => (
                  <option key={currency.id} value={currency.id}>
                    {`${currency.currencyName} (${currency.symbol})`}
                  </option>
                ))}
            </select>
            {errors.currencyId && (
              <small className="danger-text">{errors.currencyId.message}</small>
            )}
          </div>
        </div>

        {/* Description  */}
        <div className="row my-2 text-start">
          <div className="col-md-12">
            <Label htmlFor="description" className="form-label" required>
              Description
            </Label>
            <textarea
              id="description"
              className="form-control form-control-sm"
              {...register("description")}
              rows="2"
              disabled={
                data?.recurringPayment?.isVariable && !isDraft && !isProcessed
              }
            ></textarea>
            {errors.description && (
              <small className="danger-text">
                {errors.description.message}
              </small>
            )}
          </div>
        </div>

        {/* Upload Document  */}
        <div className="row my-2 text-start">
          <div className="col-md-12">
            <Label className="form-label">Upload Bill </Label>

            <div
              className="border border-secondary border-dashed rounded p-4 text-center bg-textMuted position-relative"
              style={{ cursor: "pointer" }}
              onClick={() => document.getElementById("billAttachments").click()}
            >
              <i className="bx bx-cloud-upload d-block bx-lg"> </i>
              <span className="text-muted d-block">
                Click to select or click here to browse
              </span>
              <small className="text-muted">(PDF, JPG, PNG, max 5MB)</small>

              <input
                type="file"
                id="billAttachments"
                accept=".pdf,.jpg,.jpeg,.png"
                multiple
                style={{ display: "none" }}
                {...register("billAttachments")}
                onChange={(e) => {
                  onFileChange(e);
                  e.target.value = "";
                }}
                disabled={
                  data?.recurringPayment?.isVariable && !isDraft && !isProcessed
                }
              />
            </div>
            {errors.billAttachments && (
              <small className="danger-text">
                {errors.billAttachments.message}
              </small>
            )}
            {files?.length > 0 && (
              <Filelist
                files={files}
                removeFile={removeFile}
                expenseToEdit={requestToEdit}
              />
            )}

            {Array.isArray(errors.billAttachments) &&
              errors.billAttachments.map((fileError, index) => (
                <div key={index} className="danger-text small mt-1">
                  {
                    (fileError?.fileSize?.message ||
                      fileError?.contentType?.message ||
                      fileError?.base64Data?.message,
                    fileError?.documentId?.message)
                  }
                </div>
              ))}
          </div>
        </div>
        <div className="d-flex justify-content-end gap-3">
          <button
            type="reset"
            disabled={createPending || isPending}
            onClick={handleClose}
            className="btn btn-label-secondary btn-sm mt-3"
          >
            Cancel
          </button>
          <button
            type="submit"
            className="btn btn-primary btn-sm mt-3"
            disabled={createPending || isPending}
          >
            {createPending || isPending
              ? "Please Wait..."
              : requestToEdit
              ? "Update"
              : "Save as Draft"}
          </button>
        </div>
      </form>
    </div>
  );
}

export default ManagePaymentRequest;
