import { zodResolver } from "@hookform/resolvers/zod";
import React, { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { defaultExpense, ExpenseSchema } from "./ExpenseSchema";
import { formatFileSize } from "../../utils/appUtils";
import { useProjectName } from "../../hooks/useProjects";
import { useDispatch, useSelector } from "react-redux";
import { changeMaster } from "../../slices/localVariablesSlice";
import useMaster, {
  useExpenseStatus,
  useExpenseType,
  usePaymentMode,
} from "../../hooks/masterHook/useMaster";
import {
  useEmployeesAllOrByProjectId,
  useEmployeesByProject,
} from "../../hooks/useEmployees";
import Avatar from "../common/Avatar";
import {
  useCreateExpnse,
  useExpense,
  useUpdateExpense,
} from "../../hooks/useExpense";
import ExpenseSkeleton from "./ExpenseSkeleton";

const ManageExpense = ({ closeModal, expenseToEdit = null }) => {
  const {
    data,
    isLoading,
    error: ExpenseErrorLoad,
  } = useExpense(expenseToEdit);
  const [ExpenseType, setExpenseType] = useState();
  const dispatch = useDispatch();
  const {
    ExpenseTypes,
    loading: ExpenseLoading,
    error: ExpenseError,
  } = useExpenseType();
  const schema = ExpenseSchema(ExpenseTypes);
  const {
    register,
    handleSubmit,
    watch,
    setValue,
    reset,
    formState: { errors },
  } = useForm({
    resolver: zodResolver(schema),
    defaultValues: defaultExpense,
  });

  const selectedproject = watch("projectId");
  const selectedProject = useSelector(
    (store) => store.localVariables.projectId
  );
  const { projectNames, loading: projectLoading, error } = useProjectName();

  const {
    PaymentModes,
    loading: PaymentModeLoading,
    error: PaymentModeError,
  } = usePaymentMode();
  const {
    ExpenseStatus,
    loading: StatusLoadding,
    error: stausError,
  } = useExpenseStatus();
  const {
    employees,
    loading: EmpLoading,
    error: EmpError,
  } = useEmployeesByProject(selectedproject);

  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 (expenseToEdit) {
      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 });
    }
  };

  useEffect(() => {
    if (expenseToEdit && data) {
      reset({
        projectId: data.project.id || "",
        expensesTypeId: data.expensesType.id || "",
        paymentModeId: data.paymentMode.id || "",
        paidById: data.paidBy.id || "",
        transactionDate: data.transactionDate?.slice(0, 10) || "",
        transactionId: data.transactionId || "",
        description: data.description || "",
        location: data.location || "",
        supplerName: data.supplerName || "",
        amount: data.amount || "",
        noOfPersons: data.noOfPersons || "",
        billAttachments: data.documents
          ? data.documents.map((doc) => ({
              fileName: doc.fileName,
              base64Data: null,
              contentType: doc.contentType,
              documentId: doc.documentId,
              fileSize: 0,
              description: "",
              preSignedUrl: doc.preSignedUrl,
              isActive: doc.isActive ?? true,
            }))
          : [],
      });
    }
  }, [data, reset, employees]);
  const { mutate: ExpenseUpdate, isPending } = useUpdateExpense(() =>
    handleClose()
  );
  const { mutate: CreateExpense, isPending: createPending } = useCreateExpnse(
    () => {
      handleClose();
    }
  );
  const onSubmit = (payload) => {
    if (expenseToEdit) {
      const editPayload = { ...payload, id: data.id };
      ExpenseUpdate({ id: data.id, payload: editPayload });
    } else {
      CreateExpense(payload);
    }
  };
  const ExpenseTypeId = watch("expensesTypeId");

  useEffect(() => {
    setExpenseType(ExpenseTypes?.find((type) => type.id === ExpenseTypeId));
    return () => reset(defaultExpense);
  }, [ExpenseTypeId]);

  const handleClose = () => {
    reset();
    closeModal();
  };
  if (
    StatusLoadding ||
    projectLoading ||
    ExpenseLoading ||
    isLoading
  )
    return <ExpenseSkeleton />;

  return (
    <div className="container p-3">
      <h5 className="m-0">
        {expenseToEdit ? "Update Expense " : "Create New Expense"}
      </h5>
      <form id="expenseForm" onSubmit={handleSubmit(onSubmit)}>
        <div className="row my-2">
          <div className="col-md-6">
            <label htmlFor="projectId" className="form-label">
              Select Project
            </label>
            <select
              className="form-select form-select-sm"
              {...register("projectId")}
            >
              <option value="">Select Project</option>
              {projectLoading ? (
                <option>Loading...</option>
              ) : (
                projectNames?.map((project) => (
                  <option key={project.id} value={project.id}>
                    {project.name}
                  </option>
                ))
              )}
            </select>
            {errors.projectId && (
              <small className="danger-text">{errors.projectId.message}</small>
            )}
          </div>

          <div className="col-md-6">
            <label for="expensesTypeId" className="form-label ">
              Expense Type
            </label>
            <select
              className="form-select form-select-sm"
              id="expensesTypeId"
              {...register("expensesTypeId")}
            >
              <option value="" disabled>
                Select Type
              </option>
              {ExpenseLoading ? (
                <option disabled>Loading...</option>
              ) : (
                ExpenseTypes?.map((expense) => (
                  <option key={expense.id} value={expense.id}>
                    {expense.name}
                  </option>
                ))
              )}
            </select>
            {errors.expensesTypeId && (
              <small className="danger-text">
                {errors.expensesTypeId.message}
              </small>
            )}
          </div>
        </div>

        <div className="row my-2">
          <div className="col-md-6">
            <label for="paymentModeId" className="form-label ">
              Payment Mode
            </label>
            <select
              className="form-select form-select-sm"
              id="paymentModeId"
              {...register("paymentModeId")}
            >
              <option value="" disabled>
                Select Mode
              </option>
              {PaymentModeLoading ? (
                <option disabled>Loading...</option>
              ) : (
                PaymentModes?.map((payment) => (
                  <option key={payment.id} value={payment.id}>
                    {payment.name}
                  </option>
                ))
              )}
            </select>
            {errors.paymentModeId && (
              <small className="danger-text">
                {errors.paymentModeId.message}
              </small>
            )}
          </div>

          <div className="col-md-6">
            <label for="paidById" className="form-label ">
              Paid By
            </label>
            <select
              className="form-select form-select-sm"
              id="paymentModeId"
              {...register("paidById")}
              disabled={!selectedproject}
            >
              <option value="" disabled>
                Select Person
              </option>
              {EmpLoading ? (
                <option disabled>Loading...</option>
              ) : (
                employees?.map((emp) => (
                  <option key={emp.id} value={emp.id}>
                    {`${emp.firstName} ${emp.lastName} `}
                  </option>
                ))
              )}
            </select>
            {errors.paidById && (
              <small className="danger-text">{errors.paidById.message}</small>
            )}
          </div>
        </div>

        <div className="row my-2">
          <div className="col-md-6">
            <label for="transactionDate" className="form-label ">
              Transaction Date
            </label>
            <input
              type="date"
              className="form-control form-control-sm"
              placeholder="YYYY-MM-DD"
              id="flatpickr-date"
              {...register("transactionDate")}
            />
            {errors.transactionDate && (
              <small className="danger-text">
                {errors.transactionDate.message}
              </small>
            )}
          </div>

          <div className="col-md-6">
            <label for="amount" className="form-label ">
              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>

        <div class="row my-2">
          <div className="col-md-6">
            <label for="supplerName" className="form-label ">
              Supplier Name
            </label>
            <input
              type="text"
              id="supplerName"
              className="form-control form-control-sm"
              {...register("supplerName")}
            />
            {errors.supplerName && (
              <small className="danger-text">
                {errors.supplerName.message}
              </small>
            )}
          </div>

          <div className="col-md-6">
            <label for="location" className="form-label ">
              Location
            </label>
            <input
              type="text"
              id="location"
              className="form-control form-control-sm"
              {...register("location")}
            />
            {errors.location && (
              <small className="danger-text">{errors.location.message}</small>
            )}
          </div>
        </div>
        <div className="row my-2">
          <div className="col-md-6">
            <label for="statusId" className="form-label ">
              TransactionId
            </label>
            <input
              type="text"
              id="transactionId"
              className="form-control form-control-sm"
              min="1"
              {...register("transactionId")}
            />
            {errors.transactionId && (
              <small className="danger-text">
                {errors.transactionId.message}
              </small>
            )}
          </div>

          {ExpenseType?.noOfPersonsRequired && (
            <div className="col-md-6">
              <label htmlFor="noOfPersons" >
                No. of Persons
              </label>
              <input
                type="number"
                id="noOfPersons"
                className="form-control form-control-sm"
                {...register("noOfPersons")}
                inputMode="numeric"
              />
              {errors.noOfPersons && (
                <small className="danger-text">
                  {errors.noOfPersons.message}
                </small>
              )}
            </div>
          )}
        </div>

        <div className="row my-2">
          <div className="col-md-12" >
            <label for="description">Description</label>
            <textarea
              id="description"
              className="form-control form-control-sm"
              {...register("description")}
              rows="2"
            ></textarea>
            {errors.description && (
              <small className="danger-text">
                {errors.description.message}
              </small>
            )}
          </div>
        </div>

        <div className="row my-2">
          <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 = "";
                }}
              />
            </div>
            {errors.billAttachments && (
              <small className="danger-text">
                {errors.billAttachments.message}
              </small>
            )}
            {files.length > 0 && (
              <div className="d-block">
                {files
                  .filter((file) => {
                    if (expenseToEdit) {
                      return file.isActive; 
                    }
                    return true;
                  })
                  .map((file, idx) => (
                    <a
                      key={idx}
                      className="d-flex justify-content-between text-start p-1"
                      href={file.preSignedUrl || "#"}
                      target="_blank"
                      rel="noopener noreferrer"
                    >
                      <div>
                        <span className="mb-0 text-secondary small d-block">
                          {file.fileName}
                        </span>
                        <span className="text-body-secondary small d-block">
                          {file.fileSize ? formatFileSize(file.fileSize) : ""}
                        </span>
                      </div>
                      <i
                        className="bx bx-trash bx-sm cursor-pointer text-danger"
                        onClick={(e) => {
                          e.preventDefault();
                          removeFile(expenseToEdit ? file.documentId : idx);
                        }}
                      ></i>
                    </a>
                  ))}
              </div>
            )}

            {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-center gap-2">
          {" "}
          <button
            type="submit"
            className="btn btn-primary btn-sm mt-3"
            disabled={isPending}
          >
            {isPending || createPending ? "Please Wait..." : expenseToEdit ? "Update" : "Submit"}
          </button>
          <button
            type="reset"
            disabled={isPending || createPending}
            onClick={handleClose}
            className="btn btn-secondary btn-sm mt-3"
          >
            Cancel
          </button>
        </div>
      </form>
    </div>
  );
};

export default ManageExpense;
