import { useState, useEffect, 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 {
  offerDetailOptions,
  offerCustomersOptions,
  scopeTemplatesOptions,
  offerNextNumberOptions,
  itemTemplatesOptions,
  type ItemTemplate,
  type OfferOrderInfo,
  type Customer,
} from "../lib/queries/offers";
import {
  useApiMutation,
  apiErrorMessage,
  type ApiEnvelope,
} from "../lib/queries/mutations";
import Forbidden from "../components/Forbidden";
import apiFetch from "../utils/api";
import DocumentItemsEditor, {
  emptyDocumentItem,
  nextDocumentItemKey,
  type DocumentItem,
} from "../components/document/DocumentItemsEditor";
import SectionsEditor, {
  type DocumentSection,
} from "../components/document/SectionsEditor";
import LockBanner from "../components/document/LockBanner";
import { useDocumentLock } from "../hooks/useDocumentLock";
import { useUnsavedChangesGuard } from "../hooks/useUnsavedChangesGuard";
import { useDocumentPdf } from "../hooks/useDocumentPdf";
import { numberOr, todayLocalStr } from "../utils/formatters";
import { normalizeDateStr } from "../utils/attendanceHelpers";
import { companySettingsOptions } from "../lib/queries/settings";
import {
  Button,
  Card,
  TextField,
  Select,
  DateField,
  Field,
  StatusChip,
  Modal,
  ConfirmDialog,
  LoadingState,
  PageEnter,
  CustomerPicker,
  headerActionsSx,
} from "../ui";
import {
  OFFER_STATUS,
  statusLabel,
  statusColor,
  documentNumberLabel,
} from "../lib/documentStatus";

const API_BASE = "/api/admin";

// The live (finalized) status for an offer — assigning it (on create or on
// finalizing a draft) makes the backend consume the official quotation number.
const LIVE_STATUS = "active";

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

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

interface OfferItemPayload {
  description: string;
  item_description: string;
  quantity: number;
  unit: string;
  unit_price: number;
  is_included_in_total: boolean;
  position: number;
}

interface OfferSectionPayload {
  title: string;
  title_cz: string;
  content: string;
  position: number;
}

interface OfferSavePayload {
  project_code: string;
  customer_id: number | null;
  created_at: string;
  valid_until: string;
  currency: string;
  language: string;
  items: OfferItemPayload[];
  sections: OfferSectionPayload[];
  status?: string;
}

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

export default function OfferDetail() {
  const { id } = useParams();
  const isEdit = Boolean(id);
  const alert = useAlert();
  const { hasPermission } = useAuth();
  const navigate = useNavigate();
  const queryClient = useQueryClient();

  // ---- TanStack Query hooks ----
  const offerQuery = useQuery(offerDetailOptions(id));
  // Load customers in both modes: the shared CustomerPicker needs the full list
  // (even in edit/read-only mode) to resolve the current customer id → its row.
  const { data: customersData } = useQuery(offerCustomersOptions());
  const { data: templatesData } = useQuery(scopeTemplatesOptions());
  const { data: itemTemplates } = useQuery(itemTemplatesOptions());
  const { data: nextNumberData } = useQuery({
    ...offerNextNumberOptions(),
    enabled: !isEdit,
  });
  const scopeTemplates = templatesData ?? [];
  const { data: companySettings } = useQuery(companySettingsOptions());

  const loading = isEdit && offerQuery.isLoading;
  const [saving, setSaving] = useState(false);
  // Which save action is in flight ("draft" | LIVE_STATUS | "save"), so only the
  // clicked button shows its spinner — `saving` still disables all of them to
  // prevent a concurrent double-submit.
  const [savingAction, setSavingAction] = useState<string | null>(null);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [form, setForm] = useState<OfferForm>(emptyForm);
  const [items, setItems] = useState<DocumentItem[]>(() => [
    emptyDocumentItem(),
  ]);
  const [sections, setSections] = useState<DocumentSection[]>([]);
  const [orderInfo, setOrderInfo] = useState<OfferOrderInfo | null>(null);
  const [offerStatus, setOfferStatus] = useState<string>("");
  const [quotationNumber, setQuotationNumber] = useState("");

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

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

  // 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);

  // The customers lookup may not contain a since-deleted/stale customer a
  // saved offer still references — synthesize a fallback option from the
  // hydrated form state so the picker keeps showing the name and a re-save
  // keeps the same id (same approach as the issued-orders supplier picker).
  const customers = useMemo<Customer[]>(() => {
    const activeCustomers: Customer[] = Array.isArray(customersData)
      ? customersData
      : [];
    if (
      form.customer_id != null &&
      !activeCustomers.some((c) => c.id === form.customer_id)
    ) {
      return [
        ...activeCustomers,
        {
          id: form.customer_id,
          name: form.customer_name || `Zákazník #${form.customer_id}`,
          quotation_count: 0,
        },
      ];
    }
    return activeCustomers;
  }, [customersData, form.customer_id, form.customer_name]);

  const isInvalidated = offerStatus === "invalidated";
  const isCompleted = orderInfo?.status === "dokoncena";
  const validTransitions = offerQuery.data?.valid_transitions ?? [];

  // ─── Editability + shared document hooks ───
  // Fields are editable only in create mode or while draft/active (the
  // backend now 400s field edits on ordered/invalidated offers); an
  // offers.view-only holder opens ANY offer read-only, and a fresh lock held
  // by another user forces read-only too.
  const statusEditable =
    !isEdit || offerStatus === "draft" || offerStatus === "active";
  const {
    lockedBy,
    isLockedByOther,
    setLockedBy,
    acquire: acquireLock,
  } = useDocumentLock({
    baseUrl: isEdit && id ? `${API_BASE}/offers/${id}` : null,
    enabled: isEdit && statusEditable && hasPermission("offers.edit"),
  });
  const readOnly =
    isEdit &&
    (!statusEditable || isLockedByOther || !hasPermission("offers.edit"));

  const canInvalidate =
    isEdit &&
    validTransitions.includes("invalidated") &&
    !isCompleted &&
    !orderInfo &&
    !isLockedByOther;
  // An offer is deletable only when it has NOT spawned an order (orderInfo —
  // deleting would orphan the linked order), is NOT invalidated, and is NOT
  // locked by another user. (Backend rejection of deleting an ordered offer is
  // a separate hardening, out of scope here.)
  const canDelete = isEdit && !orderInfo && !isInvalidated && !isLockedByOther;

  const { markClean } = useUnsavedChangesGuard(
    { form, items, sections },
    !loading,
  );

  const { openPdf, pdfLoading } = useDocumentPdf(
    isEdit && id ? `${API_BASE}/offers/${id}/file` : null,
  );

  // 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 = {
      project_code: d.project_code || "",
      customer_id: d.customer_id ?? null,
      customer_name: d.customer_name || "",
      created_at: normalizeDateStr(d.created_at),
      valid_until: normalizeDateStr(d.valid_until),
      currency: d.currency || companySettings?.default_currency || "CZK",
      language: d.language || "EN",
    };
    setForm(formData);
    setQuotationNumber(d.quotation_number || "");
    const mappedItems =
      Array.isArray(d.items) && d.items.length
        ? d.items.map((it) => ({
            _key: nextDocumentItemKey(),
            id: it.id,
            description: it.description || "",
            item_description: it.item_description || "",
            quantity: numberOr(it.quantity, 1),
            unit: it.unit || "",
            unit_price: Number(it.unit_price) || 0,
            is_included_in_total: it.is_included_in_total !== false,
          }))
        : [emptyDocumentItem()];
    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);
    markClean({ form: formData, items: mappedItems, sections: mappedSections });
    setOfferStatus(d.status || "");
    setOrderInfo(d.order ?? null);
    setLockedBy(d.locked_by ?? null);

    // Acquire the edit lock when nobody holds it, the offer is still
    // editable (draft/active) and the user is allowed to edit.
    if (
      !d.locked_by &&
      (d.status === "draft" || d.status === "active") &&
      d.order?.status !== "dokoncena" &&
      hasPermission("offers.edit")
    ) {
      acquireLock();
    }
    formInitializedRef.current = true;
  }, [
    offerQuery.data,
    companySettings,
    hasPermission,
    setLockedBy,
    acquireLock,
    markClean,
  ]);

  // 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 the headline preview (create mode)
  useEffect(() => {
    if (isEdit || !nextNumberData) return;
    const num = nextNumberData.next_number || nextNumberData.number || "";
    if (num) setQuotationNumber(num);
  }, [isEdit, nextNumberData]);

  // ─── Mutations (transport via useApiMutation; invalidation is handled
  // manually below to preserve the awaited-invalidate ordering) ───
  const saveMutation = useApiMutation<
    OfferSavePayload,
    ApiEnvelope<{ id: number }>
  >({
    url: () => (isEdit ? `${API_BASE}/offers/${id}` : `${API_BASE}/offers`),
    method: () => (isEdit ? "PUT" : "POST"),
    envelope: true,
  });

  const invalidateMutation = useApiMutation<void, ApiEnvelope<null>>({
    url: () => `${API_BASE}/offers/${id}/invalidate`,
    method: () => "POST",
    envelope: true,
  });

  const deleteMutation = useApiMutation<void, ApiEnvelope<null>>({
    url: () => `${API_BASE}/offers/${id}`,
    method: () => "DELETE",
    envelope: true,
  });

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

  const selectCustomer = (customerId: number | null) => {
    const c =
      customerId != null ? customers.find((x) => x.id === customerId) : null;
    setForm((prev) => ({
      ...prev,
      customer_id: customerId,
      customer_name: c?.name ?? "",
    }));
    setErrors((prev) => ({ ...prev, customer_id: "" }));
  };

  const invalidateOfferDomains = () => {
    queryClient.invalidateQueries({ queryKey: ["offers"] });
    queryClient.invalidateQueries({ queryKey: ["orders"] });
    queryClient.invalidateQueries({ queryKey: ["projects"] });
    queryClient.invalidateQueries({ queryKey: ["invoices"] });
  };

  const handleSave = async (targetStatus?: string) => {
    if (readOnly || saving) return;
    const newErrors: Record<string, string> = {};
    if (!form.customer_id) newErrors.customer_id = "Vyberte zákazníka";
    if (!form.created_at) newErrors.created_at = "Zadejte datum";
    if (!form.valid_until) newErrors.valid_until = "Zadejte datum platnosti";
    if (items.length === 0) newErrors.items = "Přidejte alespoň jednu položku";
    setErrors(newErrors);
    if (Object.keys(newErrors).length > 0) return;

    setSaving(true);
    setSavingAction(targetStatus ?? "save");
    try {
      const payload: OfferSavePayload = {
        project_code: form.project_code,
        customer_id: form.customer_id,
        created_at: form.created_at,
        valid_until: form.valid_until,
        currency: form.currency,
        language: form.language,
        items: items.map((item, i) => ({
          description: item.description,
          item_description: item.item_description,
          // Coerce the raw typed strings back to numbers so an empty/partial
          // field never reaches the server as NaN (mirrors the totals math).
          quantity: Number(item.quantity) || 0,
          unit: item.unit,
          unit_price: Number(item.unit_price) || 0,
          is_included_in_total: item.is_included_in_total !== false,
          position: i,
        })),
        sections: sections.map((s, i) => ({
          title: s.title,
          title_cz: s.title_cz,
          content: s.content,
          position: i,
        })),
      };
      // Only set status when a target is given (create-as-draft / create-as-live
      // / finalize). Editing a live offer sends no status — the backend keeps
      // its current status. The quotation number is never sent (drafts have
      // none; it is assigned by the sequence on finalize and is immutable).
      if (targetStatus) payload.status = targetStatus;

      const result = await saveMutation.mutateAsync(payload);
      const offerId = isEdit ? Number(id) : result.data?.id;
      // A draft has no number → skip the PDF save. Only generate/archive the
      // PDF on a live create or a finalize (targetStatus !== "draft").
      // Fire-and-forget: never block the success toast or navigation — but a
      // failure is surfaced, not silently swallowed.
      if (offerId && targetStatus !== "draft") {
        apiFetch(`${API_BASE}/offers-pdf/${offerId}?save=1`)
          .then((res) => {
            if (!res.ok)
              alert.error("Nepodařilo se archivovat PDF nabídky na NAS");
          })
          .catch(() =>
            alert.error("Nepodařilo se archivovat PDF nabídky na NAS"),
          );
      }
      alert.success(
        result.message ||
          (isEdit ? "Nabídka byla uložena" : "Nabídka byla vytvořena"),
      );
      if (!isEdit && result.data?.id) {
        invalidateOfferDomains();
        navigate(`/offers/${result.data.id}`);
      }
      if (isEdit) {
        markClean({ form, items, sections });
        // Finalizing a draft (draft → active) assigns the official number
        // server-side. Reflect the new status immediately and re-hydrate the
        // form from the refetched detail so the now-assigned number renders
        // (the local state already equals what was just persisted, so the
        // re-hydration is non-destructive).
        if (targetStatus && targetStatus !== "draft") {
          setOfferStatus(targetStatus);
          formInitializedRef.current = false;
          await queryClient.invalidateQueries({ queryKey: ["offers", id] });
        }
        invalidateOfferDomains();
      }
    } catch (err) {
      alert.error(
        apiErrorMessage(
          err,
          isEdit
            ? "Nepodařilo se uložit nabídku"
            : "Nepodařilo se vytvořit nabídku",
        ),
      );
    } finally {
      setSaving(false);
      setSavingAction(null);
    }
  };

  // Native form submit (e.g. Enter): route to the right save path. Create →
  // finalize live; editing a draft → save draft (the visible primary button);
  // editing a live offer → plain save (no status change).
  const handleFormSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    if (readOnly) return;
    if (!isEdit) void handleSave(LIVE_STATUS);
    else if (offerStatus === "draft") void handleSave("draft");
    else void handleSave();
  };

  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 result = await invalidateMutation.mutateAsync(undefined);
      setInvalidateConfirm(false);
      setOfferStatus("invalidated");
      alert.success(result.message || "Nabídka byla zneplatněna");
      invalidateOfferDomains();
    } catch (err) {
      alert.error(apiErrorMessage(err, "Nepodařilo se zneplatnit nabídku"));
    } finally {
      setInvalidatingOffer(false);
    }
  };

  const handleDelete = async () => {
    setDeleting(true);
    try {
      const result = await deleteMutation.mutateAsync(undefined);
      // 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");
    } catch (err) {
      alert.error(apiErrorMessage(err, "Nepodařilo se smazat nabídku"));
    } finally {
      setDeleting(false);
      setDeleteConfirm(false);
    }
  };

  // ─── Permission guards (AFTER all hooks) ───
  // A view-only (offers.view) holder can OPEN any offer read-only; create
  // mode requires offers.create.
  if (!hasPermission(isEdit ? "offers.view" : "offers.create")) {
    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,
          }}
        >
          {/* flexWrap: long document titles must drop below the Zpět button
              on phones instead of overflowing the viewport. */}
          <Box
            sx={{
              display: "flex",
              alignItems: "center",
              gap: 2,
              flexWrap: "wrap",
            }}
          >
            <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" : "Nová nabídka"}
                {/* Edit mode: a draft has no number yet → show "Koncept".
                    Create mode: show the previewed next-number when available. */}
                {(isEdit || quotationNumber) && (
                  <Box
                    component="span"
                    sx={{ color: "text.secondary", ml: 1, fontWeight: 400 }}
                  >
                    {isEdit
                      ? documentNumberLabel(quotationNumber)
                      : quotationNumber}
                  </Box>
                )}
              </Typography>
              {isEdit &&
                (isCompleted ? (
                  // Completed is derived from the linked order, not the offer's
                  // own status — surface it (success) over the base chip.
                  <StatusChip label="Dokončená" color="success" />
                ) : (
                  <StatusChip
                    label={statusLabel(OFFER_STATUS, offerStatus)}
                    color={statusColor(OFFER_STATUS, offerStatus)}
                  />
                ))}
            </Box>
          </Box>
          <Box sx={headerActionsSx}>
            {/* Drafts have no number yet — /file 404s for them. */}
            {isEdit &&
              hasPermission("offers.view") &&
              offerStatus !== "draft" && (
                <Button
                  onClick={openPdf}
                  variant="outlined"
                  color="inherit"
                  disabled={pdfLoading}
                  startIcon={
                    pdfLoading ? (
                      <CircularProgress size={16} color="inherit" />
                    ) : (
                      FileIcon
                    )
                  }
                >
                  Zobrazit nabídku
                </Button>
              )}
            {isEdit &&
              !readOnly &&
              offerStatus === "active" &&
              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="error"
              >
                Zneplatnit
              </Button>
            )}
            {/* ── Create mode: two-button save ── */}
            {!isEdit && !readOnly && (
              <>
                <Button
                  variant="outlined"
                  color="inherit"
                  onClick={() => handleSave("draft")}
                  disabled={saving}
                >
                  {savingAction === "draft" ? (
                    <CircularProgress size={16} color="inherit" />
                  ) : (
                    "Uložit koncept"
                  )}
                </Button>
                <Button
                  onClick={() => handleSave(LIVE_STATUS)}
                  disabled={saving}
                >
                  {savingAction === LIVE_STATUS ? (
                    <>
                      <CircularProgress
                        size={16}
                        color="inherit"
                        sx={{ mr: 1 }}
                      />
                      Ukládání...
                    </>
                  ) : (
                    "Vytvořit"
                  )}
                </Button>
              </>
            )}

            {/* ── Edit mode, draft: save-draft + finalize (Aktivovat) ── */}
            {isEdit && !readOnly && offerStatus === "draft" && (
              <>
                <Button
                  variant="outlined"
                  color="inherit"
                  onClick={() => handleSave("draft")}
                  disabled={saving}
                >
                  {savingAction === "draft" ? (
                    <CircularProgress size={16} color="inherit" />
                  ) : (
                    "Uložit koncept"
                  )}
                </Button>
                <Button
                  onClick={() => handleSave(LIVE_STATUS)}
                  disabled={saving}
                >
                  {savingAction === LIVE_STATUS ? (
                    <>
                      <CircularProgress
                        size={16}
                        color="inherit"
                        sx={{ mr: 1 }}
                      />
                      Ukládání...
                    </>
                  ) : (
                    "Aktivovat"
                  )}
                </Button>
              </>
            )}

            {/* ── Edit mode, live (non-draft) offer — unchanged plain save ── */}
            {isEdit && !readOnly && offerStatus !== "draft" && (
              <Button onClick={() => handleSave()} disabled={saving}>
                {savingAction === "save" ? (
                  <>
                    <CircularProgress
                      size={16}
                      color="inherit"
                      sx={{ mr: 1 }}
                    />
                    Ukládání...
                  </>
                ) : (
                  "Uložit"
                )}
              </Button>
            )}
            {canDelete && hasPermission("offers.delete") && (
              <Button
                onClick={() => setDeleteConfirm(true)}
                variant="outlined"
                color="error"
              >
                Smazat
              </Button>
            )}
          </Box>
        </Box>
      </Box>

      {/* Lock banner */}
      <LockBanner lockedBy={lockedBy} entityWord="Nabídku" />

      <form onSubmit={handleFormSubmit}>
        {/* 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", sm: "1fr 1fr" },
              gap: 2,
            }}
          >
            <Field label="Zákazník" error={errors.customer_id} required>
              <CustomerPicker
                customers={customers}
                value={form.customer_id}
                onChange={selectCustomer}
                disabled={readOnly}
                error={errors.customer_id}
                placeholder="Vyberte zákazníka…"
              />
            </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 }}
                slotProps={{ htmlInput: { maxLength: 100 } }}
              />
            </Field>
          </Box>

          <Box
            sx={{
              display: "grid",
              gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr" },
              gap: 2,
            }}
          >
            <Field label="Datum vytvoření" error={errors.created_at} required>
              <DateField
                value={form.created_at}
                disabled={readOnly}
                onChange={(val) => updateForm("created_at", val)}
              />
            </Field>
            <Field label="Platnost do" error={errors.valid_until} required>
              <DateField
                value={form.valid_until}
                disabled={readOnly}
                onChange={(val) => updateForm("valid_until", val)}
              />
            </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>
        </Card>

        {/* Items (drag-and-drop, offers carry the "V ceně" column) */}
        <DocumentItemsEditor
          items={items}
          onChange={setItems}
          currency={form.currency}
          readOnly={readOnly}
          error={errors.items}
          showIncludedInTotal
          itemDescriptionMaxLength={8000}
          templatesSlot={
            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: nextDocumentItemKey(),
                        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,
                  })),
                ]}
              />
            ) : undefined
          }
        />

        {/* Scope/Range Section */}
        <SectionsEditor
          sections={sections}
          onChange={setSections}
          readOnly={readOnly}
          title="Rozsah projektu"
          language={form.language}
          templatesSlot={
            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,
                  })),
                ]}
              />
            ) : undefined
          }
        />
      </form>

      {/* 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 "${documentNumberLabel(
          quotationNumber,
        )}"? 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 "${documentNumberLabel(
          quotationNumber,
        )}"? Budou smazány i všechny položky a sekce. Tato akce je nevratná.`}
        confirmText="Smazat"
        cancelText="Zrušit"
        confirmVariant="danger"
        loading={deleting}
      />
    </PageEnter>
  );
}
