import { useState, useEffect, useRef, useId, useCallback } from "react";
import {
  useParams,
  useNavigate,
  useLocation,
  Link as RouterLink,
} from "react-router-dom";
import { useQuery } from "@tanstack/react-query";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import { useAlert } from "../context/AlertContext";
import { useAuth } from "../context/AuthContext";
import Forbidden from "../components/Forbidden";
import ItemPicker from "../components/warehouse/ItemPicker";

import { jsonQuery } from "../lib/apiAdapter";
import {
  warehouseIssueDetailOptions,
  warehouseLocationListOptions,
  type WarehouseLocation,
} from "../lib/queries/warehouse";
import { projectListOptions, type Project } from "../lib/queries/projects";
import { useApiMutation } from "../lib/queries/mutations";
import {
  Button,
  Card,
  TextField,
  Select,
  Field,
  LoadingState,
  PageEnter,
} from "../ui";

interface IssueForm {
  project_id: number | null;
  notes: string;
}

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;
}

interface Batch {
  id: number;
  quantity: number;
  unit_price: number;
  received_at: string;
  is_consumed: boolean;
}

interface BatchesResponse {
  batches: Batch[];
  total_stock: number;
  reserved_quantity: number;
  available_quantity: number;
}

function parseDecimal(raw: string): number {
  const cleaned = raw.replace(/[eE+-]/g, "");
  const n = Number(cleaned);
  return Number.isFinite(n) ? n : 0;
}

const BackIcon = (
  <svg
    width="20"
    height="20"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <path d="M19 12H5M12 19l-7-7 7-7" />
  </svg>
);

const RemoveIcon = (
  <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>
);

const PlusIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <line x1="12" y1="5" x2="12" y2="19" />
    <line x1="5" y1="12" x2="19" y2="12" />
  </svg>
);

/** Inline batch dropdown: lists FIFO batches for an item, sets batch + unit price. */
function BatchSelect({
  itemId,
  value,
  onChange,
}: {
  itemId: number | null;
  value: number | null;
  onChange: (batchId: number, unitPrice: number) => void;
}) {
  const { data: response } = useQuery({
    queryKey: ["warehouse", "batches", itemId],
    queryFn: () =>
      jsonQuery<BatchesResponse>(
        `/api/admin/warehouse/items/${itemId}/batches`,
      ),
    enabled: !!itemId,
  });

  const batches = response?.batches ?? [];

  return (
    <Box>
      {response && response.reserved_quantity > 0 && (
        <Typography
          variant="caption"
          color="text.secondary"
          sx={{ display: "block", mb: 0.5 }}
        >
          Dostupné: {response.available_quantity} ks (z toho rezervováno:{" "}
          {response.reserved_quantity} ks)
        </Typography>
      )}
      <Select
        value={value === null ? "" : String(value)}
        onChange={(val) => {
          const batchId = Number(val);
          const batch = batches.find((b) => b.id === batchId);
          if (batch) onChange(batch.id, Number(batch.unit_price));
        }}
        options={[
          { value: "", label: "-- auto FIFO --" },
          ...batches.map((b) => ({
            value: String(b.id),
            label: `${new Date(b.received_at).toLocaleDateString("cs-CZ")} | ${b.quantity} ks | ${Number(b.unit_price).toFixed(2)} Kč`,
          })),
        ]}
      />
    </Box>
  );
}

