import { ReactNode, useId, useRef } from "react";
import ItemPicker from "./ItemPicker";
import LocationSelect from "./LocationSelect";
import BatchPicker from "./BatchPicker";

export interface MovementItem {
  key: string;
  item_id: number | null;
  item_name?: string;
  quantity: number;
  unit_price: number;
  location_id: number | null;
  batch_id: number | null;
  reservation_id: number | null;
  notes: string | null;
}

export type MovementRowRenderer<T> = (
  item: T,
  index: number,
  updateItem: (field: string, value: unknown) => void,
  removeItem: () => void,
) => ReactNode;

interface WarehouseMovementTableProps<T extends { key: string }> {
  items: T[];
  onChange: (items: T[]) => void;
  mode: "receipt" | "issue" | "inventory";
  defaultItem?: () => Omit<T, "key">;
  renderRow?: MovementRowRenderer<T>;
  renderHeader?: () => ReactNode;
}

function parseDecimal(raw: string): number {
  // Strip leading minus if you want negative support; here we want only positive
  const cleaned = raw.replace(/[eE+\-]/g, "");
  const n = Number(cleaned);
  return Number.isFinite(n) ? n : 0;
}

const builtInDefaultMovementItem = (): Omit<MovementItem, "key"> => ({
  item_id: null,
  quantity: 0,
  unit_price: 0,
  location_id: null,
  batch_id: null,
  reservation_id: null,
  notes: null,
});

export default function WarehouseMovementTable<T extends { key: string }>({
  items,
  onChange,
  mode,
  defaultItem,
  renderRow,
  renderHeader,
}: WarehouseMovementTableProps<T>) {
  const baseId = useId();
  const counterRef = useRef(0);
  const nextKey = () => `${baseId}-item-${counterRef.current++}`;

  const addItem = () => {
    const factory =
      defaultItem ??
      (builtInDefaultMovementItem as unknown as () => Omit<T, "key">);
    onChange([...items, { ...(factory() as object), key: nextKey() } as T]);
  };
  const removeItem = (index: number) => {
    onChange(items.filter((_, i) => i !== index));
  };
  const updateItem = (index: number, field: string, value: unknown) => {
    const updated = [...items];
    updated[index] = { ...updated[index], [field]: value };
    onChange(updated);
  };

  // If a custom row renderer is supplied, the caller is fully in charge of
  // the row layout (and typically the column headers too — see inventory mode).
  if (renderRow) {
    return (
      <div>
        <div className="admin-warehouse-movement-table">
          <table className="admin-table">
            {renderHeader && (
              <thead>
                <tr>{renderHeader()}</tr>
              </thead>
            )}
            <tbody>
              {items.map((item, index) => (
                <tr key={item.key}>
                  {renderRow(
                    item,
                    index,
                    (field, value) => updateItem(index, field, value),
                    () => removeItem(index),
                  )}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <button
          type="button"
          className="admin-btn admin-btn-secondary"
          onClick={addItem}
        >
          + Přidat řádek
        </button>
      </div>
    );
  }

  // Default rendering: only valid for "receipt" | "issue" — narrow at runtime.
  const movementItems = items as unknown as MovementItem[];

  return (
    <div>
      <div className="admin-warehouse-movement-table">
        <table className="admin-table">
          <thead>
            <tr>
              <th className="admin-warehouse-col-item">Položka</th>
              {mode === "issue" && (
                <th className="admin-warehouse-col-batch">Šarže</th>
              )}
              <th className="admin-warehouse-col-qty">Množství</th>
              <th className="admin-warehouse-col-price">Cena/ks</th>
              <th className="admin-warehouse-col-location">Lokace</th>
              <th className="admin-warehouse-col-notes">Poznámka</th>
              <th>Akce</th>
            </tr>
          </thead>
          <tbody>
            {movementItems.map((item, index) => (
              <tr key={item.key}>
                <td className="admin-warehouse-col-item">
                  <ItemPicker
                    value={item.item_id}
                    itemName={item.item_name}
                    onChange={(id) => updateItem(index, "item_id", id)}
                  />
                </td>
                {mode === "issue" && (
                  <td className="admin-warehouse-col-batch">
                    <BatchPicker
                      itemId={item.item_id}
                      value={item.batch_id}
                      onChange={(batchId, unitPrice) => {
                        updateItem(index, "batch_id", batchId);
                        updateItem(index, "unit_price", unitPrice);
                      }}
                    />
                  </td>
                )}
                <td className="admin-warehouse-col-qty">
                  <input
                    type="number"
                    className="admin-form-input"
                    value={item.quantity || ""}
                    onChange={(e) =>
                      updateItem(
                        index,
                        "quantity",
                        parseDecimal(e.target.value),
                      )
                    }
                    min="0"
                    step="0.001"
                    inputMode="decimal"
                    pattern="[0-9]+([\.,][0-9]+)?"
                    aria-label={`Množství, řádek ${index + 1}`}
                  />
                </td>
                <td className="admin-warehouse-col-price">
                  <input
                    type="number"
                    className="admin-form-input"
                    value={item.unit_price || ""}
                    onChange={(e) =>
                      updateItem(
                        index,
                        "unit_price",
                        parseDecimal(e.target.value),
                      )
                    }
                    min="0"
                    step="0.01"
                    disabled={mode === "issue"}
                    inputMode="decimal"
                    pattern="[0-9]+([\.,][0-9]+)?"
                    aria-label={`Cena za kus, řádek ${index + 1}`}
                  />
                </td>
                <td className="admin-warehouse-col-location">
                  <LocationSelect
                    value={item.location_id}
                    onChange={(id) => updateItem(index, "location_id", id)}
                  />
                </td>
                <td className="admin-warehouse-col-notes">
                  <input
                    type="text"
                    className="admin-form-input"
                    value={item.notes ?? ""}
                    onChange={(e) => updateItem(index, "notes", e.target.value)}
                  />
                </td>
                <td>
                  <div className="admin-table-actions">
                    <button
                      type="button"
                      className="admin-btn-icon danger"
                      onClick={() => removeItem(index)}
                      title="Odebrat řádek"
                      aria-label="Odebrat řádek"
                    >
                      <svg
                        width="16"
                        height="16"
                        viewBox="0 0 24 24"
                        fill="none"
                        stroke="currentColor"
                        strokeWidth="2"
                        strokeLinecap="round"
                        strokeLinejoin="round"
                      >
                        <line x1="18" y1="6" x2="6" y2="18" />
                        <line x1="6" y1="6" x2="18" y2="18" />
                      </svg>
                    </button>
                  </div>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <button
        type="button"
        className="admin-btn admin-btn-secondary"
        onClick={addItem}
      >
        + Přidat řádek
      </button>
    </div>
  );
}
