"use client";

import Link from "next/link";
import { useMemo, useState } from "react";
import { useMutation, useSuspenseQuery } from "@tanstack/react-query";
import { toast } from "sonner";
import { AlertModal } from "@/components/modal/alert-modal";
import { Icons } from "@/components/icons";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Textarea } from "@/components/ui/textarea";
import {
  createQuotationAttachmentMutation,
  createQuotationCustomerMutation,
  createQuotationFollowupMutation,
  createQuotationItemMutation,
  createQuotationRevisionMutation,
  createQuotationTopicMutation,
  deleteQuotationAttachmentMutation,
  deleteQuotationCustomerMutation,
  deleteQuotationFollowupMutation,
  deleteQuotationItemMutation,
  deleteQuotationTopicMutation,
  updateQuotationAttachmentMutation,
  updateQuotationCustomerMutation,
  updateQuotationFollowupMutation,
  updateQuotationItemMutation,
  updateQuotationTopicMutation,
} from "../api/mutations";
import {
  quotationAttachmentsOptions,
  quotationByIdOptions,
  quotationCustomersOptions,
  quotationFollowupsOptions,
  quotationItemsOptions,
  quotationKeys,
  quotationRevisionsOptions,
  quotationTopicsOptions,
} from "../api/queries";
import type {
  QuotationAttachmentMutationPayload,
  QuotationAttachmentRecord,
  QuotationCustomerListItem,
  QuotationCustomerMutationPayload,
  QuotationFollowupMutationPayload,
  QuotationFollowupRecord,
  QuotationItemMutationPayload,
  QuotationItemRecord,
  QuotationReferenceData,
  QuotationTopicMutationPayload,
  QuotationTopicRecord,
} from "../api/types";
import { submitQuotationApprovalMutation } from "@/features/foundation/approval/mutations";
import { quotationDocumentKeys } from "@/features/crm/quotations/document/queries";
import { QuotationDocumentPreview } from "./quotation-document-preview";
import { QuotationFormSheet } from "./quotation-form-sheet";
import { QuotationApprovalTab } from "./quotation-approval-tab";
import { QuotationStatusBadge } from "./quotation-status-badge";
import { getQueryClient } from "@/lib/query-client";

function FieldItem({
  label,
  value,
}: {
  label: string;
  value: string | null | undefined;
}) {
  return (
    <div className="space-y-1">
      <div className="text-muted-foreground text-xs">{label}</div>
      <div className="text-sm">{value ?? "-"}</div>
    </div>
  );
}

function EmptyState({ message }: { message: string }) {
  return (
    <div className="text-muted-foreground rounded-lg border border-dashed p-8 text-center text-sm">
      {message}
    </div>
  );
}

