"use client";

import { Activity, FolderPlus, Pencil, Plus, RefreshCw, Save, Trash2, X, Zap } from "lucide-react";
import { FormEvent, useEffect, useMemo, useState } from "react";
import {
  createConsumer,
  createDistributionBoard,
  createProject,
  deleteConsumer,
  listConsumers,
  listDistributionBoards,
  listProjects,
  updateConsumer,
} from "../utils/api";
import type {
  ConsumerWithCalculatedValues,
  CreateConsumerInput,
  DistributionBoardDto,
  ProjectDto,
  UpdateConsumerInput,
} from "../types";

const initialConsumerForm = {
  name: "",
  category: "",
  quantity: "1",
  installedPowerPerUnitKw: "0.1",
  demandFactor: "1",
  voltageV: "230",
  phaseCount: "1",
  powerFactor: "1",
  note: "",
};

interface EditConsumerForm {
  name: string;
  category: string;
  distributionBoardId: string;
  quantity: string;
  installedPowerPerUnitKw: string;
  demandFactor: string;
  voltageV: string;
  phaseCount: "1" | "3";
  powerFactor: string;
  note: string;
}

type ConsumerForm = typeof initialConsumerForm;

function toOptionalNumber(value: string) {
  if (value.trim() === "") {
    return undefined;
  }
  return Number(value);
}

function formatNumber(value: number | undefined, digits = 2) {
  if (value === undefined || Number.isNaN(value)) {
    return "-";
  }
  return new Intl.NumberFormat("de-DE", {
    maximumFractionDigits: digits,
    minimumFractionDigits: digits,
  }).format(value);
}

function createEditForm(consumer: ConsumerWithCalculatedValues): EditConsumerForm {
  return {
    name: consumer.name,
    category: consumer.category ?? "",
    distributionBoardId: consumer.distributionBoardId ?? "",
    quantity: String(consumer.quantity),
    installedPowerPerUnitKw: String(consumer.installedPowerPerUnitKw),
    demandFactor: String(consumer.demandFactor),
    voltageV: consumer.voltageV !== undefined ? String(consumer.voltageV) : "",
    phaseCount: consumer.phaseCount === 3 ? "3" : "1",
    powerFactor: consumer.powerFactor !== undefined ? String(consumer.powerFactor) : "",
    note: consumer.note ?? "",
  };
}

