import { useState, useEffect, useCallback } from "react";
import { get, post, put, del } from "../../api/client";
import type { BOMEntry } from "../../api/types";

interface BOMTabProps {
  partNumber: string;
  isEditor: boolean;
}

interface BOMFormData {
  child_part_number: string;
  quantity: string;
  source: string;
  seller_description: string;
  unit_cost: string;
  sourcing_link: string;
}

const emptyForm: BOMFormData = {
  child_part_number: "",
  quantity: "1",
  source: "",
  seller_description: "",
  unit_cost: "",
  sourcing_link: "",
};

export function BOMTab({ partNumber, isEditor }: BOMTabProps) {
  const [entries, setEntries] = useState<BOMEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [showAdd, setShowAdd] = useState(false);
  const [editIdx, setEditIdx] = useState<number | null>(null);
  const [form, setForm] = useState<BOMFormData>(emptyForm);

  const load = useCallback(() => {
    setLoading(true);
    get<BOMEntry[]>(`/api/items/${encodeURIComponent(partNumber)}/bom`)
      .then(setEntries)
      .catch(() => setEntries([]))
      .finally(() => setLoading(false));
  }, [partNumber]);

  useEffect(load, [load]);

  const meta = (e: BOMEntry) => (e.metadata ?? {}) as Record<string, string>;
  const unitCost = (e: BOMEntry) => Number(meta(e).unit_cost) || 0;
  const extCost = (e: BOMEntry) => unitCost(e) * (e.quantity ?? 0);
  const totalCost = entries.reduce((sum, e) => sum + extCost(e), 0);
  const assemblyCount = entries.filter((e) => e.source === "assembly").length;

  const formToRequest = () => ({
    child_part_number: form.child_part_number,
    rel_type: "component" as const,
    quantity: Number(form.quantity) || 1,
    source: form.source,
    metadata: {
      seller_description: form.seller_description,
      unit_cost: form.unit_cost,
      sourcing_link: form.sourcing_link,
    },
  });

  const handleAdd = async () => {
    try {
      await post(
        `/api/items/${encodeURIComponent(partNumber)}/bom`,
        formToRequest(),
      );
      setShowAdd(false);
      setForm(emptyForm);
      load();
    } catch (e) {
      alert(e instanceof Error ? e.message : "Failed to add BOM entry");
    }
  };

  const handleEdit = async (childPN: string) => {
    try {
      const { child_part_number: _, ...req } = formToRequest();
      await put(
        `/api/items/${encodeURIComponent(partNumber)}/bom/${encodeURIComponent(childPN)}`,
        req,
      );
      setEditIdx(null);
      setForm(emptyForm);
      load();
    } catch (e) {
      alert(e instanceof Error ? e.message : "Failed to update BOM entry");
    }
  };

  const handleDelete = async (childPN: string) => {
    if (!confirm(`Remove ${childPN} from BOM?`)) return;
    try {
      await del(
        `/api/items/${encodeURIComponent(partNumber)}/bom/${encodeURIComponent(childPN)}`,
      );
      load();
    } catch (e) {
      alert(e instanceof Error ? e.message : "Failed to delete BOM entry");
    }
  };

  const startEdit = (idx: number) => {
    const e = entries[idx]!;
    const m = meta(e);
    setForm({
      child_part_number: e.child_part_number,
      quantity: String(e.quantity ?? 1),
      source: e.source ?? "",
      seller_description: m.seller_description ?? "",
      unit_cost: m.unit_cost ?? "",
      sourcing_link: m.sourcing_link ?? "",
    });
    setEditIdx(idx);
    setShowAdd(false);
  };

  const inputStyle: React.CSSProperties = {
    padding: "0.2rem 0.4rem",
    fontSize: "0.8rem",
    backgroundColor: "var(--ctp-base)",
    border: "1px solid var(--ctp-surface1)",
    borderRadius: "0.3rem",
    color: "var(--ctp-text)",
    width: "100%",
  };

  const formRow = (isEditing: boolean, childPN?: string) => (
    <tr style={{ backgroundColor: "var(--ctp-surface0)" }}>
      <td style={tdStyle}>
        <input
          value={form.child_part_number}
          onChange={(e) =>
            setForm({ ...form, child_part_number: e.target.value })
          }
          disabled={isEditing}
          placeholder="Part number"
          style={inputStyle}
        />
      </td>
      <td style={tdStyle}>
        <select
          value={form.source}
          onChange={(e) => setForm({ ...form, source: e.target.value })}
          style={inputStyle}
        >
          <option value="">—</option>
          <option value="manual">manual</option>
          <option value="assembly">assembly</option>
        </select>
      </td>
      <td style={tdStyle}>
        <input
          value={form.seller_description}
          onChange={(e) =>
            setForm({ ...form, seller_description: e.target.value })
          }
          placeholder="Description"
          style={inputStyle}
        />
      </td>
      <td style={tdStyle}>
        <input
          value={form.unit_cost}
          onChange={(e) => setForm({ ...form, unit_cost: e.target.value })}
          type="number"
          step="0.01"
          placeholder="0.00"
          style={inputStyle}
        />
      </td>
      <td style={tdStyle}>
        <input
          value={form.quantity}
          onChange={(e) => setForm({ ...form, quantity: e.target.value })}
          type="number"
          step="1"
          placeholder="1"
          style={{ ...inputStyle, width: 50 }}
        />
      </td>
      <td style={tdStyle}>—</td>
      <td style={tdStyle}>
        <input
          value={form.sourcing_link}
          onChange={(e) => setForm({ ...form, sourcing_link: e.target.value })}
          placeholder="URL"
          style={inputStyle}
        />
      </td>
      <td style={tdStyle}>
        <button
          onClick={() =>
            isEditing ? void handleEdit(childPN!) : void handleAdd()
          }
          style={saveBtnStyle}
        >
          Save
        </button>
        <button
          onClick={() => {
            isEditing ? setEditIdx(null) : setShowAdd(false);
            setForm(emptyForm);
          }}
          style={cancelBtnStyle}
        >
          Cancel
        </button>
      </td>
    </tr>
  );

  if (loading)
    return <div style={{ color: "var(--ctp-subtext0)" }}>Loading BOM...</div>;

  return (
    <div>
      {/* Toolbar */}
      <div
        style={{
          display: "flex",
          gap: "0.5rem",
          alignItems: "center",
          marginBottom: "0.5rem",
        }}
      >
        <span style={{ fontSize: "0.85rem", color: "var(--ctp-subtext1)" }}>
          {entries.length} entries
        </span>
        <span style={{ flex: 1 }} />
        <button
          onClick={() => {
            window.location.href = `/api/items/${encodeURIComponent(partNumber)}/bom/export.csv`;
          }}
          style={toolBtnStyle}
        >
          Export CSV
        </button>
        {isEditor && (
          <button
            onClick={() => {
              setShowAdd(true);
              setEditIdx(null);
              setForm(emptyForm);
            }}
            style={toolBtnStyle}
          >
            + Add
          </button>
        )}
      </div>

      {isEditor && assemblyCount > 0 && (
        <div
          style={{
            padding: "0.35rem 0.6rem",
            marginBottom: "0.5rem",
            borderRadius: "0.3rem",
            backgroundColor: "rgba(148,226,213,0.1)",
            border: "1px solid rgba(148,226,213,0.3)",
            fontSize: "0.75rem",
            color: "var(--ctp-subtext1)",
          }}
        >
          {assemblyCount} assembly-sourced{" "}
          {assemblyCount === 1 ? "entry" : "entries"}. Entries removed from the
          FreeCAD assembly will remain here until manually deleted.
        </div>
      )}

      <div style={{ overflow: "auto" }}>
        <table
          style={{
            width: "100%",
            borderCollapse: "collapse",
            fontSize: "0.8rem",
          }}
        >
          <thead>
            <tr>
              <th style={thStyle}>PN</th>
              <th style={thStyle}>Source</th>
              <th style={thStyle}>Seller Desc</th>
              <th style={thStyle}>Unit Cost</th>
              <th style={thStyle}>QTY</th>
              <th style={thStyle}>Ext Cost</th>
              <th style={thStyle}>Link</th>
              {isEditor && <th style={thStyle}>Actions</th>}
            </tr>
          </thead>
          <tbody>
            {showAdd && formRow(false)}
            {entries.map((e, idx) => {
              if (editIdx === idx) return formRow(true, e.child_part_number);
              const m = meta(e);
              return (
                <tr
                  key={e.id}
                  style={{
                    backgroundColor:
                      idx % 2 === 0 ? "var(--ctp-base)" : "var(--ctp-surface0)",
                  }}
                >
                  <td
                    style={{
                      ...tdStyle,
                      fontFamily: "'JetBrains Mono', monospace",
                      color: "var(--ctp-peach)",
                    }}
                  >
                    {e.child_part_number}
                  </td>
                  <td style={tdStyle}>
                    {e.source === "assembly" ? (
                      <span style={assemblyBadge}>assembly</span>
                    ) : e.source === "manual" ? (
                      <span style={manualBadge}>manual</span>
                    ) : (
                      "—"
                    )}
                  </td>
                  <td
                    style={{
                      ...tdStyle,
                      maxWidth: 150,
                      overflow: "hidden",
                      textOverflow: "ellipsis",
                    }}
                  >
                    {e.child_description || m.seller_description || ""}
                  </td>
                  <td style={{ ...tdStyle, fontFamily: "monospace" }}>
                    {unitCost(e) ? `$${unitCost(e).toFixed(2)}` : "—"}
                  </td>
                  <td style={tdStyle}>{e.quantity ?? "—"}</td>
                  <td style={{ ...tdStyle, fontFamily: "monospace" }}>
                    {extCost(e) ? `$${extCost(e).toFixed(2)}` : "—"}
                  </td>
                  <td style={tdStyle}>
                    {m.sourcing_link ? (
                      <a
                        href={m.sourcing_link}
                        target="_blank"
                        rel="noreferrer"
                        style={{
                          color: "var(--ctp-sapphire)",
                          fontSize: "0.75rem",
                        }}
                      >
                        Link
                      </a>
                    ) : (
                      "—"
                    )}
                  </td>
                  {isEditor && (
                    <td style={tdStyle}>
                      <button
                        onClick={() => startEdit(idx)}
                        style={actionBtnStyle}
                      >
                        Edit
                      </button>
                      <button
                        onClick={() => void handleDelete(e.child_part_number)}
                        style={{ ...actionBtnStyle, color: "var(--ctp-red)" }}
                      >
                        Del
                      </button>
                    </td>
                  )}
                </tr>
              );
            })}
          </tbody>
          {totalCost > 0 && (
            <tfoot>
              <tr style={{ borderTop: "2px solid var(--ctp-surface1)" }}>
                <td
                  colSpan={5}
                  style={{ ...tdStyle, textAlign: "right", fontWeight: 600 }}
                >
                  Total:
                </td>
                <td
                  style={{
                    ...tdStyle,
                    fontFamily: "monospace",
                    fontWeight: 600,
                  }}
                >
                  ${totalCost.toFixed(2)}
                </td>
                <td colSpan={isEditor ? 2 : 1} style={tdStyle} />
              </tr>
            </tfoot>
          )}
        </table>
      </div>
    </div>
  );
}