export default function WarehouseIssueForm() {
  const { id } = useParams();
  const alert = useAlert();
  const { hasPermission } = useAuth();
  const navigate = useNavigate();
  const location = useLocation();

  const baseId = useId();
  const counterRef = useRef(0);
  const nextKey = useCallback(
    () => `${baseId}-item-${counterRef.current++}`,
    [baseId],
  );

  // Pre-fill data from reservation ("Create výdej" button)
  const prefill = location.state as {
    reservationId?: number;
    itemId?: number;
    projectId?: number;
    quantity?: number;
    itemName?: string;
  } | null;

  const isEdit = id !== undefined && id !== "new";

  const [form, setForm] = useState<IssueForm>({
    project_id: prefill?.projectId ?? null,
    notes: "",
  });
  const [items, setItems] = useState<MovementItem[]>(() =>
    isEdit
      ? []
      : prefill?.itemId
        ? [
            {
              key: nextKey(),
              item_id: prefill.itemId,
              item_name: prefill.itemName,
              quantity: prefill.quantity ?? 0,
              unit_price: 0,
              location_id: null,
              batch_id: null,
              reservation_id: prefill.reservationId ?? null,
              notes: null,
            },
          ]
        : [
            {
              key: nextKey(),
              item_id: null,
              quantity: 0,
              unit_price: 0,
              location_id: null,
              batch_id: null,
              reservation_id: null,
              notes: null,
            },
          ],
  );
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [saving, setSaving] = useState(false);

  const formInitialized = useRef(false);

  const { data: issue, isPending } = useQuery(
    warehouseIssueDetailOptions(isEdit ? id : undefined),
  );

  const { data: projectsData } = useQuery(projectListOptions({ perPage: 100 }));
  const projects = projectsData?.data ?? [];

  const { data: locations } = useQuery(warehouseLocationListOptions());

  useEffect(() => {
    formInitialized.current = false;
  }, [id]);

  useEffect(() => {
    if (isEdit && issue && !formInitialized.current) {
      setForm({
        project_id: issue.project_id,
        notes: issue.notes || "",
      });
      if (issue.items && issue.items.length > 0) {
        setItems(
          issue.items.map((item) => ({
            key: nextKey(),
            item_id: item.item_id,
            item_name: item.item?.name,
            quantity: Number(item.quantity),
            unit_price: item.batch ? Number(item.batch.unit_price) : 0,
            location_id: item.location_id,
            batch_id: item.batch_id,
            reservation_id: item.reservation_id,
            notes: item.notes,
          })),
        );
      }
      formInitialized.current = true;
    }
  }, [isEdit, issue, nextKey]);

  const saveMutation = useApiMutation<
    ReturnType<typeof buildPayload>,
    { id?: number }
  >({
    url: () =>
      isEdit
        ? `/api/admin/warehouse/issues/${id}`
        : "/api/admin/warehouse/issues",
    method: () => (isEdit ? "PUT" : "POST"),
    invalidate: ["warehouse"],
  });

  const confirmMutation = useApiMutation<number, void>({
    url: (issueId) => `/api/admin/warehouse/issues/${issueId}/confirm`,
    method: () => "POST",
    invalidate: ["warehouse"],
    onSuccess: () => {
      alert.success("Výdejka byla potvrzena");
    },
  });

  // All hooks above this line — permission gate is the last thing before render.
  if (!hasPermission("warehouse.operate")) return <Forbidden />;

  const addItem = () => {
    setItems((prev) => [
      ...prev,
      {
        key: nextKey(),
        item_id: null,
        quantity: 0,
        unit_price: 0,
        location_id: null,
        batch_id: null,
        reservation_id: null,
        notes: null,
      },
    ]);
  };

  const removeItem = (index: number) => {
    setItems((prev) => prev.filter((_, i) => i !== index));
  };

  const updateItem = (
    index: number,
    field: keyof MovementItem,
    value: unknown,
  ) => {
    setItems((prev) => {
      const updated = [...prev];
      updated[index] = { ...updated[index], [field]: value };
      return updated;
    });
  };

  const validate = (): boolean => {
    const newErrors: Record<string, string> = {};
    if (!form.project_id) {
      newErrors.project_id = "Projekt je povinný";
    }
    const validItems = items.filter((l) => l.item_id !== null);
    if (validItems.length === 0) {
      newErrors.items = "Přidejte alespoň jednu položku";
    }
    for (const item of validItems) {
      if (item.quantity <= 0) {
        newErrors.items = "Množství musí být větší než 0";
        break;
      }
    }
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const buildPayload = () => ({
    project_id: form.project_id,
    notes: form.notes.trim() || null,
    items: items
      .filter((l) => l.item_id !== null)
      .map((l) => ({
        item_id: l.item_id!,
        batch_id: l.batch_id,
        quantity: l.quantity,
        location_id: l.location_id,
        reservation_id: l.reservation_id,
        notes: l.notes?.trim() || null,
      })),
  });

  const saveIssue = async (): Promise<number | null> => {
    try {
      const data = await saveMutation.mutateAsync(buildPayload());
      return data?.id ?? Number(id);
    } catch (e) {
      alert.error(
        e instanceof Error ? e.message : "Nepodařilo se uložit výdejku",
      );
      return null;
    }
  };

  const confirmIssue = async (issueId: number) => {
    try {
      await confirmMutation.mutateAsync(issueId);
    } catch (e) {
      alert.error(e instanceof Error ? e.message : "Chyba připojení");
    }
  };

  const handleSaveDraft = async () => {
    if (!validate()) return;
    setSaving(true);
    try {
      const savedId = await saveIssue();
      if (savedId) {
        alert.success("Výdejka byla uložena jako návrh");
        navigate(`/warehouse/issues/${savedId}`);
      }
    } finally {
      setSaving(false);
    }
  };

  const handleSaveAndConfirm = async () => {
    if (!validate()) return;
    setSaving(true);
    try {
      const savedId = await saveIssue();
      if (savedId) {
        await confirmIssue(savedId);
        navigate(`/warehouse/issues/${savedId}`);
      }
    } finally {
      setSaving(false);
    }
  };

  if (isEdit && isPending) {
    return <LoadingState />;
  }

  const projectOptions = [
    { value: "", label: "Vyberte projekt..." },
    ...projects.map((p: Project) => ({
      value: String(p.id),
      label: `${p.project_number} – ${p.name}`,
    })),
  ];

  const locationOptions = [
    { value: "", label: "-- bez lokace --" },
    ...(locations ?? []).map((loc: WarehouseLocation) => ({
      value: String(loc.id),
      label: `${loc.code} - ${loc.name}`,
    })),
  ];

  return (
    <PageEnter>
      {/* Header */}
      <Box
        sx={{
          display: "flex",
          alignItems: "flex-start",
          justifyContent: "space-between",
          flexWrap: "wrap",
          gap: 2,
          mb: 3,
        }}
      >
        <Box sx={{ display: "flex", alignItems: "center", gap: 1.5 }}>
          <IconButton
            component={RouterLink}
            to="/warehouse/issues"
            title="Zpět na seznam"
            aria-label="Zpět na seznam"
          >
            {BackIcon}
          </IconButton>
          <Typography variant="h4">
            {isEdit ? "Upravit výdejku" : "Nová výdejka"}
          </Typography>
        </Box>
        <Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
          <Button
            variant="outlined"
            color="inherit"
            onClick={handleSaveDraft}
            disabled={saving}
          >
            {saving ? "Ukládání..." : "Uložit jako návrh"}
          </Button>
          <Button onClick={handleSaveAndConfirm} disabled={saving}>
            {saving ? "Ukládání..." : "Uložit a potvrdit"}
          </Button>
        </Box>
      </Box>

      {/* Header fields */}
      <Card sx={{ mb: 3 }}>
        <Typography variant="subtitle2" sx={{ mb: 2, fontWeight: 600 }}>
          Základní údaje
        </Typography>
        <Field label="Projekt" error={errors.project_id}>
          <Select
            value={form.project_id === null ? "" : String(form.project_id)}
            onChange={(val) =>
              setForm((prev) => ({
                ...prev,
                project_id: val === "" ? null : Number(val),
              }))
            }
            options={projectOptions}
          />
        </Field>
        <Field label="Poznámky">
          <TextField
            multiline
            minRows={3}
            value={form.notes}
            onChange={(e) =>
              setForm((prev) => ({ ...prev, notes: e.target.value }))
            }
            placeholder="Volitelné poznámky"
          />
        </Field>
      </Card>

      {/* Lines */}
      <Card sx={{ mb: 3 }}>
        <Typography variant="subtitle2" sx={{ mb: 2, fontWeight: 600 }}>
          Položky
        </Typography>
        {errors.items && (
          <Typography
            variant="caption"
            color="error"
            sx={{ display: "block", mb: 1.5 }}
          >
            {errors.items}
          </Typography>
        )}
        <Box sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}>
          {items.map((item, index) => (
            <Box
              key={item.key}
              sx={{
                display: "grid",
                gridTemplateColumns: {
                  xs: "1fr",
                  md: "minmax(160px, 1.6fr) minmax(160px, 1.6fr) 100px 100px minmax(130px, 1.1fr) minmax(120px, 1.2fr) auto",
                },
                gap: 1,
                alignItems: "start",
              }}
            >
              <ItemPicker
                value={item.item_id}
                itemName={item.item_name}
                onChange={(id) => updateItem(index, "item_id", id)}
              />
              <BatchSelect
                itemId={item.item_id}
                value={item.batch_id}
                onChange={(batchId, unitPrice) => {
                  updateItem(index, "batch_id", batchId);
                  updateItem(index, "unit_price", unitPrice);
                }}
              />
              <TextField
                type="number"
                value={item.quantity || ""}
                onChange={(e) =>
                  updateItem(index, "quantity", parseDecimal(e.target.value))
                }
                inputProps={{
                  min: 0,
                  step: 0.001,
                  inputMode: "decimal",
                  pattern: "[0-9]+([\\.,][0-9]+)?",
                  "aria-label": `Množství, řádek ${index + 1}`,
                }}
                placeholder="Množství"
              />
              <TextField
                type="number"
                value={item.unit_price || ""}
                disabled
                inputProps={{
                  min: 0,
                  step: 0.01,
                  inputMode: "decimal",
                  pattern: "[0-9]+([\\.,][0-9]+)?",
                  "aria-label": `Cena za kus, řádek ${index + 1}`,
                }}
                placeholder="Cena/ks"
              />
              <Select
                value={
                  item.location_id === null ? "" : String(item.location_id)
                }
                onChange={(val) =>
                  updateItem(index, "location_id", val ? Number(val) : null)
                }
                options={locationOptions}
              />
              <TextField
                value={item.notes ?? ""}
                onChange={(e) => updateItem(index, "notes", e.target.value)}
                placeholder="Poznámka"
              />
              <IconButton
                color="error"
                onClick={() => removeItem(index)}
                title="Odebrat řádek"
                aria-label="Odebrat řádek"
                sx={{ justifySelf: { xs: "start", md: "center" } }}
              >
                {RemoveIcon}
              </IconButton>
            </Box>
          ))}
        </Box>
        <Button
          variant="outlined"
          color="inherit"
          startIcon={PlusIcon}
          onClick={addItem}
          sx={{ mt: 2 }}
        >
          Přidat položku
        </Button>
      </Card>
    </PageEnter>
  );
}
