"use client";
import { Recommendation } from "@/app/db/schema/recommendations";
import { Dispatch, Fragment, SetStateAction, useState } from "react";
import { Dialog, Transition } from "@headlessui/react";
import RecommendationTable from "@/app/components/building-passport/RecommendationTable";
import { RecommendationMetricMap } from "@/types/recommendations";
import { sumRecommendationMetricMap } from "@/app/portfolio/[slug]/building-passport/[propertyId]/plans/utils";
import uvalueColumns from "./RecommendationTableColumns";
import { sapToEpc } from "@/app/utils";

interface RecommendationModalProps {
  title: string;
  isOpen: boolean;
  setIsOpen: (isOpen: boolean) => void;
  recommendationData: Recommendation[];
  setCardComponent: Dispatch<SetStateAction<Recommendation>>;
  setCostMap: Dispatch<SetStateAction<RecommendationMetricMap>>;
  costMap: RecommendationMetricMap;
  setTotalEstimatedCost: Dispatch<SetStateAction<number>>;
  sapMap: RecommendationMetricMap;
  setSapMap: Dispatch<SetStateAction<RecommendationMetricMap>>;
  setTotalSapPoints: Dispatch<SetStateAction<number>>;
  currentSapPoints: number;
  setExpectedEpcRating: Dispatch<SetStateAction<string>>;
  setTotalLabourDays: Dispatch<SetStateAction<number>>;
  labourDaysMap: RecommendationMetricMap;
  setLabourDaysMap: Dispatch<SetStateAction<RecommendationMetricMap>>;
  setCo2SavingsMap: Dispatch<SetStateAction<RecommendationMetricMap>>;
  co2SavingsMap: RecommendationMetricMap;
  setTotalCo2Savings: Dispatch<SetStateAction<number>>;
  setEnergyCostSavingsMap: Dispatch<SetStateAction<RecommendationMetricMap>>;
  energyCostSavingsMap: RecommendationMetricMap;
  setTotalEnergyCostSavings: Dispatch<SetStateAction<number>>;
  setKwhSavingsMap: Dispatch<SetStateAction<RecommendationMetricMap>>;
  kwhSavingsMap: RecommendationMetricMap;
  setTotalKwhSavings: Dispatch<SetStateAction<number>>;
}

const TitleMap = {
  floor_insulation: "Floor Insulation",
  roof_insulation: "Roof Insulation",
  wall_insulation: "Wall Insulation",
  mechanical_ventilation: "Ventilation",
  sealing_open_fireplace: "Sealing Fireplaces",
  low_energy_lighting: "Low Energy Lighting",
  windows_glazing: "Window Glazing",
  solar_pv: "Solar PV Systems",
};

