import {
  useState,
  useEffect,
  useCallback,
  useMemo,
  useRef,
  type ChangeEvent,
} from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAlert } from "../context/AlertContext";
import { useAuth } from "../context/AuthContext";
import { useParams, useNavigate, Link as RouterLink } from "react-router-dom";
import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import CircularProgress from "@mui/material/CircularProgress";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Checkbox from "@mui/material/Checkbox";
import useMediaQuery from "@mui/material/useMediaQuery";
import { useTheme } from "@mui/material/styles";
import {
  offerDetailOptions,
  offerCustomersOptions,
  scopeTemplatesOptions,
  offerNextNumberOptions,
  itemTemplatesOptions,
  type ItemTemplate,
  type OfferOrderInfo,
  type Customer,
} from "../lib/queries/offers";

import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  TouchSensor,
  useSensor,
  useSensors,
  type DragEndEvent,
} from "@dnd-kit/core";
import {
  SortableContext,
  verticalListSortingStrategy,
  useSortable,
  arrayMove,
} from "@dnd-kit/sortable";
import {
  restrictToVerticalAxis,
  restrictToParentElement,
} from "@dnd-kit/modifiers";
import { CSS } from "@dnd-kit/utilities";
import Forbidden from "../components/Forbidden";
import RichEditor from "../components/RichEditor";
import useDebounce from "../hooks/useDebounce";
import apiFetch from "../utils/api";
import { formatCurrency, todayLocalStr } from "../utils/formatters";
import { companySettingsOptions } from "../lib/queries/settings";
import {
  Button,
  Card,
  TextField,
  Select,
  DateField,
  Field,
  StatusChip,
  Modal,
  ConfirmDialog,
  EmptyState,
  LoadingState,
  PageEnter,
  headerActionsSx,
} from "../ui";

const API_BASE = "/api/admin";
const DRAFT_KEY = "boha_offer_draft";

interface OfferItem {
  _key: string;
  id?: number;
  description: string;
  item_description: string;
  quantity: number;
  unit: string;
  unit_price: number;
  is_included_in_total: boolean;
}

interface ScopeSection {
  title: string;
  title_cz: string;
  content: string;
}

interface OfferForm {
  quotation_number: string;
  project_code: string;
  customer_id: number | null;
  customer_name: string;
  created_at: string;
  valid_until: string;
  currency: string;
  language: string;
  vat_rate: number;
  apply_vat: boolean;
}

const emptyForm: OfferForm = {
  quotation_number: "",
  project_code: "",
  customer_id: null,
  customer_name: "",
  created_at: todayLocalStr(),
  valid_until: "",
  currency: "CZK",
  language: "EN",
  vat_rate: 21,
  apply_vat: false,
};

const emptyScopeSection = (): ScopeSection => ({
  title: "",
  title_cz: "",
  content: "",
});

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 FileIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
    <polyline points="14 2 14 8 20 8" />
  </svg>
);

const DragIcon = (
  <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
    <circle cx="9" cy="5" r="1.5" />
    <circle cx="15" cy="5" r="1.5" />
    <circle cx="9" cy="12" r="1.5" />
    <circle cx="15" cy="12" r="1.5" />
    <circle cx="9" cy="19" r="1.5" />
    <circle cx="15" cy="19" r="1.5" />
  </svg>
);

const RemoveIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <line x1="18" y1="6" x2="6" y2="18" />
    <line x1="6" y1="6" x2="18" y2="18" />
  </svg>
);

const UpIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <polyline points="18 15 12 9 6 15" />
  </svg>
);

const DownIcon = (
  <svg
    width="16"
    height="16"
    viewBox="0 0 24 24"
    fill="none"
    stroke="currentColor"
    strokeWidth="2"
  >
    <polyline points="6 9 12 15 18 9" />
  </svg>
);

function SortableItemRow({
  item,
  index,
  currency,
  readOnly,
  canDelete,
  onUpdate,
  onRemove,
}: {
  item: OfferItem;
  index: number;
  currency: string;
  readOnly: boolean;
  canDelete: boolean;
  onUpdate: (field: string, value: unknown) => void;
  onRemove: () => void;
}) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: item._key, disabled: readOnly });
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
    background: isDragging ? "var(--mui-palette-action-hover)" : undefined,
    position: "relative" as const,
    zIndex: isDragging ? 10 : undefined,
  };
  const lineTotal =
    (Number(item.quantity) || 0) * (Number(item.unit_price) || 0);

  if (isMobile) {
    return (
      <Box
        ref={setNodeRef}
        sx={{
          border: 1,
          borderColor: "divider",
          borderRadius: 2,
          p: 1.5,
          display: "flex",
          flexDirection: "column",
          gap: 1.25,
          bgcolor: "background.paper",
          ...style,
        }}
      >
        <Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
          {!readOnly && (
            <IconButton
              size="small"
              {...attributes}
              {...listeners}
              title="Přetáhnout"
              aria-label="Přetáhnout"
              sx={{ cursor: "grab", color: "text.secondary" }}
            >
              {DragIcon}
            </IconButton>
          )}
          <Typography
            variant="caption"
            sx={{ color: "text.secondary", fontWeight: 700 }}
          >
            Položka {index + 1}
          </Typography>
          <Box sx={{ flex: 1 }} />
          {!readOnly && (
            <IconButton
              color="error"
              size="small"
              onClick={onRemove}
              title="Odebrat"
              aria-label="Odebrat"
              disabled={!canDelete}
            >
              {RemoveIcon}
            </IconButton>
          )}
        </Box>
        <TextField
          label="Popis"
          value={item.description}
          onChange={(e) => onUpdate("description", e.target.value)}
          placeholder="Název položky"
          InputProps={{ readOnly }}
        />
        <TextField
          label="Podrobný popis"
          value={item.item_description}
          onChange={(e) => onUpdate("item_description", e.target.value)}
          placeholder="Volitelný"
          InputProps={{ readOnly }}
        />
        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
            gap: 1,
          }}
        >
          <TextField
            label="Množství"
            type="number"
            value={item.quantity}
            onChange={(e) => onUpdate("quantity", parseInt(e.target.value, 10))}
            slotProps={{ htmlInput: { step: "1" } }}
            InputProps={{ readOnly }}
          />
          <TextField
            label="Jednotka"
            value={item.unit}
            onChange={(e) => onUpdate("unit", e.target.value)}
            InputProps={{ readOnly }}
          />
          <TextField
            label="Cena/ks"
            type="number"
            value={item.unit_price}
            onChange={(e) => onUpdate("unit_price", parseFloat(e.target.value))}
            slotProps={{ htmlInput: { step: "0.01" } }}
            InputProps={{ readOnly }}
          />
        </Box>
        <Box
          sx={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
          }}
        >
          <Box
            component="label"
            sx={{
              display: "flex",
              alignItems: "center",
              gap: 0.5,
              cursor: readOnly ? "default" : "pointer",
            }}
          >
            <Checkbox
              checked={item.is_included_in_total}
              onChange={(e) =>
                onUpdate("is_included_in_total", e.target.checked)
              }
              disabled={readOnly}
            />
            <Typography variant="body2">V ceně</Typography>
          </Box>
          <Box sx={{ textAlign: "right" }}>
            <Typography
              variant="caption"
              sx={{ color: "text.secondary", display: "block" }}
            >
              Celkem
            </Typography>
            <Typography
              sx={{
                fontFamily: "'DM Mono', Menlo, monospace",
                fontWeight: 600,
              }}
            >
              {formatCurrency(lineTotal, currency)}
            </Typography>
          </Box>
        </Box>
      </Box>
    );
  }

  return (
    <TableRow ref={setNodeRef} sx={style}>
      {!readOnly && (
        <TableCell sx={{ width: "2rem", px: 0.5 }}>
          <IconButton
            size="small"
            {...attributes}
            {...listeners}
            title="Přetáhnout"
            aria-label="Přetáhnout"
            sx={{ cursor: "grab", color: "text.secondary" }}
          >
            {DragIcon}
          </IconButton>
        </TableCell>
      )}
      <TableCell align="center" sx={{ color: "text.secondary" }}>
        {index + 1}
      </TableCell>
      <TableCell sx={{ verticalAlign: "top" }}>
        <Box sx={{ display: "flex", flexDirection: "column", gap: 0.5 }}>
          <TextField
            value={item.description}
            onChange={(e) => onUpdate("description", e.target.value)}
            placeholder="Název položky"
            InputProps={{ readOnly }}
            sx={{ "& input": { fontWeight: 500 } }}
          />
          <TextField
            value={item.item_description}
            onChange={(e) => onUpdate("item_description", e.target.value)}
            placeholder="Podrobný popis (volitelný)"
            InputProps={{ readOnly }}
            sx={{ "& input": { fontSize: "0.8rem", opacity: 0.8 } }}
          />
        </Box>
      </TableCell>
      <TableCell>
        <TextField
          type="number"
          value={item.quantity}
          onChange={(e) => onUpdate("quantity", parseInt(e.target.value, 10))}
          slotProps={{ htmlInput: { step: "1" } }}
          InputProps={{ readOnly }}
        />
      </TableCell>
      <TableCell>
        <TextField
          value={item.unit}
          onChange={(e) => onUpdate("unit", e.target.value)}
          InputProps={{ readOnly }}
        />
      </TableCell>
      <TableCell>
        <TextField
          type="number"
          value={item.unit_price}
          onChange={(e) => onUpdate("unit_price", parseFloat(e.target.value))}
          slotProps={{ htmlInput: { step: "0.01" } }}
          InputProps={{ readOnly }}
        />
      </TableCell>
      <TableCell align="center">
        <Checkbox
          checked={item.is_included_in_total}
          onChange={(e) => onUpdate("is_included_in_total", e.target.checked)}
          disabled={readOnly}
        />
      </TableCell>
      <TableCell
        align="right"
        sx={{ fontFamily: "'DM Mono', Menlo, monospace", fontWeight: 600 }}
      >
        {formatCurrency(lineTotal, currency)}
      </TableCell>
      {!readOnly && (
        <TableCell>
          <IconButton
            color="error"
            size="small"
            onClick={onRemove}
            title="Odebrat"
            aria-label="Odebrat"
            disabled={!canDelete}
          >
            {RemoveIcon}
          </IconButton>
        </TableCell>
      )}
    </TableRow>
  );
}

