/*
 * RELOG: Supply Chain Analysis and Optimization
 * Copyright (C) 2020-2025, UChicago Argonne, LLC. All rights reserved.
 * Released under the modified BSD license. See COPYING.md for more details.
 */

import Header from "./Header";

import "tabulator-tables/dist/css/tabulator.min.css";
import "../Common/Forms/Tables.css";
import Footer from "./Footer";
import React, { useState, useRef } from "react";
import { defaultPlant, defaultProduct, defaultCenter } from "./defaults";
import PipelineBlock from "./PipelineBlock";
import "@xyflow/react/dist/style.css";
import {
  PlantNode,
  CenterNode,
  ProductNode,
  RELOGScenario,
} from "./InitialData";
import { idText } from "typescript";

declare global {
  interface Window {
    nextX: number;
    nextY: number;
  }
}

const Default_Scenario: RELOGScenario = {
  Parameters: { version: "1.0" },
  Plants: {},
  Products: {},
  Centers: {},
};

const CaseBuilder = () => {
  const nextUid = useRef(1);
  const [scenario, setScenario] = useState<RELOGScenario>(Default_Scenario);

  const onClear = () => {};
  const onSave = () => {};
  const onLoad = () => {};

  const nextNodePosition = (): [number, number] => {
    if (window.nextX === undefined) window.nextX = 15;
    if (window.nextY === undefined) window.nextY = 15;

    window.nextY += 60;
    if (window.nextY >= 500) {
      window.nextY = 15;
      window.nextX += 150;
    }
    return [window.nextX, window.nextY];
  };

  const promptName = (): string | undefined => {
    const name = prompt("Name");
    if (!name || name.length === 0) return;
    return name;
  };

  type EntityKey = "Plants" | "Products" | "Centers";

  const onAddNode = (type: EntityKey) => {
    setScenario((prevData) => {
      const name = promptName();
      if (!name) return prevData;

      const uid = `${name}-$${nextUid.current++}`;
      const [x, y] = nextNodePosition();

      let newNode;
      if (type === "Plants") {
        newNode = { ...defaultPlant, uid, name, x, y };
      } else if (type === "Products") {
        newNode = { ...defaultProduct, uid, name, x, y };
      } else {
        newNode = { ...defaultCenter, uid, name, x, y };
      }
      return {
        ...prevData,
        [type]: {
          ...prevData[type],
          [uid]: newNode,
        },
      } as RELOGScenario;
    });
  };

  const onSetCenterInput = (centerName: string, productName: string) => {
    setScenario((prev) => {
      const center = prev.Centers[centerName];
      if (!center) return prev;
      return {
        ...prev,
        Centers: {
          ...prev.Centers,
          [centerName]: { ...center, input: productName },
        },
      };
    });
  };

  const onSetPlantInput = (plantName: string, productName: string) => {
    setScenario((prevData: RELOGScenario) => {
      const plant = prevData.Plants[plantName];

      if (!plant) return prevData;

      const updatedPlant: PlantNode = {
        ...plant,

        inputs: plant.inputs.includes(productName)
          ? plant.inputs
          : [...plant.inputs, productName],
      };

      return {
        ...prevData,

        Plants: {
          ...prevData.Plants,

          [plantName]: updatedPlant,
        },
      };
    });
  };

  const onAddPlantOutput = (plantName: string, productName: string) => {
    setScenario((prevData) => {
      const plant = prevData.Plants[plantName];
      if (!plant) return prevData;

      const newOutputs = plant.outputs.includes(productName)
        ? plant.outputs
        : [...plant.outputs, productName];

      return {
        ...prevData,
        Plants: {
          ...prevData.Plants,
          [plantName]: {
            ...plant,
            outputs: newOutputs,
          },
        },
      };
    });
  };

  const onAddCenterOutput = (centerName: string, productName: string) => {
    setScenario((prev) => {
      const center = prev.Centers[centerName];
      if (!center) return prev;

      const updatedOutputs = [...center.output, productName];
      return {
        ...prev,
        Centers: {
          ...prev.Centers,
          [centerName]: { ...center, output: updatedOutputs },
        },
      };
    });
  };

  const onMoveNode = (type: EntityKey, id: string, x: number, y: number) => {
    setScenario((prevData) => {
      const nodesMap = prevData[type];
      const node = nodesMap[id];
      if (!node) return prevData;

      return {
        ...prevData,
        [type]: {
          ...nodesMap,
          [id]: { ...node, x, y },
        },
      } as RELOGScenario;
    });
  };

  const onRemoveNode = (type: EntityKey, id: string) => {
    setScenario((prevData) => {
      const nodesMap = { ...prevData[type] };
      delete nodesMap[id];

      return {
        ...prevData,
        [type]: nodesMap,
      };
    });
  };

  const onRenameNode = (type: EntityKey, uniqueId: string, newName: string) => {
    setScenario((prevData) => {
      const entities = prevData[type];
      const node = entities[uniqueId];

      if (!node) return prevData;

      return {
        ...prevData,
        [type]: {
          ...entities,
          [uniqueId]: { ...node, name: newName },
        },
      };
    });
  };

  return (
    <div>
      <Header onClear={onClear} onSave={onSave} onLoad={onLoad} />
      <div className="content">
        <div id="contentBackground">
          <div id="content">
            <PipelineBlock
              onAddPlant={() => onAddNode("Plants")}
              onAddProduct={() => onAddNode("Products")}
              onMovePlant={(id, x, y) => onMoveNode("Plants", id, x, y)}
              onMoveProduct={(id, x, y) => onMoveNode("Products", id, x, y)}
              plants={scenario.Plants}
              products={scenario.Products}
              onSetPlantInput={onSetPlantInput}
              onAddPlantOutput={onAddPlantOutput}
              onAddCenter={() => onAddNode("Centers")}
              onAddCenterInput={onSetCenterInput}
              onAddCenterOutput={onAddCenterOutput}
              onMoveCenter={(id, x, y) => onMoveNode("Centers", id, x, y)}
              centers={scenario.Centers}
              onRemovePlant={(id) => onRemoveNode("Plants", id)}
              onRemoveProduct={(id) => onRemoveNode("Products", id)}
              onRemoveCenter={(id) => onRemoveNode("Centers", id)}
              onRenamePlant={(id, name) => onRenameNode("Plants", id, name)}
              onRenameProduct={(id, name) => onRenameNode("Products", id, name)}
              onRenameCenter={(id, name) => onRenameNode("Centers", id, name)}
            />
          </div>
        </div>
      </div>
      <Footer />
    </div>
  );
};

export default CaseBuilder;