function ItemDialog({
  open,
  onOpenChange,
  onSubmit,
  pending,
  referenceData,
  item,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (values: QuotationItemMutationPayload) => Promise<void>;
  pending: boolean;
  referenceData: QuotationReferenceData;
  item?: QuotationItemRecord;
}) {
  const [values, setValues] = useState({
    productType: item?.productType ?? referenceData.productTypes[0]?.id ?? "",
    description: item?.description ?? "",
    quantity: String(item?.quantity ?? 1),
    unit: item?.unit ?? "",
    unitPrice: String(item?.unitPrice ?? 0),
    discount: String(item?.discount ?? 0),
    discountType: item?.discountType ?? "",
    taxRate: String(item?.taxRate ?? 0),
    notes: item?.notes ?? "",
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{item ? "Edit Item" : "Add Item"}</DialogTitle>
          <DialogDescription>
            Line items drive quotation totals from the server.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4">
          <Select
            value={values.productType}
            onValueChange={(value) =>
              setValues((s) => ({ ...s, productType: value }))
            }
          >
            <SelectTrigger>
              <SelectValue placeholder="Product type" />
            </SelectTrigger>
            <SelectContent>
              {referenceData.productTypes.map((option) => (
                <SelectItem key={option.id} value={option.id}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Input
            value={values.description}
            onChange={(e) =>
              setValues((s) => ({ ...s, description: e.target.value }))
            }
            placeholder="Description"
          />
          <div className="grid gap-4 md:grid-cols-2">
            <Input
              value={values.quantity}
              onChange={(e) =>
                setValues((s) => ({ ...s, quantity: e.target.value }))
              }
              type="number"
              placeholder="Quantity"
            />
            <Select
              value={values.unit || "__none__"}
              onValueChange={(value) =>
                setValues((s) => ({
                  ...s,
                  unit: value === "__none__" ? "" : value,
                }))
              }
            >
              <SelectTrigger>
                <SelectValue placeholder="Unit" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="__none__">No unit</SelectItem>
                {referenceData.units.map((option) => (
                  <SelectItem key={option.id} value={option.id}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="grid gap-4 md:grid-cols-2">
            <Input
              value={values.unitPrice}
              onChange={(e) =>
                setValues((s) => ({ ...s, unitPrice: e.target.value }))
              }
              type="number"
              placeholder="Unit price"
            />
            <Input
              value={values.discount}
              onChange={(e) =>
                setValues((s) => ({ ...s, discount: e.target.value }))
              }
              type="number"
              placeholder="Discount"
            />
          </div>
          <div className="grid gap-4 md:grid-cols-2">
            <Select
              value={values.discountType || "__none__"}
              onValueChange={(value) =>
                setValues((s) => ({
                  ...s,
                  discountType: value === "__none__" ? "" : value,
                }))
              }
            >
              <SelectTrigger>
                <SelectValue placeholder="Discount type" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="__none__">No discount type</SelectItem>
                {referenceData.discountTypes.map((option) => (
                  <SelectItem key={option.id} value={option.id}>
                    {option.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Input
              value={values.taxRate}
              onChange={(e) =>
                setValues((s) => ({ ...s, taxRate: e.target.value }))
              }
              type="number"
              placeholder="Tax rate %"
            />
          </div>
          <Textarea
            value={values.notes}
            onChange={(e) =>
              setValues((s) => ({ ...s, notes: e.target.value }))
            }
            placeholder="Notes"
          />
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            isLoading={pending}
            onClick={async () => {
              await onSubmit({
                productType: values.productType,
                description: values.description,
                quantity: Number(values.quantity),
                unit: values.unit,
                unitPrice: Number(values.unitPrice),
                discount: Number(values.discount),
                discountType: values.discountType || null,
                taxRate: Number(values.taxRate),
                notes: values.notes,
              });
              onOpenChange(false);
            }}
          >
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function CustomerDialog({
  open,
  onOpenChange,
  onSubmit,
  pending,
  referenceData,
  relation,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (values: QuotationCustomerMutationPayload) => Promise<void>;
  pending: boolean;
  referenceData: QuotationReferenceData;
  relation?: QuotationCustomerListItem;
}) {
  const [customerId, setCustomerId] = useState(
    relation?.customerId ?? referenceData.customers[0]?.id ?? "",
  );
  const [role, setRole] = useState(
    relation?.role ?? referenceData.projectPartyRoles[0]?.id ?? "",
  );
  const [remark, setRemark] = useState(relation?.remark ?? "");

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>
            {relation ? "Edit Project Party" : "Add Project Party"}
          </DialogTitle>
          <DialogDescription>
            Keep related companies visible with their role in this quotation.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4">
          <Select value={customerId} onValueChange={setCustomerId}>
            <SelectTrigger>
              <SelectValue placeholder="Customer" />
            </SelectTrigger>
            <SelectContent>
              {referenceData.customers.map((item) => (
                <SelectItem key={item.id} value={item.id}>
                  {item.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Select value={role} onValueChange={setRole}>
            <SelectTrigger>
              <SelectValue placeholder="Role" />
            </SelectTrigger>
            <SelectContent>
              {referenceData.projectPartyRoles.map((item) => (
                <SelectItem key={item.id} value={item.id}>
                  {item.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Input
            value={remark}
            onChange={(event) => setRemark(event.target.value)}
            placeholder="Remark"
          />
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            isLoading={pending}
            onClick={async () => {
              await onSubmit({ customerId, role, remark: remark || null });
              onOpenChange(false);
            }}
          >
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function TopicDialog({
  open,
  onOpenChange,
  onSubmit,
  pending,
  referenceData,
  topic,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (values: QuotationTopicMutationPayload) => Promise<void>;
  pending: boolean;
  referenceData: QuotationReferenceData;
  topic?: QuotationTopicRecord;
}) {
  const [topicType, setTopicType] = useState(
    topic?.topicType ?? referenceData.topicTypes[0]?.id ?? "",
  );
  const [title, setTitle] = useState(topic?.title ?? "");
  const [itemsText, setItemsText] = useState(
    topic?.items.map((item) => item.content).join("\n") ?? "",
  );

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{topic ? "Edit Topic" : "Add Topic"}</DialogTitle>
          <DialogDescription>
            Each line becomes a topic item in the generated quotation document.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4">
          <Select value={topicType} onValueChange={setTopicType}>
            <SelectTrigger>
              <SelectValue placeholder="Topic type" />
            </SelectTrigger>
            <SelectContent>
              {referenceData.topicTypes.map((item) => (
                <SelectItem key={item.id} value={item.id}>
                  {item.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Input
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            placeholder="Topic title"
          />
          <Textarea
            value={itemsText}
            onChange={(e) => setItemsText(e.target.value)}
            placeholder="One line per topic item"
            rows={6}
          />
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            isLoading={pending}
            onClick={async () => {
              await onSubmit({
                id: topic?.id,
                topicType,
                title,
                items: itemsText
                  .split("\n")
                  .map((item, index) => ({
                    content: item.trim(),
                    sortOrder: index,
                  }))
                  .filter((item) => item.content.length > 0),
              });
              onOpenChange(false);
            }}
          >
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function FollowupDialog({
  open,
  onOpenChange,
  onSubmit,
  pending,
  referenceData,
  customerId,
  followup,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (values: QuotationFollowupMutationPayload) => Promise<void>;
  pending: boolean;
  referenceData: QuotationReferenceData;
  customerId: string;
  followup?: QuotationFollowupRecord;
}) {
  const contacts = referenceData.contacts.filter(
    (item) => item.customerId === customerId,
  );
  const [values, setValues] = useState({
    followupDate:
      followup?.followupDate.slice(0, 10) ??
      new Date().toISOString().slice(0, 10),
    followupType:
      followup?.followupType ?? referenceData.followupTypes[0]?.id ?? "",
    contactId: followup?.contactId ?? "",
    outcome: followup?.outcome ?? "",
    notes: followup?.notes ?? "",
    nextFollowupDate: followup?.nextFollowupDate?.slice(0, 10) ?? "",
    nextAction: followup?.nextAction ?? "",
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>
            {followup ? "Edit Follow-up" : "Add Follow-up"}
          </DialogTitle>
          <DialogDescription>
            Keep quotation chasing and commercial communication visible.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4">
          <Input
            type="date"
            value={values.followupDate}
            onChange={(e) =>
              setValues((s) => ({ ...s, followupDate: e.target.value }))
            }
          />
          <Select
            value={values.followupType}
            onValueChange={(value) =>
              setValues((s) => ({ ...s, followupType: value }))
            }
          >
            <SelectTrigger>
              <SelectValue placeholder="Follow-up type" />
            </SelectTrigger>
            <SelectContent>
              {referenceData.followupTypes.map((item) => (
                <SelectItem key={item.id} value={item.id}>
                  {item.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Select
            value={values.contactId || "__none__"}
            onValueChange={(value) =>
              setValues((s) => ({
                ...s,
                contactId: value === "__none__" ? "" : value,
              }))
            }
          >
            <SelectTrigger>
              <SelectValue placeholder="Contact" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="__none__">No contact</SelectItem>
              {contacts.map((item) => (
                <SelectItem key={item.id} value={item.id}>
                  {item.name}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
          <Input
            value={values.outcome}
            onChange={(e) =>
              setValues((s) => ({ ...s, outcome: e.target.value }))
            }
            placeholder="Outcome"
          />
          <Input
            type="date"
            value={values.nextFollowupDate}
            onChange={(e) =>
              setValues((s) => ({ ...s, nextFollowupDate: e.target.value }))
            }
          />
          <Input
            value={values.nextAction}
            onChange={(e) =>
              setValues((s) => ({ ...s, nextAction: e.target.value }))
            }
            placeholder="Next action"
          />
          <Textarea
            value={values.notes}
            onChange={(e) =>
              setValues((s) => ({ ...s, notes: e.target.value }))
            }
            placeholder="Notes"
          />
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            isLoading={pending}
            onClick={async () => {
              await onSubmit({
                id: followup?.id,
                followupDate: values.followupDate,
                followupType: values.followupType,
                contactId: values.contactId || null,
                outcome: values.outcome,
                notes: values.notes,
                nextFollowupDate: values.nextFollowupDate || null,
                nextAction: values.nextAction,
              });
              onOpenChange(false);
            }}
          >
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function AttachmentDialog({
  open,
  onOpenChange,
  onSubmit,
  pending,
  attachment,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSubmit: (values: QuotationAttachmentMutationPayload) => Promise<void>;
  pending: boolean;
  attachment?: QuotationAttachmentRecord;
}) {
  const [values, setValues] = useState({
    fileName: attachment?.fileName ?? "",
    originalFileName: attachment?.originalFileName ?? "",
    filePath: attachment?.filePath ?? "",
    fileSize: String(attachment?.fileSize ?? 0),
    fileType: attachment?.fileType ?? "",
    description: attachment?.description ?? "",
  });

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>
            {attachment
              ? "Edit Attachment Metadata"
              : "Add Attachment Metadata"}
          </DialogTitle>
          <DialogDescription>
            Task E stores attachment metadata only, without file upload
            plumbing.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4">
          <Input
            value={values.fileName}
            onChange={(e) =>
              setValues((s) => ({ ...s, fileName: e.target.value }))
            }
            placeholder="Stored file name"
          />
          <Input
            value={values.originalFileName}
            onChange={(e) =>
              setValues((s) => ({ ...s, originalFileName: e.target.value }))
            }
            placeholder="Original file name"
          />
          <Input
            value={values.filePath}
            onChange={(e) =>
              setValues((s) => ({ ...s, filePath: e.target.value }))
            }
            placeholder="/crm/quotations/..."
          />
          <div className="grid gap-4 md:grid-cols-2">
            <Input
              value={values.fileType}
              onChange={(e) =>
                setValues((s) => ({ ...s, fileType: e.target.value }))
              }
              placeholder="application/pdf"
            />
            <Input
              value={values.fileSize}
              onChange={(e) =>
                setValues((s) => ({ ...s, fileSize: e.target.value }))
              }
              type="number"
              placeholder="File size bytes"
            />
          </div>
          <Textarea
            value={values.description}
            onChange={(e) =>
              setValues((s) => ({ ...s, description: e.target.value }))
            }
            placeholder="Description"
          />
        </div>
        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            isLoading={pending}
            onClick={async () => {
              await onSubmit({
                id: attachment?.id,
                fileName: values.fileName,
                originalFileName: values.originalFileName,
                filePath: values.filePath,
                fileSize: Number(values.fileSize),
                fileType: values.fileType || null,
                description: values.description,
              });
              onOpenChange(false);
            }}
          >
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

export function QuotationDetail({
  quotationId,
  referenceData,
  canUpdate,
  canManageItems,
  canManageCustomers,
  canManageTopics,
  canManageFollowups,
  canManageAttachments,
  canCreateRevision,
  canSubmitApproval,
  canApproveApproval,
  canRejectApproval,
  canReturnApproval,
  activeBusinessRole,
  isOrgAdmin,
  currentUserId,
  canPreviewDocument,
  canPreviewPdf,
  canDownloadPdf,
  canGenerateApprovedPdf,
}: {
  quotationId: string;
  referenceData: QuotationReferenceData;
  canUpdate: boolean;
  canManageItems: boolean;
  canManageCustomers: boolean;
  canManageTopics: boolean;
  canManageFollowups: boolean;
  canManageAttachments: boolean;
  canCreateRevision: boolean;
  canSubmitApproval: boolean;
  canApproveApproval: boolean;
  canRejectApproval: boolean;
  canReturnApproval: boolean;
  activeBusinessRole: string | null;
  isOrgAdmin: boolean;
  currentUserId: string;
  canPreviewDocument: boolean;
  canPreviewPdf: boolean;
  canDownloadPdf: boolean;
  canGenerateApprovedPdf: boolean;
}) {
  const { data } = useSuspenseQuery(quotationByIdOptions(quotationId));
  const { data: itemsData } = useSuspenseQuery(
    quotationItemsOptions(quotationId),
  );
  const { data: customersData } = useSuspenseQuery(
    quotationCustomersOptions(quotationId),
  );
  const { data: topicsData } = useSuspenseQuery(
    quotationTopicsOptions(quotationId),
  );
  const { data: followupsData } = useSuspenseQuery(
    quotationFollowupsOptions(quotationId),
  );
  const { data: attachmentsData } = useSuspenseQuery(
    quotationAttachmentsOptions(quotationId),
  );
  const { data: revisionsData } = useSuspenseQuery(
    quotationRevisionsOptions(quotationId),
  );
  const quotation = data.quotation;
  const [editOpen, setEditOpen] = useState(false);

  const [itemOpen, setItemOpen] = useState(false);
  const [editingItem, setEditingItem] = useState<
    QuotationItemRecord | undefined
  >();
  const [deleteItemId, setDeleteItemId] = useState<string | null>(null);
  const createItem = useMutation({
    ...createQuotationItemMutation,
    onSuccess: () => toast.success("Quotation item saved"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to save item",
      ),
  });
  const updateItem = useMutation({
    ...updateQuotationItemMutation,
    onSuccess: () => toast.success("Quotation item updated"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to update item",
      ),
  });
  const deleteItem = useMutation({
    ...deleteQuotationItemMutation,
    onSuccess: () => {
      toast.success("Quotation item deleted");
      setDeleteItemId(null);
    },
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to delete item",
      ),
  });

  const [customerOpen, setCustomerOpen] = useState(false);
  const [editingCustomer, setEditingCustomer] = useState<
    QuotationCustomerListItem | undefined
  >();
  const [deleteCustomerId, setDeleteCustomerId] = useState<string | null>(null);
  const createCustomer = useMutation({
    ...createQuotationCustomerMutation,
    onSuccess: () => toast.success("Project party saved"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to save project party",
      ),
  });
  const updateCustomer = useMutation({
    ...updateQuotationCustomerMutation,
    onSuccess: () => toast.success("Project party updated"),
    onError: (error) =>
      toast.error(
        error instanceof Error
          ? error.message
          : "Failed to update project party",
      ),
  });
  const deleteCustomer = useMutation({
    ...deleteQuotationCustomerMutation,
    onSuccess: () => {
      toast.success("Project party deleted");
      setDeleteCustomerId(null);
    },
    onError: (error) =>
      toast.error(
        error instanceof Error
          ? error.message
          : "Failed to delete project party",
      ),
  });

  const [topicOpen, setTopicOpen] = useState(false);
  const [editingTopic, setEditingTopic] = useState<
    QuotationTopicRecord | undefined
  >();
  const [deleteTopicId, setDeleteTopicId] = useState<string | null>(null);
  const createTopic = useMutation({
    ...createQuotationTopicMutation,
    onSuccess: () => toast.success("Topic saved"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to save topic",
      ),
  });
  const updateTopic = useMutation({
    ...updateQuotationTopicMutation,
    onSuccess: () => toast.success("Topic updated"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to update topic",
      ),
  });
  const deleteTopic = useMutation({
    ...deleteQuotationTopicMutation,
    onSuccess: () => {
      toast.success("Topic deleted");
      setDeleteTopicId(null);
    },
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to delete topic",
      ),
  });

  const [followupOpen, setFollowupOpen] = useState(false);
  const [editingFollowup, setEditingFollowup] = useState<
    QuotationFollowupRecord | undefined
  >();
  const [deleteFollowupId, setDeleteFollowupId] = useState<string | null>(null);
  const createFollowup = useMutation({
    ...createQuotationFollowupMutation,
    onSuccess: () => toast.success("Follow-up saved"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to save follow-up",
      ),
  });
  const updateFollowup = useMutation({
    ...updateQuotationFollowupMutation,
    onSuccess: () => toast.success("Follow-up updated"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to update follow-up",
      ),
  });
  const deleteFollowup = useMutation({
    ...deleteQuotationFollowupMutation,
    onSuccess: () => {
      toast.success("Follow-up deleted");
      setDeleteFollowupId(null);
    },
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to delete follow-up",
      ),
  });

  const [attachmentOpen, setAttachmentOpen] = useState(false);
  const [editingAttachment, setEditingAttachment] = useState<
    QuotationAttachmentRecord | undefined
  >();
  const [deleteAttachmentId, setDeleteAttachmentId] = useState<string | null>(
    null,
  );
  const createAttachment = useMutation({
    ...createQuotationAttachmentMutation,
    onSuccess: () => toast.success("Attachment metadata saved"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to save attachment",
      ),
  });
  const updateAttachment = useMutation({
    ...updateQuotationAttachmentMutation,
    onSuccess: () => toast.success("Attachment metadata updated"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to update attachment",
      ),
  });
  const deleteAttachment = useMutation({
    ...deleteQuotationAttachmentMutation,
    onSuccess: () => {
      toast.success("Attachment metadata deleted");
      setDeleteAttachmentId(null);
    },
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to delete attachment",
      ),
  });

  const createRevision = useMutation({
    ...createQuotationRevisionMutation,
    onSuccess: () => toast.success("Revision created successfully"),
    onError: (error) =>
      toast.error(
        error instanceof Error ? error.message : "Failed to create revision",
      ),
  });
  const submitForApproval = useMutation({
    ...submitQuotationApprovalMutation,
    onSuccess: () => toast.success("Quotation moved to pending approval"),
    onError: (error) =>
      toast.error(
        error instanceof Error
          ? error.message
          : "Failed to submit for approval",
      ),
  });
  const generateApprovedPdf = useMutation({
    mutationFn: async () => {
      const response = await fetch(
        `/api/crm/quotations/${quotationId}/approved-pdf`,
        {
          method: "POST",
        },
      );

      if (!response.ok) {
        const payload = (await response.json().catch(() => null)) as {
          message?: string;
        } | null;
        throw new Error(payload?.message ?? "Failed to generate approved PDF");
      }

      return response.blob();
    },
    onSuccess: async (blob) => {
      const url = URL.createObjectURL(blob);
      const anchor = document.createElement("a");
      anchor.href = url;
      anchor.download = `${quotation.code}-approved.pdf`;
      document.body.append(anchor);
      anchor.click();
      anchor.remove();
      URL.revokeObjectURL(url);

      const queryClient = getQueryClient();
      await Promise.all([
        queryClient.invalidateQueries({
          queryKey: quotationKeys.detail(quotationId),
        }),
        queryClient.invalidateQueries({
          queryKey: quotationKeys.attachments(quotationId),
        }),
        queryClient.invalidateQueries({
          queryKey: quotationDocumentKeys.data(quotationId),
        }),
        queryClient.invalidateQueries({
          queryKey: quotationDocumentKeys.preview(quotationId),
        }),
      ]);
      toast.success("Approved PDF generated successfully");
    },
    onError: (error) =>
      toast.error(
        error instanceof Error
          ? error.message
          : "Failed to generate approved PDF",
      ),
  });

  const branchMap = useMemo(
    () => new Map(referenceData.branches.map((item) => [item.id, item.name])),
    [referenceData.branches],
  );
  const customerMap = useMemo(
    () => new Map(referenceData.customers.map((item) => [item.id, item])),
    [referenceData.customers],
  );
  const contactMap = useMemo(
    () => new Map(referenceData.contacts.map((item) => [item.id, item])),
    [referenceData.contacts],
  );
  const statusMap = useMemo(
    () => new Map(referenceData.statuses.map((item) => [item.id, item])),
    [referenceData.statuses],
  );
  const typeMap = useMemo(
    () => new Map(referenceData.quotationTypes.map((item) => [item.id, item])),
    [referenceData.quotationTypes],
  );
  const currencyMap = useMemo(
    () => new Map(referenceData.currencies.map((item) => [item.id, item])),
    [referenceData.currencies],
  );
  const topicTypeMap = useMemo(
    () => new Map(referenceData.topicTypes.map((item) => [item.id, item])),
    [referenceData.topicTypes],
  );
  const followupTypeMap = useMemo(
    () => new Map(referenceData.followupTypes.map((item) => [item.id, item])),
    [referenceData.followupTypes],
  );
  const customer = customerMap.get(quotation.customerId);
  const contact = quotation.contactId
    ? contactMap.get(quotation.contactId)
    : null;
  const status = statusMap.get(quotation.status);
  const canReviseByStatus = [
    "accepted",
    "rejected",
    "sent",
    "approved",
  ].includes(status?.code ?? "");
  const canSubmitCurrentQuotation =
    canSubmitApproval && ["draft", "revised"].includes(status?.code ?? "");
  const canGenerateApprovedNow =
    canGenerateApprovedPdf && (status?.code ?? "") === "approved";

  return (
    <div className="space-y-6">
      <AlertModal
        isOpen={!!deleteItemId}
        onClose={() => setDeleteItemId(null)}
        onConfirm={() =>
          deleteItemId &&
          deleteItem.mutate({ quotationId, itemId: deleteItemId })
        }
        loading={deleteItem.isPending}
      />
      <AlertModal
        isOpen={!!deleteCustomerId}
        onClose={() => setDeleteCustomerId(null)}
        onConfirm={() =>
          deleteCustomerId &&
          deleteCustomer.mutate({ quotationId, relationId: deleteCustomerId })
        }
        loading={deleteCustomer.isPending}
      />
      <AlertModal
        isOpen={!!deleteTopicId}
        onClose={() => setDeleteTopicId(null)}
        onConfirm={() =>
          deleteTopicId &&
          deleteTopic.mutate({ quotationId, topicId: deleteTopicId })
        }
        loading={deleteTopic.isPending}
      />
      <AlertModal
        isOpen={!!deleteFollowupId}
        onClose={() => setDeleteFollowupId(null)}
        onConfirm={() =>
          deleteFollowupId &&
          deleteFollowup.mutate({ quotationId, followupId: deleteFollowupId })
        }
        loading={deleteFollowup.isPending}
      />
      <AlertModal
        isOpen={!!deleteAttachmentId}
        onClose={() => setDeleteAttachmentId(null)}
        onConfirm={() =>
          deleteAttachmentId &&
          deleteAttachment.mutate({
            quotationId,
            attachmentId: deleteAttachmentId,
          })
        }
        loading={deleteAttachment.isPending}
      />

      <ItemDialog
        open={itemOpen}
        onOpenChange={setItemOpen}
        item={editingItem}
        referenceData={referenceData}
        pending={createItem.isPending || updateItem.isPending}
        onSubmit={async (values) => {
          if (editingItem) {
            await updateItem.mutateAsync({
              quotationId,
              itemId: editingItem.id,
              values,
            });
            return;
          }

          await createItem.mutateAsync({ quotationId, values });
        }}
      />
      <CustomerDialog
        open={customerOpen}
        onOpenChange={setCustomerOpen}
        relation={editingCustomer}
        referenceData={referenceData}
        pending={createCustomer.isPending || updateCustomer.isPending}
        onSubmit={async (values) => {
          if (editingCustomer) {
            await updateCustomer.mutateAsync({
              quotationId,
              relationId: editingCustomer.id,
              values,
            });
            return;
          }

          await createCustomer.mutateAsync({ quotationId, values });
        }}
      />
      <TopicDialog
        open={topicOpen}
        onOpenChange={setTopicOpen}
        topic={editingTopic}
        referenceData={referenceData}
        pending={createTopic.isPending || updateTopic.isPending}
        onSubmit={async (values) => {
          if (editingTopic) {
            await updateTopic.mutateAsync({
              quotationId,
              values: { ...values, id: editingTopic.id },
            });
            return;
          }

          await createTopic.mutateAsync({ quotationId, values });
        }}
      />
      <FollowupDialog
        open={followupOpen}
        onOpenChange={setFollowupOpen}
        followup={editingFollowup}
        customerId={quotation.customerId}
        referenceData={referenceData}
        pending={createFollowup.isPending || updateFollowup.isPending}
        onSubmit={async (values) => {
          if (editingFollowup) {
            await updateFollowup.mutateAsync({
              quotationId,
              values: { ...values, id: editingFollowup.id },
            });
            return;
          }

          await createFollowup.mutateAsync({ quotationId, values });
        }}
      />
      <AttachmentDialog
        open={attachmentOpen}
        onOpenChange={setAttachmentOpen}
        attachment={editingAttachment}
        pending={createAttachment.isPending || updateAttachment.isPending}
        onSubmit={async (values) => {
          if (editingAttachment) {
            await updateAttachment.mutateAsync({
              quotationId,
              values: { ...values, id: editingAttachment.id },
            });
            return;
          }

          await createAttachment.mutateAsync({ quotationId, values });
        }}
      />
      <QuotationFormSheet
        quotation={quotation}
        open={editOpen}
        onOpenChange={setEditOpen}
        referenceData={referenceData}
      />

      <div className="flex flex-col gap-4 rounded-xl border p-5 lg:flex-row lg:items-start lg:justify-between">
        <div className="space-y-3">
          <div className="flex items-center gap-2">
            <Button asChild variant="ghost" size="icon">
              <Link href="/dashboard/crm/quotations">
                <Icons.chevronLeft className="h-4 w-4" />
              </Link>
            </Button>
            <span className="text-muted-foreground font-mono text-sm">
              {quotation.code}
            </span>
            <QuotationStatusBadge
              code={status?.code}
              label={status?.label ?? "Unknown"}
            />
            {quotation.isHotProject ? <Badge>Hot</Badge> : null}
          </div>
          <div>
            <h2 className="text-2xl font-semibold">
              {quotation.projectName || "Untitled quotation"}
            </h2>
            <p className="text-muted-foreground text-sm">
              {customer?.name ?? "Unknown customer"}
              {contact ? ` - ${contact.name}` : ""}
            </p>
          </div>
        </div>
        <div className="flex flex-wrap gap-2">
          {canSubmitCurrentQuotation ? (
            <Button
              variant="outline"
              isLoading={submitForApproval.isPending}
              onClick={() => submitForApproval.mutate({ id: quotationId })}
            >
              <Icons.send className="mr-2 h-4 w-4" /> Submit for approval
            </Button>
          ) : null}
          {canCreateRevision && canReviseByStatus ? (
            <Button
              variant="outline"
              isLoading={createRevision.isPending}
              onClick={() => createRevision.mutate({ quotationId })}
            >
              <Icons.add className="mr-2 h-4 w-4" /> Create Revision
            </Button>
          ) : null}
          {canUpdate ? (
            <Button variant="outline" onClick={() => setEditOpen(true)}>
              <Icons.edit className="mr-2 h-4 w-4" /> Edit Quotation
            </Button>
          ) : null}
          {canPreviewPdf ? (
            <Button asChild variant="outline">
              <Link
                href={`/api/crm/quotations/${quotationId}/pdf-preview`}
                target="_blank"
              >
                <Icons.eyeOff className="mr-2 h-4 w-4" /> Preview PDF
              </Link>
            </Button>
          ) : null}
          {canDownloadPdf ? (
            <Button asChild variant="outline">
              <Link
                href={`/api/crm/quotations/${quotationId}/pdf-download`}
                target="_blank"
              >
                <Icons.download className="mr-2 h-4 w-4" /> Download PDF
              </Link>
            </Button>
          ) : null}
          {canGenerateApprovedNow ? (
            <Button
              variant="outline"
              isLoading={generateApprovedPdf.isPending}
              onClick={() => generateApprovedPdf.mutate()}
            >
              <Icons.badgeCheck className="mr-2 h-4 w-4" /> Generate Approved
              PDF
            </Button>
          ) : null}
          {quotation.approvedPdfUrl ? (
            <Button asChild variant="outline">
              <Link
                href={
                  quotation.approvedArtifact?.id
                    ? `/api/crm/document-artifacts/${quotation.approvedArtifact.id}/download`
                    : `/api/crm/quotations/${quotationId}/approved-pdf`
                }
                target="_blank"
              >
                <Icons.externalLink className="mr-2 h-4 w-4" /> View Approved
                PDF
              </Link>
            </Button>
          ) : null}
        </div>
      </div>

      <div className="grid gap-6 lg:grid-cols-3">
        <div className="space-y-6 lg:col-span-2">
          <Card>
            <CardContent className="pt-6">
              <Tabs defaultValue="overview" className="gap-4">
                <TabsList className="flex flex-wrap">
                  <TabsTrigger value="overview">Overview</TabsTrigger>
                  <TabsTrigger value="items">Items</TabsTrigger>
                  <TabsTrigger value="customers">ผู้เกี่ยวข้องในโครงการ</TabsTrigger>
                  <TabsTrigger value="topics">Topics</TabsTrigger>
                  <TabsTrigger value="followups">Follow-ups</TabsTrigger>
                  <TabsTrigger value="attachments">Attachments</TabsTrigger>
                  <TabsTrigger value="activity">Activity</TabsTrigger>
                  <TabsTrigger value="approval">Approval</TabsTrigger>
                  <TabsTrigger value="preview">Document Preview</TabsTrigger>
                </TabsList>

                <TabsContent value="overview">
                  <Card>
                    <CardHeader>
                      <CardTitle>Overview</CardTitle>
                      <CardDescription>
                        Commercial header data and quotation summary.
                      </CardDescription>
                    </CardHeader>
                    <CardContent className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
                      <FieldItem
                        label="ลูกค้าผู้รับใบเสนอราคา"
                        value={customer?.name}
                      />
                      <FieldItem label="Contact" value={contact?.name} />
                      <FieldItem
                        label="Branch"
                        value={
                          quotation.branchId
                            ? branchMap.get(quotation.branchId)
                            : null
                        }
                      />
                      <FieldItem
                        label="Type"
                        value={typeMap.get(quotation.quotationType)?.label}
                      />
                      <FieldItem
                        label="Currency"
                        value={currencyMap.get(quotation.currency)?.label}
                      />
                      <FieldItem
                        label="Exchange Rate"
                        value={quotation.exchangeRate.toString()}
                      />
                      <FieldItem
                        label="Quotation Date"
                        value={new Date(
                          quotation.quotationDate,
                        ).toLocaleDateString()}
                      />
                      <FieldItem
                        label="Valid Until"
                        value={
                          quotation.validUntil
                            ? new Date(
                                quotation.validUntil,
                              ).toLocaleDateString()
                            : null
                        }
                      />
                      <FieldItem
                        label="Subtotal"
                        value={quotation.subtotal.toLocaleString()}
                      />
                      <FieldItem
                        label="Tax"
                        value={quotation.taxAmount.toLocaleString()}
                      />
                      <FieldItem
                        label="Total"
                        value={quotation.totalAmount.toLocaleString()}
                      />
                      <FieldItem
                        label="Chance %"
                        value={
                          quotation.chancePercent !== null
                            ? `${quotation.chancePercent}%`
                            : null
                        }
                      />
                      <div className="md:col-span-2 xl:col-span-4">
                        <div className="space-y-3">
                          <div className="text-muted-foreground text-xs">
                            ผู้เกี่ยวข้องในโครงการ
                          </div>
                          {!customersData.items.length ? (
                            <div className="text-muted-foreground rounded-lg border border-dashed p-4 text-sm">
                              No project parties have been added yet.
                            </div>
                          ) : (
                            <div className="space-y-3">
                              {customersData.items.map((item) => (
                                <div
                                  key={item.id}
                                  className="rounded-lg border p-4 text-sm"
                                >
                                  <div className="font-medium">
                                    {item.customerName}
                                  </div>
                                  <div className="text-muted-foreground">
                                    Role: {item.roleLabel ?? item.roleCode}
                                  </div>
                                  {item.remark ? (
                                    <div className="mt-1">{item.remark}</div>
                                  ) : null}
                                </div>
                              ))}
                            </div>
                          )}
                        </div>
                      </div>
                      <div className="md:col-span-2 xl:col-span-4">
                        <FieldItem
                          label="Project"
                          value={
                            [quotation.projectName, quotation.projectLocation]
                              .filter(Boolean)
                              .join(" - ") || null
                          }
                        />
                      </div>
                      <div className="md:col-span-2 xl:col-span-4">
                        <FieldItem
                          label="Attention / Reference"
                          value={
                            [quotation.attention, quotation.reference]
                              .filter(Boolean)
                              .join(" - ") || null
                          }
                        />
                      </div>
                      <div className="md:col-span-2 xl:col-span-4">
                        <FieldItem label="Notes" value={quotation.notes} />
                      </div>
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="items">
                  <Card>
                    <CardHeader className="flex flex-row items-center justify-between">
                      <div>
                        <CardTitle>Items</CardTitle>
                        <CardDescription>
                          Server-calculated line items and pricing inputs.
                        </CardDescription>
                      </div>
                      {canManageItems ? (
                        <Button
                          onClick={() => {
                            setEditingItem(undefined);
                            setItemOpen(true);
                          }}
                        >
                          <Icons.add className="mr-2 h-4 w-4" /> Add Item
                        </Button>
                      ) : null}
                    </CardHeader>
                    <CardContent className="space-y-3">
                      {!itemsData.items.length ? (
                        <EmptyState message="No quotation items yet." />
                      ) : (
                        itemsData.items.map((item) => (
                          <div key={item.id} className="rounded-lg border p-4">
                            <div className="flex items-start justify-between gap-4">
                              <div className="space-y-1">
                                <div className="font-medium">
                                  {item.description}
                                </div>
                                <div className="text-muted-foreground text-sm">
                                  Qty {item.quantity} {item.unit || ""} x{" "}
                                  {item.unitPrice.toLocaleString()}
                                </div>
                                <div className="text-muted-foreground text-xs">
                                  Total {item.totalPrice.toLocaleString()}
                                </div>
                              </div>
                              {canManageItems ? (
                                <div className="flex gap-2">
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => {
                                      setEditingItem(item);
                                      setItemOpen(true);
                                    }}
                                  >
                                    <Icons.edit className="mr-2 h-4 w-4" /> Edit
                                  </Button>
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => setDeleteItemId(item.id)}
                                  >
                                    <Icons.trash className="mr-2 h-4 w-4" />{" "}
                                    Delete
                                  </Button>
                                </div>
                              ) : null}
                            </div>
                          </div>
                        ))
                      )}
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="customers">
                  <Card>
                    <CardHeader className="flex flex-row items-center justify-between">
                      <div>
                        <CardTitle>ผู้เกี่ยวข้องในโครงการ</CardTitle>
                        <CardDescription>
                          Related companies for this quotation, each with a
                          visible role.
                        </CardDescription>
                      </div>
                      {canManageCustomers ? (
                        <Button
                          onClick={() => {
                            setEditingCustomer(undefined);
                            setCustomerOpen(true);
                          }}
                        >
                          <Icons.add className="mr-2 h-4 w-4" /> Add Party
                        </Button>
                      ) : null}
                    </CardHeader>
                    <CardContent className="space-y-3">
                      {!customersData.items.length ? (
                        <EmptyState message="No project parties have been added yet." />
                      ) : (
                        customersData.items.map((item) => (
                          <div
                            key={item.id}
                            className="flex items-center justify-between rounded-lg border p-4"
                          >
                            <div>
                              <div className="font-medium">
                                {item.customerName}
                              </div>
                              <div className="text-muted-foreground text-sm">
                                Role: {item.roleLabel ?? item.roleCode}
                              </div>
                              {item.remark ? (
                                <div className="text-muted-foreground mt-1 text-sm">
                                  {item.remark}
                                </div>
                              ) : null}
                            </div>
                            {canManageCustomers ? (
                              <div className="flex gap-2">
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => {
                                    setEditingCustomer(item);
                                    setCustomerOpen(true);
                                  }}
                                >
                                  <Icons.edit className="mr-2 h-4 w-4" /> Edit
                                </Button>
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => setDeleteCustomerId(item.id)}
                                >
                                  <Icons.trash className="mr-2 h-4 w-4" />{" "}
                                  Delete
                                </Button>
                              </div>
                            ) : null}
                          </div>
                        ))
                      )}
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="topics">
                  <Card>
                    <CardHeader className="flex flex-row items-center justify-between">
                      <div>
                        <CardTitle>Topics</CardTitle>
                        <CardDescription>
                          Scope, exclusions, payment terms, and other document
                          sections.
                        </CardDescription>
                      </div>
                      {canManageTopics ? (
                        <Button
                          onClick={() => {
                            setEditingTopic(undefined);
                            setTopicOpen(true);
                          }}
                        >
                          <Icons.add className="mr-2 h-4 w-4" /> Add Topic
                        </Button>
                      ) : null}
                    </CardHeader>
                    <CardContent className="space-y-4">
                      {!topicsData.items.length ? (
                        <EmptyState message="No quotation topics yet." />
                      ) : (
                        topicsData.items.map((topic) => (
                          <div key={topic.id} className="rounded-lg border p-4">
                            <div className="mb-3 flex items-center justify-between gap-4">
                              <div>
                                <div className="font-medium">{topic.title}</div>
                                <div className="text-muted-foreground text-sm">
                                  {topicTypeMap.get(topic.topicType)?.label ??
                                    topic.topicType}
                                </div>
                              </div>
                              {canManageTopics ? (
                                <div className="flex gap-2">
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => {
                                      setEditingTopic(topic);
                                      setTopicOpen(true);
                                    }}
                                  >
                                    <Icons.edit className="mr-2 h-4 w-4" /> Edit
                                  </Button>
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => setDeleteTopicId(topic.id)}
                                  >
                                    <Icons.trash className="mr-2 h-4 w-4" />{" "}
                                    Delete
                                  </Button>
                                </div>
                              ) : null}
                            </div>
                            <ul className="list-disc space-y-2 pl-5 text-sm">
                              {topic.items.map((item) => (
                                <li key={item.id}>{item.content}</li>
                              ))}
                            </ul>
                          </div>
                        ))
                      )}
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="followups">
                  <Card>
                    <CardHeader className="flex flex-row items-center justify-between">
                      <div>
                        <CardTitle>Follow-ups</CardTitle>
                        <CardDescription>
                          Commercial chasing and response history.
                        </CardDescription>
                      </div>
                      {canManageFollowups ? (
                        <Button
                          onClick={() => {
                            setEditingFollowup(undefined);
                            setFollowupOpen(true);
                          }}
                        >
                          <Icons.add className="mr-2 h-4 w-4" /> Add Follow-up
                        </Button>
                      ) : null}
                    </CardHeader>
                    <CardContent className="space-y-3">
                      {!followupsData.items.length ? (
                        <EmptyState message="No quotation follow-ups yet." />
                      ) : (
                        followupsData.items.map((item) => (
                          <div key={item.id} className="rounded-lg border p-4">
                            <div className="flex items-start justify-between gap-4">
                              <div className="space-y-1">
                                <div className="font-medium">
                                  {followupTypeMap.get(item.followupType)
                                    ?.label ?? item.followupType}
                                </div>
                                <div className="text-muted-foreground text-sm">
                                  {new Date(
                                    item.followupDate,
                                  ).toLocaleDateString()}
                                  {item.outcome ? ` - ${item.outcome}` : ""}
                                </div>
                                <div className="text-sm">
                                  {item.notes || "-"}
                                </div>
                              </div>
                              {canManageFollowups ? (
                                <div className="flex gap-2">
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => {
                                      setEditingFollowup(item);
                                      setFollowupOpen(true);
                                    }}
                                  >
                                    <Icons.edit className="mr-2 h-4 w-4" /> Edit
                                  </Button>
                                  <Button
                                    variant="outline"
                                    size="sm"
                                    onClick={() => setDeleteFollowupId(item.id)}
                                  >
                                    <Icons.trash className="mr-2 h-4 w-4" />{" "}
                                    Delete
                                  </Button>
                                </div>
                              ) : null}
                            </div>
                          </div>
                        ))
                      )}
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="attachments">
                  <Card>
                    <CardHeader className="flex flex-row items-center justify-between">
                      <div>
                        <CardTitle>Attachments</CardTitle>
                        <CardDescription>
                          Metadata only in Task E, ready for storage integration
                          later.
                        </CardDescription>
                      </div>
                      {canManageAttachments ? (
                        <Button
                          onClick={() => {
                            setEditingAttachment(undefined);
                            setAttachmentOpen(true);
                          }}
                        >
                          <Icons.add className="mr-2 h-4 w-4" /> Add Attachment
                        </Button>
                      ) : null}
                    </CardHeader>
                    <CardContent className="space-y-3">
                      {!attachmentsData.items.length ? (
                        <EmptyState message="No attachment metadata yet." />
                      ) : (
                        attachmentsData.items.map((item) => (
                          <div
                            key={item.id}
                            className="flex items-center justify-between rounded-lg border p-4"
                          >
                            <div>
                              <div className="font-medium">
                                {item.originalFileName}
                              </div>
                              <div className="text-muted-foreground text-sm">
                                {item.fileType || "Unknown type"}
                                {item.fileSize
                                  ? ` - ${item.fileSize.toLocaleString()} bytes`
                                  : ""}
                              </div>
                            </div>
                            {canManageAttachments ? (
                              <div className="flex gap-2">
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => {
                                    setEditingAttachment(item);
                                    setAttachmentOpen(true);
                                  }}
                                >
                                  <Icons.edit className="mr-2 h-4 w-4" /> Edit
                                </Button>
                                <Button
                                  variant="outline"
                                  size="sm"
                                  onClick={() => setDeleteAttachmentId(item.id)}
                                >
                                  <Icons.trash className="mr-2 h-4 w-4" />{" "}
                                  Delete
                                </Button>
                              </div>
                            ) : null}
                          </div>
                        ))
                      )}
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="activity">
                  <Card>
                    <CardHeader>
                      <CardTitle>Activity</CardTitle>
                      <CardDescription>
                        Audit events for quotation mutations and child records.
                      </CardDescription>
                    </CardHeader>
                    <CardContent className="space-y-4">
                      {!data.activity.length ? (
                        <EmptyState message="No activity recorded yet." />
                      ) : (
                        data.activity.map((item, index) => (
                          <div key={item.id} className="space-y-4">
                            <div className="flex items-start gap-3">
                              <div className="bg-primary mt-2 h-2 w-2 rounded-full" />
                              <div className="space-y-1">
                                <div className="flex items-center gap-2">
                                  <Badge
                                    variant="outline"
                                    className="capitalize"
                                  >
                                    {item.action}
                                  </Badge>
                                  <Badge variant="secondary">
                                    {item.entityType.replaceAll("_", " ")}
                                  </Badge>
                                  <span className="text-sm font-medium">
                                    {item.actorName ?? item.userId}
                                  </span>
                                </div>
                                <div className="text-muted-foreground text-xs">
                                  {new Date(item.createdAt).toLocaleString()}
                                </div>
                              </div>
                            </div>
                            {index < data.activity.length - 1 ? (
                              <Separator />
                            ) : null}
                          </div>
                        ))
                      )}
                    </CardContent>
                  </Card>
                </TabsContent>

                <TabsContent value="approval">
                  <QuotationApprovalTab
                    quotationId={quotationId}
                    quotationStatusCode={status?.code ?? null}
                    canSubmitApproval={canSubmitApproval}
                    canApproveApproval={canApproveApproval}
                    canRejectApproval={canRejectApproval}
                    canReturnApproval={canReturnApproval}
                    activeBusinessRole={activeBusinessRole}
                    isOrgAdmin={isOrgAdmin}
                    currentUserId={currentUserId}
                  />
                </TabsContent>

                <TabsContent value="preview">
                  {canPreviewDocument ? (
                    <QuotationDocumentPreview quotationId={quotationId} />
                  ) : (
                    <Card>
                      <CardHeader>
                        <CardTitle>Document Preview</CardTitle>
                        <CardDescription>
                          Preview permission is required to load document data.
                        </CardDescription>
                      </CardHeader>
                      <CardContent>
                        <EmptyState message="You do not have access to quotation document preview." />
                      </CardContent>
                    </Card>
                  )}
                </TabsContent>
              </Tabs>
            </CardContent>
          </Card>
        </div>

        <div className="space-y-6">
          <Card>
            <CardHeader>
              <CardTitle>Revision Chain</CardTitle>
              <CardDescription>
                Family of quotations copied from the same parent record.
              </CardDescription>
            </CardHeader>
            <CardContent className="space-y-3">
              {!revisionsData.items.length ? (
                <EmptyState message="No revisions yet." />
              ) : (
                revisionsData.items.map((item) => (
                  <Link
                    key={item.id}
                    href={`/dashboard/crm/quotations/${item.id}`}
                    className="block rounded-lg border p-3 transition-colors hover:bg-muted/40"
                  >
                    <div className="flex items-center justify-between gap-3">
                      <div>
                        <div className="font-medium">{item.code}</div>
                        <div className="text-muted-foreground text-xs">
                          {item.totalAmount.toLocaleString()}
                        </div>
                      </div>
                      <Icons.arrowRight className="text-muted-foreground h-4 w-4" />
                    </div>
                  </Link>
                ))
              )}
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle>Record Snapshot</CardTitle>
              <CardDescription>
                Operational metadata for this quotation row.
              </CardDescription>
            </CardHeader>
            <CardContent className="space-y-4">
              <FieldItem label="Created By" value={quotation.createdBy} />
              <FieldItem label="Updated By" value={quotation.updatedBy} />
              <FieldItem
                label="Created At"
                value={new Date(quotation.createdAt).toLocaleString()}
              />
              <FieldItem
                label="Updated At"
                value={new Date(quotation.updatedAt).toLocaleString()}
              />
              <FieldItem
                label="Revision"
                value={`R${String(quotation.revision).padStart(2, "0")}`}
              />
              <FieldItem
                label="Approved At"
                value={
                  quotation.approvedAt
                    ? new Date(quotation.approvedAt).toLocaleString()
                    : null
                }
              />
              <FieldItem
                label="Approved Template Version"
                value={quotation.approvedTemplateVersionId}
              />
              <FieldItem
                label="Approved Artifact"
                value={quotation.approvedArtifact?.fileName ?? null}
              />
              <FieldItem
                label="Artifact Generated By"
                value={
                  quotation.approvedArtifact?.generatedByName ??
                  quotation.approvedArtifact?.generatedBy ??
                  null
                }
              />
              <FieldItem
                label="Artifact Generated At"
                value={
                  quotation.approvedArtifact?.generatedAt
                    ? new Date(
                        quotation.approvedArtifact.generatedAt,
                      ).toLocaleString()
                    : null
                }
              />
              <FieldItem
                label="Artifact Checksum"
                value={
                  quotation.approvedArtifact?.checksum?.slice(0, 16) ?? null
                }
              />
              <div className="space-y-2">
                <div className="text-muted-foreground text-xs">
                  Artifact Status
                </div>
                <div className="flex flex-wrap items-center gap-2">
                  {quotation.approvedArtifact ? (
                    <Badge
                      variant={
                        quotation.approvedArtifact.status === "locked"
                          ? "default"
                          : "secondary"
                      }
                    >
                      {quotation.approvedArtifact.status}
                    </Badge>
                  ) : (
                    <span className="text-sm">-</span>
                  )}
                  {quotation.approvedArtifact?.lockedAt ? (
                    <span className="text-muted-foreground text-xs">
                      Locked{" "}
                      {new Date(
                        quotation.approvedArtifact.lockedAt,
                      ).toLocaleString()}
                    </span>
                  ) : null}
                </div>
              </div>
              {quotation.hasLegacyApprovedPdf ? (
                <div className="rounded-lg border border-dashed p-3 text-sm">
                  <div className="font-medium">
                    Legacy approved PDF detected
                  </div>
                  <div className="text-muted-foreground mt-1">
                    This quotation still points to the old `public/generated`
                    storage path and has not been migrated into the artifact
                    storage model yet.
                  </div>
                </div>
              ) : null}
            </CardContent>
          </Card>
        </div>
      </div>
    </div>
  );
}