export function PowerBalanceWorkspace() {
  const [projects, setProjects] = useState<ProjectDto[]>([]);
  const [selectedProjectId, setSelectedProjectId] = useState("");
  const [distributionBoards, setDistributionBoards] = useState<DistributionBoardDto[]>([]);
  const [selectedBoardId, setSelectedBoardId] = useState("");
  const [consumers, setConsumers] = useState<ConsumerWithCalculatedValues[]>([]);
  const [projectName, setProjectName] = useState("");
  const [boardName, setBoardName] = useState("");
  const [consumerForm, setConsumerForm] = useState<ConsumerForm>(initialConsumerForm);
  const [editingConsumerId, setEditingConsumerId] = useState<string | null>(null);
  const [editConsumerForm, setEditConsumerForm] = useState<EditConsumerForm | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const selectedProject = projects.find((project) => project.id === selectedProjectId);
  const selectedBoard = distributionBoards.find((board) => board.id === selectedBoardId);
  const boardNames = new Map(distributionBoards.map((board) => [board.id, board.name]));
  const visibleConsumers = selectedBoardId
    ? consumers.filter((consumer) => consumer.distributionBoardId === selectedBoardId)
    : consumers;

  const totals = useMemo(
    () =>
      visibleConsumers.reduce(
        (sum, consumer) => ({
          installedPowerKw: sum.installedPowerKw + consumer.installedPowerKw,
          demandPowerKw: sum.demandPowerKw + consumer.demandPowerKw,
        }),
        { installedPowerKw: 0, demandPowerKw: 0 }
      ),
    [visibleConsumers]
  );
  const totalsByBoard = useMemo(() => {
    const bucket = new Map<string, { consumerCount: number; installedPowerKw: number; demandPowerKw: number }>();
    for (const board of distributionBoards) {
      bucket.set(board.id, { consumerCount: 0, installedPowerKw: 0, demandPowerKw: 0 });
    }
    bucket.set("__unassigned__", { consumerCount: 0, installedPowerKw: 0, demandPowerKw: 0 });

    for (const consumer of consumers) {
      const key = consumer.distributionBoardId ?? "__unassigned__";
      const entry = bucket.get(key);
      if (!entry) {
        continue;
      }
      entry.consumerCount += 1;
      entry.installedPowerKw += consumer.installedPowerKw;
      entry.demandPowerKw += consumer.demandPowerKw;
    }

    return [
      ...distributionBoards.map((board) => ({
        key: board.id,
        boardName: board.name,
        ...bucket.get(board.id)!,
      })),
      {
        key: "__unassigned__",
        boardName: "Ohne Verteilung",
        ...bucket.get("__unassigned__")!,
      },
    ].filter((item) => item.consumerCount > 0);
  }, [consumers, distributionBoards]);
  const projectTotals = useMemo(
    () =>
      consumers.reduce(
        (sum, consumer) => ({
          consumerCount: sum.consumerCount + 1,
          installedPowerKw: sum.installedPowerKw + consumer.installedPowerKw,
          demandPowerKw: sum.demandPowerKw + consumer.demandPowerKw,
        }),
        { consumerCount: 0, installedPowerKw: 0, demandPowerKw: 0 }
      ),
    [consumers]
  );

  async function refreshProjects() {
    setError(null);
    const loadedProjects = await listProjects();
    setProjects(loadedProjects);
    setSelectedProjectId((current) => current || loadedProjects[0]?.id || "");
  }

  async function refreshConsumers(projectId: string) {
    if (!projectId) {
      setConsumers([]);
      return;
    }
    setError(null);
    setConsumers(await listConsumers(projectId));
  }

  async function refreshDistributionBoards(projectId: string) {
    if (!projectId) {
      setDistributionBoards([]);
      setSelectedBoardId("");
      return;
    }

    setError(null);
    const boards = await listDistributionBoards(projectId);
    setDistributionBoards(boards);
    setSelectedBoardId((current) => (boards.some((board) => board.id === current) ? current : boards[0]?.id || ""));
  }

  useEffect(() => {
    refreshProjects()
      .catch((err: unknown) => setError(err instanceof Error ? err.message : "Projekte konnten nicht geladen werden."))
      .finally(() => setIsLoading(false));
  }, []);

  useEffect(() => {
    setEditingConsumerId(null);
    setEditConsumerForm(null);
    refreshDistributionBoards(selectedProjectId).catch((err: unknown) =>
      setError(err instanceof Error ? err.message : "Verteilungen konnten nicht geladen werden.")
    );
    refreshConsumers(selectedProjectId).catch((err: unknown) =>
      setError(err instanceof Error ? err.message : "Verbraucher konnten nicht geladen werden.")
    );
  }, [selectedProjectId]);

  async function handleCreateProject(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const name = projectName.trim();
    if (!name) {
      return;
    }

    setIsSaving(true);
    setError(null);
    try {
      const project = await createProject(name);
      setProjects((current) => [...current, project]);
      setSelectedProjectId(project.id);
      setProjectName("");
    } catch (err) {
      setError(err instanceof Error ? err.message : "Projekt konnte nicht angelegt werden.");
    } finally {
      setIsSaving(false);
    }
  }

  async function handleCreateDistributionBoard(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const name = boardName.trim();
    if (!selectedProjectId || !name) {
      return;
    }

    setIsSaving(true);
    setError(null);
    try {
      const board = await createDistributionBoard(selectedProjectId, name);
      setDistributionBoards((current) => [...current, board]);
      setSelectedBoardId(board.id);
      setBoardName("");
    } catch (err) {
      setError(err instanceof Error ? err.message : "Verteilung konnte nicht angelegt werden.");
    } finally {
      setIsSaving(false);
    }
  }

  async function handleCreateConsumer(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (!selectedProjectId || !consumerForm.name.trim()) {
      return;
    }

    const input: CreateConsumerInput = {
      projectId: selectedProjectId,
      distributionBoardId: selectedBoardId || undefined,
      name: consumerForm.name.trim(),
      category: consumerForm.category.trim() || undefined,
      quantity: Number(consumerForm.quantity),
      installedPowerPerUnitKw: Number(consumerForm.installedPowerPerUnitKw),
      demandFactor: Number(consumerForm.demandFactor),
      voltageV: toOptionalNumber(consumerForm.voltageV),
      phaseCount: consumerForm.phaseCount === "3" ? 3 : 1,
      powerFactor: toOptionalNumber(consumerForm.powerFactor),
      note: consumerForm.note.trim() || undefined,
    };

    setIsSaving(true);
    setError(null);
    try {
      const created = await createConsumer(input);
      setConsumers((current) => [...current, created]);
      setConsumerForm(initialConsumerForm);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Verbraucher konnte nicht angelegt werden.");
    } finally {
      setIsSaving(false);
    }
  }

  async function handleSaveConsumer(consumerId: string) {
    if (!selectedProjectId || !editConsumerForm) {
      return;
    }

    const input: UpdateConsumerInput = {
      projectId: selectedProjectId,
      distributionBoardId: editConsumerForm.distributionBoardId || undefined,
      name: editConsumerForm.name.trim(),
      category: editConsumerForm.category.trim() || undefined,
      quantity: Number(editConsumerForm.quantity),
      installedPowerPerUnitKw: Number(editConsumerForm.installedPowerPerUnitKw),
      demandFactor: Number(editConsumerForm.demandFactor),
      voltageV: toOptionalNumber(editConsumerForm.voltageV),
      phaseCount: editConsumerForm.phaseCount === "3" ? 3 : 1,
      powerFactor: toOptionalNumber(editConsumerForm.powerFactor),
      note: editConsumerForm.note.trim() || undefined,
    };

    setIsSaving(true);
    setError(null);
    try {
      const updated = await updateConsumer(consumerId, input);
      setConsumers((current) => current.map((item) => (item.id === consumerId ? updated : item)));
      setEditingConsumerId(null);
      setEditConsumerForm(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Verbraucher konnte nicht gespeichert werden.");
    } finally {
      setIsSaving(false);
    }
  }

  async function handleDeleteConsumer(consumerId: string) {
    setIsSaving(true);
    setError(null);
    try {
      await deleteConsumer(consumerId);
      setConsumers((current) => current.filter((item) => item.id !== consumerId));
      if (editingConsumerId === consumerId) {
        setEditingConsumerId(null);
        setEditConsumerForm(null);
      }
    } catch (err) {
      setError(err instanceof Error ? err.message : "Verbraucher konnte nicht geloescht werden.");
    } finally {
      setIsSaving(false);
    }
  }

  function startEditConsumer(consumer: ConsumerWithCalculatedValues) {
    setEditingConsumerId(consumer.id);
    setEditConsumerForm(createEditForm(consumer));
  }

  function cancelEditConsumer() {
    setEditingConsumerId(null);
    setEditConsumerForm(null);
  }

  function updateConsumerForm(field: keyof ConsumerForm, value: string) {
    setConsumerForm((current) => ({ ...current, [field]: value }));
  }

  function updateEditConsumerForm(field: keyof EditConsumerForm, value: string) {
    setEditConsumerForm((current) => (current ? { ...current, [field]: value } : current));
  }

  return (
    <main className="workspace">
      <header className="topbar">
        <div>
          <p className="eyebrow">TGA / ELT Planung</p>
          <h1>Leistungsbilanz</h1>
        </div>
        <button className="iconButton" type="button" onClick={() => refreshConsumers(selectedProjectId)} title="Aktualisieren">
          <RefreshCw size={18} />
        </button>
      </header>

      {error ? <p className="alert">{error}</p> : null}

      <section className="toolbarBand">
        <form className="projectForm" onSubmit={handleCreateProject}>
          <label>
            Projekt
            <select value={selectedProjectId} onChange={(event) => setSelectedProjectId(event.target.value)}>
              <option value="">Kein Projekt</option>
              {projects.map((project) => (
                <option key={project.id} value={project.id}>
                  {project.name}
                </option>
              ))}
            </select>
          </label>
          <label>
            Neues Projekt
            <input value={projectName} onChange={(event) => setProjectName(event.target.value)} placeholder="z. B. BV Neubau" />
          </label>
          <button className="primaryButton" type="submit" disabled={isSaving}>
            <FolderPlus size={17} />
            Anlegen
          </button>
        </form>

        <form className="boardForm" onSubmit={handleCreateDistributionBoard}>
          <label>
            Verteilung
            <select value={selectedBoardId} onChange={(event) => setSelectedBoardId(event.target.value)}>
              <option value="">Alle Verteilungen</option>
              {distributionBoards.map((board) => (
                <option key={board.id} value={board.id}>
                  {board.name}
                </option>
              ))}
            </select>
          </label>
          <label>
            Neue Verteilung
            <input value={boardName} onChange={(event) => setBoardName(event.target.value)} placeholder="z. B. UV-01" />
          </label>
          <button className="primaryButton" type="submit" disabled={!selectedProjectId || isSaving}>
            <Plus size={17} />
            Anlegen
          </button>
        </form>

        <div className="summaryStrip" aria-label="Summen">
          <div>
            <span>Verbraucher</span>
            <strong>{visibleConsumers.length}</strong>
          </div>
          <div>
            <span>Installierte Leistung</span>
            <strong>{formatNumber(totals.installedPowerKw)} kW</strong>
          </div>
          <div>
            <span>Berechnete Leistung</span>
            <strong>{formatNumber(totals.demandPowerKw)} kW</strong>
          </div>
        </div>
      </section>

      <section className="entryBand">
        <form className="consumerForm" onSubmit={handleCreateConsumer}>
          <label>
            Verbraucher
            <input value={consumerForm.name} onChange={(event) => updateConsumerForm("name", event.target.value)} placeholder="z. B. Steckdosen Buero" />
          </label>
          <label>
            Kategorie
            <input value={consumerForm.category} onChange={(event) => updateConsumerForm("category", event.target.value)} placeholder="Allgemein" />
          </label>
          <label>
            Anzahl
            <input min="0" type="number" value={consumerForm.quantity} onChange={(event) => updateConsumerForm("quantity", event.target.value)} />
          </label>
          <label>
            Leistung je Stueck [kW]
            <input min="0" step="0.01" type="number" value={consumerForm.installedPowerPerUnitKw} onChange={(event) => updateConsumerForm("installedPowerPerUnitKw", event.target.value)} />
          </label>
          <label>
            Gleichzeitigkeitsfaktor
            <input min="0" max="1" step="0.01" type="number" value={consumerForm.demandFactor} onChange={(event) => updateConsumerForm("demandFactor", event.target.value)} />
          </label>
          <label>
            Spannung [V]
            <input min="1" type="number" value={consumerForm.voltageV} onChange={(event) => updateConsumerForm("voltageV", event.target.value)} />
          </label>
          <label>
            Phasen
            <select value={consumerForm.phaseCount} onChange={(event) => updateConsumerForm("phaseCount", event.target.value)}>
              <option value="1">1-phasig</option>
              <option value="3">3-phasig</option>
            </select>
          </label>
          <label>
            cos phi
            <input min="0" max="1" step="0.01" type="number" value={consumerForm.powerFactor} onChange={(event) => updateConsumerForm("powerFactor", event.target.value)} />
          </label>
          <label className="wideField">
            Bemerkung
            <input value={consumerForm.note} onChange={(event) => updateConsumerForm("note", event.target.value)} />
          </label>
          <button className="primaryButton" type="submit" disabled={!selectedProjectId || isSaving}>
            <Plus size={17} />
            Hinzufuegen
          </button>
        </form>
      </section>

      <section className="tableBand">
        <div className="tableHeader">
          <div>
            <p className="eyebrow">Aktuelles Projekt</p>
            <h2>{selectedProject?.name || "Noch kein Projekt ausgewaehlt"}</h2>
            <p className="subline">{selectedBoard ? `Verteilung: ${selectedBoard.name}` : "Alle Verteilungen"}</p>
          </div>
          <div className="statusPill">
            <Activity size={16} />
            {isLoading ? "Laedt" : "Bereit"}
          </div>
        </div>

        <div className="boardTotals">
          <h3>Summen nach Verteilung</h3>
          <div className="tableScroll">
            <table>
              <thead>
                <tr>
                  <th>Verteilung</th>
                  <th>Verbraucher</th>
                  <th>Installierte Leistung [kW]</th>
                  <th>Berechnete Leistung [kW]</th>
                </tr>
              </thead>
              <tbody>
                {totalsByBoard.map((item) => (
                  <tr key={item.key}>
                    <td>{item.boardName}</td>
                    <td>{item.consumerCount}</td>
                    <td>{formatNumber(item.installedPowerKw)}</td>
                    <td>{formatNumber(item.demandPowerKw)}</td>
                  </tr>
                ))}
                {!totalsByBoard.length ? (
                  <tr>
                    <td colSpan={4} className="emptyState">
                      Noch keine Verbraucher fuer eine Summenbildung vorhanden.
                    </td>
                  </tr>
                ) : null}
                <tr className="totalRow">
                  <td>Projekt gesamt</td>
                  <td>{projectTotals.consumerCount}</td>
                  <td>{formatNumber(projectTotals.installedPowerKw)}</td>
                  <td>{formatNumber(projectTotals.demandPowerKw)}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>

        <div className="tableScroll">
          <table>
            <thead>
              <tr>
                <th>Verbraucher</th>
                <th>Verteilung</th>
                <th>Kategorie</th>
                <th>Anzahl</th>
                <th>Leistung je Stueck [kW]</th>
                <th>Installierte Leistung [kW]</th>
                <th>GZF</th>
                <th>Berechnete Leistung [kW]</th>
                <th>Strom [A]</th>
                <th>Bemerkung</th>
                <th>Aktionen</th>
              </tr>
            </thead>
            <tbody>
              {visibleConsumers.map((consumer) => {
                const isEditing = editingConsumerId === consumer.id && editConsumerForm;
                return (
                  <tr key={consumer.id}>
                    <td className="nameCell">
                      <Zap size={15} />
                      {isEditing ? (
                        <input value={editConsumerForm.name} onChange={(event) => updateEditConsumerForm("name", event.target.value)} />
                      ) : (
                        consumer.name
                      )}
                    </td>
                    <td>
                      {isEditing ? (
                        <select
                          value={editConsumerForm.distributionBoardId}
                          onChange={(event) => updateEditConsumerForm("distributionBoardId", event.target.value)}
                        >
                          <option value="">-</option>
                          {distributionBoards.map((board) => (
                            <option key={board.id} value={board.id}>
                              {board.name}
                            </option>
                          ))}
                        </select>
                      ) : consumer.distributionBoardId ? (
                        boardNames.get(consumer.distributionBoardId) || "-"
                      ) : (
                        "-"
                      )}
                    </td>
                    <td>
                      {isEditing ? (
                        <input value={editConsumerForm.category} onChange={(event) => updateEditConsumerForm("category", event.target.value)} />
                      ) : (
                        consumer.category || "-"
                      )}
                    </td>
                    <td>
                      {isEditing ? (
                        <input min="0" type="number" value={editConsumerForm.quantity} onChange={(event) => updateEditConsumerForm("quantity", event.target.value)} />
                      ) : (
                        consumer.quantity
                      )}
                    </td>
                    <td>
                      {isEditing ? (
                        <input
                          min="0"
                          step="0.01"
                          type="number"
                          value={editConsumerForm.installedPowerPerUnitKw}
                          onChange={(event) => updateEditConsumerForm("installedPowerPerUnitKw", event.target.value)}
                        />
                      ) : (
                        formatNumber(consumer.installedPowerPerUnitKw)
                      )}
                    </td>
                    <td>{formatNumber(consumer.installedPowerKw)}</td>
                    <td>
                      {isEditing ? (
                        <input min="0" max="1" step="0.01" type="number" value={editConsumerForm.demandFactor} onChange={(event) => updateEditConsumerForm("demandFactor", event.target.value)} />
                      ) : (
                        formatNumber(consumer.demandFactor)
                      )}
                    </td>
                    <td>{formatNumber(consumer.demandPowerKw)}</td>
                    <td>
                      {isEditing ? (
                        <div className="rowField">
                          <input min="1" type="number" value={editConsumerForm.voltageV} onChange={(event) => updateEditConsumerForm("voltageV", event.target.value)} />
                          <select value={editConsumerForm.phaseCount} onChange={(event) => updateEditConsumerForm("phaseCount", event.target.value)}>
                            <option value="1">1</option>
                            <option value="3">3</option>
                          </select>
                          <input min="0" max="1" step="0.01" type="number" value={editConsumerForm.powerFactor} onChange={(event) => updateEditConsumerForm("powerFactor", event.target.value)} />
                        </div>
                      ) : (
                        formatNumber(consumer.currentA)
                      )}
                    </td>
                    <td>
                      {isEditing ? (
                        <input value={editConsumerForm.note} onChange={(event) => updateEditConsumerForm("note", event.target.value)} />
                      ) : (
                        consumer.note || "-"
                      )}
                    </td>
                    <td>
                      <div className="rowActions">
                        {isEditing ? (
                          <>
                            <button className="iconButton small" type="button" title="Speichern" onClick={() => handleSaveConsumer(consumer.id)} disabled={isSaving}>
                              <Save size={14} />
                            </button>
                            <button className="iconButton small muted" type="button" title="Abbrechen" onClick={cancelEditConsumer}>
                              <X size={14} />
                            </button>
                          </>
                        ) : (
                          <button className="iconButton small" type="button" title="Bearbeiten" onClick={() => startEditConsumer(consumer)}>
                            <Pencil size={14} />
                          </button>
                        )}
                        <button className="iconButton small danger" type="button" title="Loeschen" onClick={() => handleDeleteConsumer(consumer.id)} disabled={isSaving}>
                          <Trash2 size={14} />
                        </button>
                      </div>
                    </td>
                  </tr>
                );
              })}
              {!visibleConsumers.length ? (
                <tr>
                  <td colSpan={11} className="emptyState">
                    Lege eine Verteilung an oder erfasse den ersten Verbraucher.
                  </td>
                </tr>
              ) : null}
            </tbody>
          </table>
        </div>
      </section>
    </main>
  );
}