export default function RecommendationModal({
  title,
  isOpen = false,
  setIsOpen,
  recommendationData,
  setCardComponent,
  setCostMap,
  costMap,
  setTotalEstimatedCost,
  sapMap,
  setSapMap,
  setTotalSapPoints,
  currentSapPoints,
  setExpectedEpcRating,
  setTotalLabourDays,
  labourDaysMap,
  setLabourDaysMap,
  setCo2SavingsMap,
  co2SavingsMap,
  setTotalCo2Savings,
  setEnergyCostSavingsMap,
  energyCostSavingsMap,
  setTotalEnergyCostSavings,
  setKwhSavingsMap,
  kwhSavingsMap,
  setTotalKwhSavings,
}: RecommendationModalProps) {
  const [saveButtonDisabled, setSaveButtonDisabled] = useState(true);

  // Find the row where default is true
  const [defaultRowIndex, setDefaultRowIndex] = useState(
    recommendationData.findIndex((d) => d.default)
  );

  // Initialise the state with the default row index
  const [rowSelection, setRowSelection] = useState(
    defaultRowIndex !== -1 ? { [defaultRowIndex]: true } : {}
  );

  function closeModal() {
    setIsOpen(false);
    // If the user closes the modal, re-set the state of the row selection to the default, since nothing has changed
    setRowSelection({ [defaultRowIndex]: true });
  }

  function saveChanges() {
    // disable the button to prevent multiple clicks
    // TODO: Add a loading state to show we're saving
    setSaveButtonDisabled(true);
    setIsOpen(false);
    // Update the card component data
    const newIndex = parseInt(Object.keys(rowSelection)[0]);

    setCardComponent(recommendationData[newIndex]);
    // Set the default index
    setDefaultRowIndex(newIndex);
    // Update the cost map
    const newCostMap = {
      ...costMap,
      [title]: recommendationData[newIndex]?.estimatedCost || 0,
    };
    setCostMap(newCostMap);
    // update the cost sum
    setTotalEstimatedCost(sumRecommendationMetricMap(newCostMap));

    // Update the sap map
    const newSapMap = {
      ...sapMap,
      [title]: recommendationData[newIndex]?.sapPoints || 0,
    };
    setSapMap(newSapMap);

    // update the sap sum
    const newSapImprovement = sumRecommendationMetricMap(newSapMap);
    setTotalSapPoints(newSapImprovement);

    // TODO: While we have placeholder SAP points, constrain to 100
    const newSapPoints = Math.min(currentSapPoints + newSapImprovement, 100);

    // update the expected EPC rating
    setExpectedEpcRating(sapToEpc(newSapPoints));

    // Update the labour days map
    const newLabourDaysMap = {
      ...labourDaysMap,
      [title]: recommendationData[newIndex]?.labourDays || 0,
    };

    setLabourDaysMap(newLabourDaysMap);

    // update the labour days sum
    setTotalLabourDays(sumRecommendationMetricMap(newLabourDaysMap));

    // Update the co2 savings map
    const newCo2SavingsMap = {
      ...co2SavingsMap,
      [title]: recommendationData[newIndex]?.co2EquivalentSavings || 0,
    };

    setCo2SavingsMap(newCo2SavingsMap);

    // update the co2 savings sum
    setTotalCo2Savings(sumRecommendationMetricMap(newCo2SavingsMap));

    // Update the energy cost savings map
    const newEnergyCostSavingsMap = {
      ...energyCostSavingsMap,
      [title]: recommendationData[newIndex]?.energyCostSavings || 0,
    };

    setEnergyCostSavingsMap(newEnergyCostSavingsMap);

    // update the energy cost savings sum
    setTotalEnergyCostSavings(
      sumRecommendationMetricMap(newEnergyCostSavingsMap)
    );

    // Update the heat demand savings map
    const newKwhSavingsMap = {
      ...kwhSavingsMap,
      [title]: recommendationData[newIndex]?.kwhSavings || 0,
    };

    setKwhSavingsMap(newKwhSavingsMap);

    // update the heat demand savings sum
    setTotalKwhSavings(sumRecommendationMetricMap(newKwhSavingsMap));
  }

  return (
    <>
      <Transition appear show={isOpen} as={Fragment}>
        <Dialog as="div" className="relative z-10" onClose={closeModal}>
          <Transition.Child
            as={Fragment}
            enter="ease-out duration-300"
            enterFrom="opacity-0"
            enterTo="opacity-100"
            leave="ease-in duration-200"
            leaveFrom="opacity-100"
            leaveTo="opacity-0"
          >
            <div className="fixed inset-0 bg-black bg-opacity-25" />
          </Transition.Child>

          <div className="fixed inset-0 overflow-y-auto">
            <div className="flex min-h-full items-center justify-center p-4 text-center">
              <Transition.Child
                as={Fragment}
                enter="ease-out duration-300"
                enterFrom="opacity-0 scale-95"
                enterTo="opacity-100 scale-100"
                leave="ease-in duration-200"
                leaveFrom="opacity-100 scale-100"
                leaveTo="opacity-0 scale-95"
              >
                <Dialog.Panel className="w-full max-w-screen-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
                  <Dialog.Title
                    as="h3"
                    className="text-lg font-medium leading-6 text-brandblue mb-3"
                  >
                    {TitleMap[title as keyof typeof TitleMap]}
                  </Dialog.Title>
                  <RecommendationTable
                    data={recommendationData}
                    columns={uvalueColumns}
                    defaultRowIndex={defaultRowIndex}
                    rowSelection={rowSelection}
                    setRowSelection={setRowSelection}
                    setSaveButtonDisabled={setSaveButtonDisabled}
                  />
                  <div className="mt-4 flex justify-end gap-2">
                    <button
                      type="button"
                      className="inline-flex justify-center rounded-md border border-transparent hover:text-red-600 bg-gray-200 px-4 py-2 text-sm font-medium text-red-600 hover:bg-gray-300 focus:outline-none focus-visible:ring-2 focus-visible:none focus-visible:ring-offset-2"
                      onClick={() => {
                        setRowSelection({});
                      }}
                    >
                      Remove Recommendation
                    </button>
                    <button
                      type="button"
                      className="inline-flex justify-center rounded-md border border-transparent bg-blue-100 px-4 py-2 text-sm font-medium text-blue-900 hover:bg-blue-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"
                      onClick={closeModal}
                    >
                      Cancel
                    </button>

                    <button
                      type="button"
                      className="inline-flex justify-center rounded-md border border-transparent bg-brandblue px-4 py-2 text-sm font-medium text-gray-100 hover:bg-hoverblue focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-brandblue"
                      onClick={saveChanges}
                      disabled={saveButtonDisabled}
                    >
                      Save
                    </button>
                  </div>
                </Dialog.Panel>
              </Transition.Child>
            </div>
          </div>
        </Dialog>
      </Transition>
    </>
  );
}