const thStyle: React.CSSProperties = {
  padding: "0.3rem 0.5rem",
  textAlign: "left",
  borderBottom: "1px solid var(--ctp-surface1)",
  color: "var(--ctp-subtext1)",
  fontWeight: 600,
  fontSize: "0.7rem",
  textTransform: "uppercase",
  letterSpacing: "0.05em",
  whiteSpace: "nowrap",
};

const tdStyle: React.CSSProperties = {
  padding: "0.25rem 0.5rem",
  borderBottom: "1px solid var(--ctp-surface0)",
  whiteSpace: "nowrap",
};

const toolBtnStyle: React.CSSProperties = {
  padding: "0.25rem 0.5rem",
  fontSize: "0.8rem",
  border: "none",
  borderRadius: "0.3rem",
  backgroundColor: "var(--ctp-surface1)",
  color: "var(--ctp-text)",
  cursor: "pointer",
};

const actionBtnStyle: React.CSSProperties = {
  background: "none",
  border: "none",
  color: "var(--ctp-subtext1)",
  cursor: "pointer",
  fontSize: "0.75rem",
  padding: "0.1rem 0.3rem",
};

const saveBtnStyle: React.CSSProperties = {
  padding: "0.2rem 0.4rem",
  fontSize: "0.75rem",
  border: "none",
  borderRadius: "0.25rem",
  backgroundColor: "var(--ctp-green)",
  color: "var(--ctp-crust)",
  cursor: "pointer",
  marginRight: "0.25rem",
};

const sourceBadgeBase: React.CSSProperties = {
  padding: "0.1rem 0.4rem",
  borderRadius: "1rem",
  fontSize: "0.7rem",
  fontWeight: 500,
};

const assemblyBadge: React.CSSProperties = {
  ...sourceBadgeBase,
  backgroundColor: "rgba(148,226,213,0.2)",
  color: "var(--ctp-teal)",
};

const manualBadge: React.CSSProperties = {
  ...sourceBadgeBase,
  backgroundColor: "rgba(137,180,250,0.2)",
  color: "var(--ctp-blue)",
};

const cancelBtnStyle: React.CSSProperties = {
  padding: "0.2rem 0.4rem",
  fontSize: "0.75rem",
  border: "none",
  borderRadius: "0.25rem",
  backgroundColor: "var(--ctp-surface1)",
  color: "var(--ctp-subtext1)",
  cursor: "pointer",
};