function loadOfferDraft(): {
  form?: Record<string, unknown>;
  items?: unknown[];
  sections?: unknown[];
} | null {
  try {
    const raw = localStorage.getItem(DRAFT_KEY);
    return raw ? JSON.parse(raw) : null;
  } catch (e) {
    console.error("Failed to load offer draft:", e);
    return null;
  }
}

export default function OfferDetail() {
  const { id } = useParams();
  const isEdit = Boolean(id);
  const alert = useAlert();
  const { hasPermission } = useAuth();
  const navigate = useNavigate();
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
  const dndSensors = useSensors(
    useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
    useSensor(TouchSensor, {
      activationConstraint: { delay: 200, tolerance: 5 },
    }),
    useSensor(KeyboardSensor),
  );

  const itemKeyCounter = useRef(0);
  const emptyItem = useCallback(
    (): OfferItem => ({
      _key: `item-${++itemKeyCounter.current}`,
      description: "",
      item_description: "",
      quantity: 1,
      unit: "ks",
      unit_price: 0,
      is_included_in_total: true,
    }),
    [],
  );

  const queryClient = useQueryClient();

  // ---- TanStack Query hooks ----
  const offerQuery = useQuery(offerDetailOptions(id));
  const { data: customersData } = useQuery({
    ...offerCustomersOptions(),
    enabled: !isEdit,
  });
  const { data: templatesData } = useQuery(scopeTemplatesOptions());
  const { data: itemTemplates } = useQuery(itemTemplatesOptions());
  const { data: nextNumberData } = useQuery({
    ...offerNextNumberOptions(),
    enabled: !isEdit,
  });
  const customers: Customer[] = Array.isArray(customersData)
    ? customersData
    : [];
  const scopeTemplates = templatesData ?? [];

  const loading = isEdit && offerQuery.isLoading;
  const [saving, setSaving] = useState(false);
  const [errors, setErrors] = useState<Record<string, string | undefined>>({});
  const [form, setForm] = useState<OfferForm>(() => {
    // The draft is the unsaved-NEW-offer buffer — never restore it over an
    // existing offer in edit mode (it would also leak its stale item keys).
    const draft = isEdit ? null : loadOfferDraft();
    if (draft?.form) {
      return {
        quotation_number:
          (draft.form.quotation_number as string) || emptyForm.quotation_number,
        project_code:
          (draft.form.project_code as string) || emptyForm.project_code,
        customer_id:
          (draft.form.customer_id as number | null) ?? emptyForm.customer_id,
        customer_name:
          (draft.form.customer_name as string) || emptyForm.customer_name,
        created_at: (draft.form.created_at as string) || emptyForm.created_at,
        valid_until:
          (draft.form.valid_until as string) || emptyForm.valid_until,
        currency: (draft.form.currency as string) || emptyForm.currency,
        language: (draft.form.language as string) || emptyForm.language,
        vat_rate: (draft.form.vat_rate as number) ?? emptyForm.vat_rate,
        apply_vat: (draft.form.apply_vat as boolean) ?? emptyForm.apply_vat,
      };
    }
    return emptyForm;
  });
  const [items, setItems] = useState<OfferItem[]>(() => {
    const draft = isEdit ? null : loadOfferDraft();
    if (Array.isArray(draft?.items) && draft.items.length > 0) {
      // Re-key restored items: their persisted _key values are stale and the
      // counter restarts at 0 each load, so reusing them would collide with
      // newly-added rows (duplicate React key / dnd-kit id → the warning).
      return (draft.items as OfferItem[]).map((it) => ({
        ...it,
        _key: `item-${++itemKeyCounter.current}`,
      }));
    }
    return [emptyItem()];
  });
  const [sections, setSections] = useState<ScopeSection[]>(() => {
    const draft = isEdit ? null : loadOfferDraft();
    if (Array.isArray(draft?.sections) && draft.sections.length > 0) {
      return draft.sections as ScopeSection[];
    }
    return [];
  });
  const [customerSearch, setCustomerSearch] = useState("");
  const [showCustomerDropdown, setShowCustomerDropdown] = useState(false);
  const [orderInfo, setOrderInfo] = useState<OfferOrderInfo | null>(null);
  const [offerStatus, setOfferStatus] = useState<string>("");

  const [deleteConfirm, setDeleteConfirm] = useState(false);
  const [deleting, setDeleting] = useState(false);
  const [creatingOrder, setCreatingOrder] = useState(false);
  const [showOrderModal, setShowOrderModal] = useState(false);
  const [invalidateConfirm, setInvalidateConfirm] = useState(false);
  const [invalidatingOffer, setInvalidatingOffer] = useState(false);
  const [customerOrderNumber, setCustomerOrderNumber] = useState("");
  const [orderAttachment, setOrderAttachment] = useState<File | null>(null);
  const [pdfLoading, setPdfLoading] = useState(false);
  const blobTimeoutsRef = useRef<ReturnType<typeof setTimeout>[]>([]);
  const { data: companySettings } = useQuery(companySettingsOptions());

  useEffect(() => {
    if (companySettings && !isEdit) {
      setForm((prev) => ({
        ...prev,
        currency:
          prev.currency === "CZK"
            ? companySettings.default_currency || "CZK"
            : prev.currency,
        vat_rate:
          prev.vat_rate === 21
            ? (companySettings.default_vat_rate ?? 21)
            : prev.vat_rate,
      }));
    }
  }, [companySettings, isEdit]);

  const [lockedBy, setLockedBy] = useState<{
    user_id: number;
    username: string;
    full_name: string;
  } | null>(null);
  const heartbeatRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const unlockAbortRef = useRef<AbortController | null>(null);
  const initialSnapshotRef = useRef<string | null>(null);
  // Set to true right after a successful delete so the detail-page error
  // effect doesn't fire "Nepodařilo se načíst nabídku" on top of the
  // success toast (the 404 from a refetched-already-deleted row is
  // expected here, not a real error).
  const deletingRef = useRef(false);

  // Note: Modal applies useDialogScrollLock internally.
  useEffect(() => {
    return () => {
      blobTimeoutsRef.current.forEach(clearTimeout);
    };
  }, []);

  const isInvalidated = offerStatus === "invalidated";
  const isCompleted = orderInfo?.status === "dokoncena";
  const isLockedByOther = !!lockedBy;
  const readOnly = isInvalidated || isLockedByOther || isCompleted;
  const canInvalidate = isEdit && !isInvalidated && !isCompleted && !orderInfo;

  // Sync offer detail data to form state on first load (edit mode)
  const formInitializedRef = useRef(false);
  useEffect(() => {
    if (!offerQuery.data || formInitializedRef.current) return;
    const d = offerQuery.data;
    const formData: OfferForm = {
      quotation_number: d.quotation_number || "",
      project_code: d.project_code || "",
      customer_id: d.customer_id ?? null,
      customer_name: d.customer_name || "",
      created_at: d.created_at ? d.created_at.substring(0, 10) : "",
      valid_until: d.valid_until ? d.valid_until.substring(0, 10) : "",
      currency: d.currency || companySettings?.default_currency || "CZK",
      language: d.language || "EN",
      vat_rate: d.vat_rate ?? companySettings?.default_vat_rate ?? 21,
      apply_vat: !!d.apply_vat,
    };
    setForm(formData);
    const mappedItems =
      Array.isArray(d.items) && d.items.length
        ? d.items.map((it) => ({
            ...it,
            _key: `item-${++itemKeyCounter.current}`,
          }))
        : [emptyItem()];
    setItems(mappedItems);
    const mappedSections =
      Array.isArray(d.sections) && d.sections.length
        ? d.sections.map((s) => ({
            title: s.title || "",
            title_cz: s.title_cz || "",
            content: s.content || "",
          }))
        : [];
    setSections(mappedSections);
    initialSnapshotRef.current = JSON.stringify({
      form: formData,
      items: mappedItems,
      sections: mappedSections,
    });
    setOfferStatus(d.status || "");
    setOrderInfo(d.order ?? null);
    setLockedBy(d.locked_by ?? null);

    // Try to acquire lock if not locked by someone else, not invalidated, and not completed
    if (
      !d.locked_by &&
      d.status !== "invalidated" &&
      d.order?.status !== "dokoncena" &&
      hasPermission("offers.edit")
    ) {
      apiFetch(`${API_BASE}/offers/${id}/lock`, { method: "POST" }).catch(
        () => {},
      );
    }
    formInitializedRef.current = true;
  }, [offerQuery.data, companySettings, hasPermission, id, emptyItem]);

  // Redirect on offer fetch error (edit mode).
  // Suppress when deletingRef is set: the in-flight refetch of a row we
  // just deleted will 404, and we don't want a "load failed" toast on
  // top of the success toast.
  useEffect(() => {
    if (isEdit && offerQuery.isError && !deletingRef.current) {
      alert.error("Nepodařilo se načíst nabídku");
      navigate("/offers");
    }
  }, [isEdit, offerQuery.isError, alert, navigate]);

  // Sync next-number data to form (create mode)
  useEffect(() => {
    if (isEdit || !nextNumberData) return;
    const num = nextNumberData.next_number || nextNumberData.number || "";
    if (num) {
      setForm((prev) => ({ ...prev, quotation_number: num }));
    }
  }, [isEdit, nextNumberData]);

  // Heartbeat to keep lock alive + cleanup on unmount
  useEffect(() => {
    if (!isEdit || !id || isLockedByOther || isInvalidated || isCompleted)
      return;

    heartbeatRef.current = setInterval(() => {
      apiFetch(`${API_BASE}/offers/${id}/heartbeat`, { method: "POST" })
        .then((res) => {
          // 401 here means the access token expired AND the refresh failed
          // (session truly gone — apiFetch retries with a refreshed token on a
          // recoverable 401 and would return 200). Stop the interval so we don't
          // spam a 401 every 10s while the user sits idle on a dead session;
          // apiFetch has already flagged session-expired for the next action.
          if (res.status === 401 && heartbeatRef.current) {
            clearInterval(heartbeatRef.current);
            heartbeatRef.current = null;
          }
        })
        .catch(() => {});
    }, 10 * 1000); // every 10 seconds

    return () => {
      if (heartbeatRef.current) clearInterval(heartbeatRef.current);
      if (unlockAbortRef.current) unlockAbortRef.current.abort();
      // Release lock on unmount
      const controller = new AbortController();
      unlockAbortRef.current = controller;
      apiFetch(`${API_BASE}/offers/${id}/unlock`, {
        method: "POST",
        signal: controller.signal,
      }).catch(() => {});
    };
  }, [isEdit, id, isLockedByOther, isInvalidated, isCompleted]);

  // Capture initial snapshot after loading completes (create mode)
  if (!loading && !initialSnapshotRef.current) {
    initialSnapshotRef.current = JSON.stringify({ form, items, sections });
  }

  const isDirty = useMemo(() => {
    if (!initialSnapshotRef.current) return false;
    return (
      JSON.stringify({ form, items, sections }) !== initialSnapshotRef.current
    );
  }, [form, items, sections]);

  useEffect(() => {
    if (!isDirty) return;
    const handler = (e: BeforeUnloadEvent) => {
      e.preventDefault();
      e.returnValue = "";
    };
    window.addEventListener("beforeunload", handler);
    return () => window.removeEventListener("beforeunload", handler);
  }, [isDirty]);

  // Close dropdown on outside click
  useEffect(() => {
    const handleClickOutside = () => setShowCustomerDropdown(false);
    if (showCustomerDropdown) {
      document.addEventListener("click", handleClickOutside);
      return () => document.removeEventListener("click", handleClickOutside);
    }
  }, [showCustomerDropdown]);

  // Auto-save draft to localStorage (create mode only)
  const draftPayload = JSON.stringify({ form, items, sections });
  const debouncedDraft = useDebounce(draftPayload, 1500);
  useEffect(() => {
    if (isEdit) return;
    try {
      const data = JSON.parse(debouncedDraft);
      const draft = {
        form: {
          project_code: data.form.project_code ?? "",
          customer_id: data.form.customer_id ?? null,
          customer_name: data.form.customer_name ?? "",
          created_at: data.form.created_at ?? "",
          valid_until: data.form.valid_until ?? "",
          currency: data.form.currency ?? "CZK",
          language: data.form.language ?? "EN",
          vat_rate: data.form.vat_rate ?? 21,
          apply_vat: data.form.apply_vat ?? false,
        },
        items: data.items,
        sections: data.sections,
        savedAt: new Date().toISOString(),
      };
      localStorage.setItem(DRAFT_KEY, JSON.stringify(draft));
    } catch (e) {
      console.error("Failed to save offer draft:", e);
    }
  }, [debouncedDraft]); // eslint-disable-line react-hooks/exhaustive-deps

  const updateForm = (field: keyof OfferForm, value: unknown) => {
    setForm((prev) => ({ ...prev, [field]: value }));
    setErrors((prev) => ({ ...prev, [field]: undefined }));
  };

  const selectCustomer = (c: Customer) => {
    setForm((prev) => ({ ...prev, customer_id: c.id, customer_name: c.name }));
    setErrors((prev) => ({ ...prev, customer_id: undefined }));
    setCustomerSearch("");
    setShowCustomerDropdown(false);
  };

  const clearCustomer = () => {
    setForm((prev) => ({ ...prev, customer_id: null, customer_name: "" }));
  };

  const updateItem = (
    index: number,
    field: keyof OfferItem,
    value: unknown,
  ) => {
    setItems((prev) =>
      prev.map((item, i) => (i === index ? { ...item, [field]: value } : item)),
    );
  };

  const addItem = () => setItems((prev) => [...prev, emptyItem()]);

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

  const subtotal = items.reduce((sum, item) => {
    if (item.is_included_in_total) {
      return (
        sum + (Number(item.quantity) || 0) * (Number(item.unit_price) || 0)
      );
    }
    return sum;
  }, 0);
  const vatAmount = form.apply_vat ? subtotal * (form.vat_rate / 100) : 0;
  const total = subtotal + vatAmount;

  const filteredCustomers = customerSearch
    ? customers.filter((c) =>
        c.name.toLowerCase().includes(customerSearch.toLowerCase()),
      )
    : customers;

  const handleSave = async () => {
    const newErrors: Record<string, string> = {};
    if (!form.customer_id) newErrors.customer_id = "Zákazník je povinný";
    if (!form.created_at) newErrors.created_at = "Datum je povinné";
    if (!form.valid_until) newErrors.valid_until = "Platnost je povinná";
    if (items.length === 0) newErrors.items = "Přidejte alespoň jednu položku";
    setErrors(newErrors);
    if (Object.keys(newErrors).length > 0) return;

    setSaving(true);
    try {
      const url = isEdit ? `${API_BASE}/offers/${id}` : `${API_BASE}/offers`;
      const payload: any = {
        ...form,
        items: items.map((item, i) => ({ ...item, position: i })),
        sections: sections.map((s, i) => ({ ...s, position: i })),
      };
      if (!isEdit) delete payload.quotation_number;

      const response = await apiFetch(url, {
        method: isEdit ? "PUT" : "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(payload),
      });
      const result = await response.json();
      if (result.success) {
        const offerId = isEdit ? id : result.data?.id;
        if (offerId) {
          await apiFetch(`${API_BASE}/offers-pdf/${offerId}?save=1`).catch(
            () => {},
          );
        }
        alert.success(
          result.message ||
            (isEdit ? "Nabídka byla aktualizována" : "Nabídka byla vytvořena"),
        );
        if (!isEdit) {
          try {
            localStorage.removeItem(DRAFT_KEY);
          } catch (e) {
            console.error("Failed to remove offer draft:", e);
          }
        }
        if (!isEdit && result.data?.id) {
          queryClient.invalidateQueries({ queryKey: ["offers"] });
          queryClient.invalidateQueries({ queryKey: ["orders"] });
          queryClient.invalidateQueries({ queryKey: ["projects"] });
          queryClient.invalidateQueries({ queryKey: ["invoices"] });
          navigate(`/offers/${result.data.id}`);
        }
        if (isEdit) {
          initialSnapshotRef.current = JSON.stringify({
            form,
            items,
            sections,
          });
          queryClient.invalidateQueries({ queryKey: ["offers"] });
          queryClient.invalidateQueries({ queryKey: ["orders"] });
          queryClient.invalidateQueries({ queryKey: ["projects"] });
          queryClient.invalidateQueries({ queryKey: ["invoices"] });
        }
      } else {
        alert.error(result.error || "Nepodařilo se uložit nabídku");
      }
    } catch {
      alert.error("Chyba připojení");
    } finally {
      setSaving(false);
    }
  };

  const handleCreateOrder = async () => {
    if (!customerOrderNumber.trim()) {
      alert.error("Číslo objednávky zákazníka je povinné");
      return;
    }
    setCreatingOrder(true);
    try {
      let fetchOptions: RequestInit;
      if (orderAttachment) {
        // With attachment: send as multipart/form-data
        const formData = new FormData();
        formData.append("quotationId", String(id));
        formData.append("customerOrderNumber", customerOrderNumber.trim());
        formData.append("attachment", orderAttachment);
        fetchOptions = { method: "POST", body: formData };
      } else {
        // Without attachment: send as JSON
        fetchOptions = {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            quotationId: id,
            customerOrderNumber: customerOrderNumber.trim(),
          }),
        };
      }
      const response = await apiFetch(`${API_BASE}/orders`, fetchOptions);
      const result = await response.json();
      if (result.success) {
        setShowOrderModal(false);
        alert.success(result.message || "Objednávka byla vytvořena");
        await queryClient.invalidateQueries({ queryKey: ["offers"] });
        await queryClient.invalidateQueries({ queryKey: ["orders"] });
        await queryClient.invalidateQueries({ queryKey: ["projects"] });
        await queryClient.invalidateQueries({ queryKey: ["invoices"] });
        navigate(`/orders/${result.data.order_id}`);
      } else {
        alert.error(result.error || "Nepodařilo se vytvořit objednávku");
      }
    } catch {
      alert.error("Chyba připojení");
    } finally {
      setCreatingOrder(false);
    }
  };

  const handleInvalidateOffer = async () => {
    setInvalidatingOffer(true);
    try {
      const response = await apiFetch(`${API_BASE}/offers/${id}/invalidate`, {
        method: "POST",
      });
      const result = await response.json();
      if (result.success) {
        setInvalidateConfirm(false);
        setOfferStatus("invalidated");
        alert.success(result.message || "Nabídka byla zneplatněna");
        queryClient.invalidateQueries({ queryKey: ["offers"] });
        queryClient.invalidateQueries({ queryKey: ["orders"] });
        queryClient.invalidateQueries({ queryKey: ["projects"] });
        queryClient.invalidateQueries({ queryKey: ["invoices"] });
      } else {
        alert.error(result.error || "Nepodařilo se zneplatnit nabídku");
      }
    } catch {
      alert.error("Chyba připojení");
    } finally {
      setInvalidatingOffer(false);
    }
  };

  const handleDelete = async () => {
    setDeleting(true);
    try {
      const response = await apiFetch(`${API_BASE}/offers/${id}`, {
        method: "DELETE",
      });
      const result = await response.json();
      if (result.success) {
        // Mark the row as gone before the list invalidation refetches the
        // detail key (which would 404 and trigger the error-toast effect).
        deletingRef.current = true;
        queryClient.removeQueries({ queryKey: ["offers", id] });
        alert.success(result.message || "Nabídka byla smazána");
        await queryClient.invalidateQueries({ queryKey: ["offers"] });
        await queryClient.invalidateQueries({ queryKey: ["orders"] });
        await queryClient.invalidateQueries({ queryKey: ["projects"] });
        await queryClient.invalidateQueries({ queryKey: ["invoices"] });
        navigate("/offers");
      } else {
        alert.error(result.error || "Nepodařilo se smazat nabídku");
      }
    } catch {
      alert.error("Chyba připojení");
    } finally {
      setDeleting(false);
      setDeleteConfirm(false);
    }
  };

  const handlePdf = async () => {
    if (!isEdit || pdfLoading) return;
    const newWindow = window.open("", "_blank");
    setPdfLoading(true);
    try {
      const response = await apiFetch(`${API_BASE}/offers/${id}/file`);
      if (response.status === 401) {
        newWindow?.close();
        return;
      }
      if (!response.ok) {
        newWindow?.close();
        alert.error("PDF soubor nenalezen — uložte nabídku pro vygenerování");
        return;
      }
      const blob = await response.blob();
      const url = URL.createObjectURL(blob);
      if (newWindow) newWindow.location.href = url;
      const timeoutId = setTimeout(() => URL.revokeObjectURL(url), 60000);
      blobTimeoutsRef.current.push(timeoutId);
    } catch {
      newWindow?.close();
      alert.error("Chyba při generování PDF");
    } finally {
      setPdfLoading(false);
    }
  };

  const getRequiredPerm = () => {
    if (!isEdit) return "offers.create";
    return isInvalidated || isCompleted ? "offers.view" : "offers.edit";
  };
  const requiredPerm = getRequiredPerm();
  if (!hasPermission(requiredPerm)) return <Forbidden />;

  if (loading) {
    return <LoadingState />;
  }
  return (
    <PageEnter>
      {/* Header */}
      <Box>
        <Box
          sx={{
            display: "flex",
            alignItems: "flex-start",
            justifyContent: "space-between",
            flexWrap: "wrap",
            gap: 2,
            mb: 3,
          }}
        >
          <Box sx={{ display: "flex", alignItems: "center", gap: 2 }}>
            <Button
              component={RouterLink}
              to="/offers"
              variant="outlined"
              color="inherit"
              startIcon={BackIcon}
            >
              Zpět
            </Button>
            <Box
              sx={{
                display: "flex",
                alignItems: "center",
                gap: 1.5,
                flexWrap: "wrap",
              }}
            >
              <Typography variant="h4">
                {isEdit ? `Nabídka ${form.quotation_number}` : "Nová nabídka"}
              </Typography>
              {isInvalidated && (
                <StatusChip label="Zneplatněna" color="error" />
              )}
              {isCompleted && <StatusChip label="Dokončeno" color="success" />}
            </Box>
          </Box>
          <Box sx={headerActionsSx}>
            {isEdit && hasPermission("offers.export") && (
              <Button
                onClick={handlePdf}
                variant="outlined"
                color="inherit"
                disabled={pdfLoading}
                startIcon={
                  pdfLoading ? (
                    <CircularProgress size={16} color="inherit" />
                  ) : (
                    FileIcon
                  )
                }
              >
                Zobrazit nabídku
              </Button>
            )}
            {isEdit &&
              !readOnly &&
              hasPermission("orders.create") &&
              !orderInfo && (
                <Button
                  onClick={() => {
                    setCustomerOrderNumber("");
                    setOrderAttachment(null);
                    setShowOrderModal(true);
                  }}
                  variant="outlined"
                  color="inherit"
                >
                  Vytvořit objednávku
                </Button>
              )}
            {isEdit && orderInfo && (
              <Button
                component={RouterLink}
                to={`/orders/${orderInfo.id}`}
                variant="outlined"
                color="inherit"
              >
                Objednávka {orderInfo.order_number}
              </Button>
            )}
            {canInvalidate && hasPermission("offers.edit") && (
              <Button
                onClick={() => setInvalidateConfirm(true)}
                variant="outlined"
                color="inherit"
              >
                Zneplatnit
              </Button>
            )}
            {!readOnly && (
              <Button onClick={handleSave} disabled={saving}>
                {saving ? "Ukládání..." : "Uložit"}
              </Button>
            )}
            {isEdit && hasPermission("offers.delete") && (
              <Button
                onClick={() => setDeleteConfirm(true)}
                variant="outlined"
                color="error"
              >
                Smazat
              </Button>
            )}
          </Box>
        </Box>
      </Box>

      {/* Lock banner */}
      {isLockedByOther && (
        <Box
          sx={{
            bgcolor:
              "color-mix(in srgb, var(--mui-palette-warning-main) 15%, transparent)",
            border: 1,
            borderColor: "warning.main",
            borderRadius: 1,
            px: 2,
            py: 1.5,
            display: "flex",
            alignItems: "center",
            gap: 1,
            mb: 2,
            fontSize: "0.875rem",
            color: "warning.main",
          }}
        >
          <svg
            width="18"
            height="18"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="2"
          >
            <rect x="3" y="11" width="18" height="11" rx="2" ry="2" />
            <path d="M7 11V7a5 5 0 0 1 10 0v4" />
          </svg>
          <span>
            Nabídku právě upravuje <strong>{lockedBy!.full_name}</strong>.
            Můžete ji pouze prohlížet.
          </span>
        </Box>
      )}

      {/* Quotation Form */}
      <Card sx={{ mb: 3 }}>
        <Typography variant="subtitle2" sx={{ mb: 2, fontWeight: 600 }}>
          Základní údaje
        </Typography>
        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: { xs: "1fr", md: "1fr 1fr 1fr" },
            gap: 2,
          }}
        >
          <Field label="Číslo nabídky">
            <TextField
              value={form.quotation_number}
              InputProps={{ readOnly: true }}
              sx={{ "& .MuiInputBase-root": { bgcolor: "action.hover" } }}
            />
          </Field>
          <Field label="Kód projektu">
            <TextField
              value={form.project_code}
              onChange={(e) => updateForm("project_code", e.target.value)}
              placeholder="Volitelný kód projektu"
              InputProps={{ readOnly }}
            />
          </Field>
          <Field label="Zákazník" error={errors.customer_id} required>
            {form.customer_id ? (
              <Box
                sx={{
                  display: "flex",
                  alignItems: "center",
                  gap: 1,
                  px: 1.5,
                  py: 1,
                  border: 1,
                  borderColor: "divider",
                  borderRadius: 1,
                }}
              >
                <Box component="span" sx={{ flex: 1 }}>
                  {form.customer_name}
                </Box>
                {!readOnly && (
                  <IconButton
                    size="small"
                    onClick={clearCustomer}
                    title="Odebrat zákazníka"
                    aria-label="Odebrat zákazníka"
                  >
                    <svg
                      width="14"
                      height="14"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="currentColor"
                      strokeWidth="2"
                    >
                      <line x1="18" y1="6" x2="6" y2="18" />
                      <line x1="6" y1="6" x2="18" y2="18" />
                    </svg>
                  </IconButton>
                )}
              </Box>
            ) : (
              <Box
                sx={{ position: "relative" }}
                onClick={(e) => e.stopPropagation()}
              >
                <TextField
                  value={customerSearch}
                  onChange={(e) => {
                    setCustomerSearch(e.target.value);
                    setShowCustomerDropdown(true);
                  }}
                  onFocus={() => setShowCustomerDropdown(true)}
                  placeholder="Hledat zákazníka..."
                  InputProps={{ readOnly }}
                />
                {showCustomerDropdown && !isInvalidated && (
                  <Box
                    sx={{
                      position: "absolute",
                      top: "100%",
                      left: 0,
                      right: 0,
                      zIndex: 20,
                      mt: 0.5,
                      maxHeight: 280,
                      overflowY: "auto",
                      bgcolor: "background.paper",
                      border: 1,
                      borderColor: "divider",
                      borderRadius: 1,
                      boxShadow: 3,
                    }}
                  >
                    {filteredCustomers.length === 0 ? (
                      <Box sx={{ px: 1.5, py: 1, color: "text.secondary" }}>
                        Žádní zákazníci
                      </Box>
                    ) : (
                      filteredCustomers.slice(0, 20).map((c) => (
                        <Box
                          key={c.id}
                          onMouseDown={() => selectCustomer(c)}
                          sx={{
                            px: 1.5,
                            py: 1,
                            cursor: "pointer",
                            "&:hover": { bgcolor: "action.hover" },
                          }}
                        >
                          <Box>{c.name}</Box>
                          {c.city && (
                            <Box
                              sx={{
                                fontSize: "0.8rem",
                                color: "text.secondary",
                              }}
                            >
                              {c.city}
                            </Box>
                          )}
                        </Box>
                      ))
                    )}
                  </Box>
                )}
              </Box>
            )}
          </Field>
        </Box>

        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr" },
            gap: 2,
          }}
        >
          <Field label="Datum vytvoření" error={errors.created_at} required>
            {readOnly ? (
              <TextField
                value={form.created_at}
                InputProps={{ readOnly: true }}
              />
            ) : (
              <DateField
                value={form.created_at}
                onChange={(val) => {
                  updateForm("created_at", val);
                  setErrors((prev) => ({ ...prev, created_at: undefined }));
                }}
              />
            )}
          </Field>
          <Field label="Platnost do" error={errors.valid_until} required>
            {readOnly ? (
              <TextField
                value={form.valid_until}
                InputProps={{ readOnly: true }}
              />
            ) : (
              <DateField
                value={form.valid_until}
                onChange={(val) => {
                  updateForm("valid_until", val);
                  setErrors((prev) => ({
                    ...prev,
                    valid_until: undefined,
                  }));
                }}
              />
            )}
          </Field>
        </Box>

        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr" },
            gap: 2,
          }}
        >
          <Field label="Měna">
            <Select
              value={form.currency}
              onChange={(val) => updateForm("currency", val)}
              disabled={readOnly}
              options={(
                companySettings?.available_currencies || [
                  "CZK",
                  "EUR",
                  "USD",
                  "GBP",
                ]
              ).map((c) => ({ value: c, label: c }))}
            />
          </Field>
          <Field label="Jazyk nabídky">
            <Select
              value={form.language}
              onChange={(val) => updateForm("language", val)}
              disabled={readOnly}
              options={[
                { value: "EN", label: "English" },
                { value: "CZ", label: "Čeština" },
              ]}
            />
          </Field>
        </Box>

        <Box
          sx={{
            display: "grid",
            gridTemplateColumns: { xs: "1fr", md: "1fr 1fr 1fr" },
            gap: 2,
          }}
        >
          <Field label="Sazba DPH (%)">
            <Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
              <Select
                value={String(form.vat_rate)}
                onChange={(val) => updateForm("vat_rate", parseFloat(val) || 0)}
                disabled={readOnly}
                sx={{ flex: 1 }}
                options={(
                  companySettings?.available_vat_rates || [0, 10, 12, 15, 21]
                ).map((r) => ({ value: String(r), label: `${r}%` }))}
              />
              <Box
                component="label"
                sx={{
                  display: "flex",
                  alignItems: "center",
                  whiteSpace: "nowrap",
                  cursor: readOnly ? "default" : "pointer",
                }}
              >
                <Checkbox
                  checked={form.apply_vat}
                  onChange={(e) => updateForm("apply_vat", e.target.checked)}
                  disabled={readOnly}
                />
                <Box component="span">Účtovat DPH</Box>
              </Box>
            </Box>
          </Field>
        </Box>
      </Card>

      {/* Items Section with drag-and-drop */}
      <Card sx={{ mb: 3 }}>
        <Box
          sx={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            mb: 2,
          }}
        >
          <Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
            Položky
          </Typography>
          {!readOnly && (
            <Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
              {itemTemplates && itemTemplates.length > 0 && (
                <Select
                  value=""
                  onChange={(val) => {
                    const templateId = Number(val);
                    if (!templateId) return;
                    const template = itemTemplates.find(
                      (t: ItemTemplate) => t.id === templateId,
                    );
                    if (template) {
                      setItems((prev) => [
                        ...prev,
                        {
                          _key: `item-${++itemKeyCounter.current}`,
                          description: template.name || "",
                          item_description: template.description || "",
                          quantity: 1,
                          unit: "ks",
                          unit_price: template.default_price || 0,
                          is_included_in_total: true,
                        },
                      ]);
                      alert.success(
                        `Načtena šablona položky "${template.name}"`,
                      );
                    }
                  }}
                  sx={{ minWidth: 160 }}
                  options={[
                    { value: "", label: "Ze šablony..." },
                    ...itemTemplates.map((t: ItemTemplate) => ({
                      value: String(t.id),
                      label: t.name,
                    })),
                  ]}
                />
              )}
              <Button
                onClick={addItem}
                variant="outlined"
                color="inherit"
                size="small"
              >
                + Přidat položku
              </Button>
            </Box>
          )}
        </Box>
        {errors.items && (
          <Typography
            variant="caption"
            color="error"
            sx={{ display: "block", mb: 1 }}
          >
            {errors.items}
          </Typography>
        )}

        <DndContext
          sensors={dndSensors}
          collisionDetection={closestCenter}
          modifiers={[restrictToVerticalAxis, restrictToParentElement]}
          onDragEnd={(event: DragEndEvent) => {
            const { active, over } = event;
            if (!over || active.id === over.id) return;
            setItems((prev) => {
              const oldIndex = prev.findIndex(
                (i) => i._key === String(active.id),
              );
              const newIndex = prev.findIndex(
                (i) => i._key === String(over.id),
              );
              if (oldIndex === -1 || newIndex === -1) return prev;
              return arrayMove(prev, oldIndex, newIndex);
            });
          }}
        >
          <SortableContext
            items={items.map((i) => i._key)}
            strategy={verticalListSortingStrategy}
          >
            {isMobile ? (
              <Box sx={{ display: "flex", flexDirection: "column", gap: 1.5 }}>
                {items.map((item, index) => (
                  <SortableItemRow
                    key={item._key}
                    item={item}
                    index={index}
                    currency={form.currency}
                    readOnly={readOnly}
                    canDelete={items.length > 1}
                    onUpdate={(field, value) =>
                      updateItem(index, field as keyof OfferItem, value)
                    }
                    onRemove={() => removeItem(index)}
                  />
                ))}
              </Box>
            ) : (
              <TableContainer sx={{ overflowX: "auto" }}>
                <Table
                  size="small"
                  sx={{
                    minWidth: 720,
                    "& td, & th": { borderColor: "divider" },
                  }}
                >
                  <TableHead>
                    <TableRow>
                      {!readOnly && <TableCell sx={{ width: "2rem" }} />}
                      <TableCell sx={{ width: "2.5rem" }} align="center">
                        #
                      </TableCell>
                      <TableCell>Popis</TableCell>
                      <TableCell sx={{ width: "5rem" }}>Množství</TableCell>
                      <TableCell sx={{ width: "5rem" }}>Jednotka</TableCell>
                      <TableCell sx={{ width: "7rem" }}>Cena/ks</TableCell>
                      <TableCell sx={{ width: "4rem" }} align="center">
                        V ceně
                      </TableCell>
                      <TableCell sx={{ width: "7rem" }} align="right">
                        Celkem
                      </TableCell>
                      {!readOnly && <TableCell sx={{ width: "3rem" }} />}
                    </TableRow>
                  </TableHead>
                  <TableBody>
                    {items.map((item, index) => (
                      <SortableItemRow
                        key={item._key}
                        item={item}
                        index={index}
                        currency={form.currency}
                        readOnly={readOnly}
                        canDelete={items.length > 1}
                        onUpdate={(field, value) =>
                          updateItem(index, field as keyof OfferItem, value)
                        }
                        onRemove={() => removeItem(index)}
                      />
                    ))}
                  </TableBody>
                </Table>
              </TableContainer>
            )}
          </SortableContext>
        </DndContext>

        {/* Totals */}
        <Box
          sx={{
            mt: 2,
            ml: "auto",
            maxWidth: 360,
            display: "flex",
            flexDirection: "column",
            gap: 0.5,
          }}
        >
          <Box sx={{ display: "flex", justifyContent: "space-between" }}>
            <Typography variant="body2" color="text.secondary">
              Mezisoučet:
            </Typography>
            <Typography
              variant="body2"
              sx={{ fontFamily: "'DM Mono', Menlo, monospace" }}
            >
              {formatCurrency(subtotal, form.currency)}
            </Typography>
          </Box>
          {form.apply_vat && (
            <Box sx={{ display: "flex", justifyContent: "space-between" }}>
              <Typography variant="body2" color="text.secondary">
                DPH ({form.vat_rate}%):
              </Typography>
              <Typography
                variant="body2"
                sx={{ fontFamily: "'DM Mono', Menlo, monospace" }}
              >
                {formatCurrency(vatAmount, form.currency)}
              </Typography>
            </Box>
          )}
          <Box
            sx={{
              display: "flex",
              justifyContent: "space-between",
              pt: 0.5,
              mt: 0.5,
              borderTop: 1,
              borderColor: "divider",
            }}
          >
            <Typography variant="body2" sx={{ fontWeight: 700 }}>
              Celkem:
            </Typography>
            <Typography
              variant="body2"
              sx={{
                fontFamily: "'DM Mono', Menlo, monospace",
                fontWeight: 700,
              }}
            >
              {formatCurrency(total, form.currency)}
            </Typography>
          </Box>
        </Box>
      </Card>

      {/* Scope/Range Section */}
      <Card sx={{ mb: 3 }}>
        <Box
          sx={{
            display: "flex",
            justifyContent: "space-between",
            alignItems: "center",
            mb: 2,
          }}
        >
          <Typography variant="subtitle2" sx={{ fontWeight: 600 }}>
            Rozsah projektu
          </Typography>
          {!readOnly && (
            <Box sx={{ display: "flex", gap: 1, alignItems: "center" }}>
              {scopeTemplates.length > 0 && (
                <Select
                  value=""
                  onChange={(val) => {
                    const templateId = Number(val);
                    if (!templateId) return;
                    const template = scopeTemplates.find(
                      (t) => t.id === templateId,
                    );
                    if (template?.scope_template_sections?.length) {
                      const newSections = template.scope_template_sections.map(
                        (s) => ({
                          title: s.title || "",
                          title_cz: s.title_cz || "",
                          content: s.content || "",
                        }),
                      );
                      setSections((prev) => [...prev, ...newSections]);
                      alert.success(`Načtena šablona "${template.name}"`);
                    }
                  }}
                  sx={{ minWidth: 160 }}
                  options={[
                    { value: "", label: "Ze šablony..." },
                    ...scopeTemplates.map((t) => ({
                      value: String(t.id),
                      label: t.name,
                    })),
                  ]}
                />
              )}
              <Button
                onClick={() =>
                  setSections((prev) => [...prev, emptyScopeSection()])
                }
                variant="outlined"
                color="inherit"
                size="small"
              >
                + Přidat sekci
              </Button>
            </Box>
          )}
        </Box>

        {sections.length === 0 ? (
          <EmptyState title='Žádné sekce rozsahu. Klikněte na "Přidat sekci" nebo vyberte šablonu.' />
        ) : (
          <Box
            sx={{
              display: "flex",
              flexDirection: "column",
              gap: 3,
              mt: 1,
            }}
          >
            {sections.map((section, idx) => (
              <Box
                key={idx}
                sx={{
                  border: 1,
                  borderColor: "divider",
                  borderRadius: 2,
                  p: 2,
                  bgcolor: "action.hover",
                }}
              >
                <Box
                  sx={{
                    display: "flex",
                    justifyContent: "space-between",
                    alignItems: "center",
                    mb: 1.5,
                  }}
                >
                  <Typography
                    variant="body2"
                    sx={{ fontWeight: 600, color: "text.secondary" }}
                  >
                    Sekce {idx + 1}
                    {(form.language === "CZ"
                      ? section.title_cz
                      : section.title) && (
                      <Box component="span" sx={{ fontWeight: 400, ml: 1 }}>
                        —{" "}
                        {form.language === "CZ"
                          ? section.title_cz || section.title
                          : section.title}
                      </Box>
                    )}
                  </Typography>
                  {!readOnly && (
                    <Box sx={{ display: "flex", gap: 0.25 }}>
                      {idx > 0 && (
                        <IconButton
                          size="small"
                          onClick={() =>
                            setSections((prev) => {
                              const arr = [...prev];
                              [arr[idx - 1], arr[idx]] = [
                                arr[idx],
                                arr[idx - 1],
                              ];
                              return arr;
                            })
                          }
                          title="Posunout nahoru"
                          aria-label="Posunout nahoru"
                        >
                          {UpIcon}
                        </IconButton>
                      )}
                      {idx < sections.length - 1 && (
                        <IconButton
                          size="small"
                          onClick={() =>
                            setSections((prev) => {
                              const arr = [...prev];
                              [arr[idx], arr[idx + 1]] = [
                                arr[idx + 1],
                                arr[idx],
                              ];
                              return arr;
                            })
                          }
                          title="Posunout dolů"
                          aria-label="Posunout dolů"
                        >
                          {DownIcon}
                        </IconButton>
                      )}
                      <IconButton
                        size="small"
                        color="error"
                        onClick={() =>
                          setSections((prev) =>
                            prev.filter((_, i) => i !== idx),
                          )
                        }
                        title="Odebrat sekci"
                        aria-label="Odebrat sekci"
                      >
                        {RemoveIcon}
                      </IconButton>
                    </Box>
                  )}
                </Box>

                <Box
                  sx={{
                    display: "grid",
                    gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr" },
                    gap: 2,
                  }}
                >
                  <Box sx={{ mb: 2 }}>
                    <Box
                      sx={{
                        display: "flex",
                        alignItems: "center",
                        gap: 0.75,
                        mb: 0.5,
                      }}
                    >
                      <StatusChip label="EN" color="info" />
                      <Typography
                        component="label"
                        variant="body2"
                        sx={{ fontWeight: 600, color: "text.secondary" }}
                      >
                        Název sekce
                      </Typography>
                    </Box>
                    <TextField
                      value={section.title}
                      onChange={(e) =>
                        setSections((prev) =>
                          prev.map((s, i) =>
                            i === idx ? { ...s, title: e.target.value } : s,
                          ),
                        )
                      }
                      placeholder="Název sekce (anglicky)"
                      InputProps={{ readOnly }}
                    />
                  </Box>
                  <Box sx={{ mb: 2 }}>
                    <Box
                      sx={{
                        display: "flex",
                        alignItems: "center",
                        gap: 0.75,
                        mb: 0.5,
                      }}
                    >
                      <StatusChip label="CZ" color="success" />
                      <Typography
                        component="label"
                        variant="body2"
                        sx={{ fontWeight: 600, color: "text.secondary" }}
                      >
                        Název sekce
                      </Typography>
                    </Box>
                    <TextField
                      value={section.title_cz}
                      onChange={(e) =>
                        setSections((prev) =>
                          prev.map((s, i) =>
                            i === idx ? { ...s, title_cz: e.target.value } : s,
                          ),
                        )
                      }
                      placeholder="Název sekce (česky)"
                      InputProps={{ readOnly }}
                    />
                  </Box>
                </Box>

                <Field label="Obsah">
                  <RichEditor
                    value={section.content}
                    onChange={(val) =>
                      setSections((prev) =>
                        prev.map((s, i) =>
                          i === idx ? { ...s, content: val } : s,
                        ),
                      )
                    }
                    placeholder="Obsah sekce..."
                    minHeight="120px"
                    readOnly={readOnly}
                  />
                </Field>
              </Box>
            ))}
          </Box>
        )}
      </Card>

      {/* Order modal */}
      <Modal
        isOpen={showOrderModal}
        onClose={() => !creatingOrder && setShowOrderModal(false)}
        onSubmit={handleCreateOrder}
        title="Vytvořit objednávku"
        submitText={creatingOrder ? "Vytváření..." : "Vytvořit"}
        loading={creatingOrder}
        maxWidth="sm"
      >
        <Field label="Číslo objednávky zákazníka" required>
          <TextField
            value={customerOrderNumber}
            onChange={(e: ChangeEvent<HTMLInputElement>) =>
              setCustomerOrderNumber(e.target.value)
            }
            onKeyDown={(e) =>
              e.key === "Enter" && !creatingOrder && handleCreateOrder()
            }
            placeholder="Např. PO-2026-001"
            autoFocus
          />
        </Field>
        <Field label="Příloha (PDF)" hint="Max 10 MB">
          {orderAttachment ? (
            <Box sx={{ display: "flex", alignItems: "center", gap: 1 }}>
              <Box component="span">
                {orderAttachment.name}{" "}
                <Box component="span" sx={{ color: "text.secondary" }}>
                  ({(orderAttachment.size / 1024).toFixed(0)} KB)
                </Box>
              </Box>
              <IconButton
                size="small"
                onClick={() => setOrderAttachment(null)}
                title="Odebrat"
                aria-label="Odebrat"
                sx={{ ml: "auto" }}
              >
                <svg
                  width="16"
                  height="16"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth="2"
                >
                  <path d="M18 6L6 18M6 6l12 12" />
                </svg>
              </IconButton>
            </Box>
          ) : (
            <Button
              component="label"
              variant="outlined"
              color="inherit"
              size="small"
            >
              Vybrat soubor
              <input
                type="file"
                accept="application/pdf"
                onChange={(e: ChangeEvent<HTMLInputElement>) =>
                  setOrderAttachment(e.target.files?.[0] || null)
                }
                style={{ display: "none" }}
              />
            </Button>
          )}
        </Field>
      </Modal>

      <ConfirmDialog
        isOpen={invalidateConfirm}
        onClose={() => setInvalidateConfirm(false)}
        onConfirm={handleInvalidateOffer}
        title="Zneplatnit nabídku"
        message={`Opravdu chcete zneplatnit nabídku "${form.quotation_number}"? Nabídka bude pouze pro čtení a nepůjde upravovat.`}
        confirmText="Zneplatnit"
        cancelText="Zrušit"
        confirmVariant="danger"
        loading={invalidatingOffer}
      />

      <ConfirmDialog
        isOpen={deleteConfirm}
        onClose={() => setDeleteConfirm(false)}
        onConfirm={handleDelete}
        title="Smazat nabídku"
        message={`Opravdu chcete smazat nabídku "${form.quotation_number}"? Budou smazány i všechny položky a sekce. Tato akce je nevratná.`}
        confirmText="Smazat"
        cancelText="Zrušit"
        confirmVariant="danger"
        loading={deleting}
      />
    </PageEnter>
  );
}
