import { useState } from 'react';
import { Link, useForm } from '@inertiajs/react';
import { ArrowLeft, Check, RotateCcw, X } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout';
import { Button } from '@/Components/ui/button';
import { StatusBadge } from '@/Components/Proto/UI/StatusBadge';
import { QuotationHistoryCell } from '@/Components/MenuQuotations/QuotationDetailPage/QuotationHistoryCell';
import { QuotationAuditCell } from '@/Components/MenuQuotations/QuotationDetailPage/QuotationAuditCell';
import { HistoryTimelinePopover } from '@/Components/MenuQuotations/QuotationDetailPage/HistoryTimelinePopover';
import { QuotationLinks } from '@/Components/MenuQuotations/QuotationDetailPage/QuotationLinks';
import { CustomerArPending } from '@/Components/MenuQuotations/CustomerOutstanding/CustomerArPending';
import CompanyTabs from '@/Components/MenuCompanies/CompanyTabs';
import { useCustomerAr } from '@/Hooks/useCustomerAr';
import { useToast } from '@/Components/Toast';
import { DecisionBar } from '@/Components/MenuSampleOrders/DecisionBar';
import { DecisionConfirmDialog } from '@/Components/MenuSampleOrders/DecisionConfirmDialog';

// Maps real quotationstatus.StatusName / quotationdetailstatus.StatusDetailName to a tone.
const STATUS_TONES = {
    'Request': 'warning',
    'Approval SM': 'primary',
    'Approval PM': 'primary',
    'Revise': 'warning',
    'Reject': 'danger',
    'Cancel': 'danger',
    'Print': 'success',
    'Feedback': 'primary',
    'Process To Order': 'success',
    'Good Shipped': 'success',
    'Good Receive': 'success',
    'Update PO Number': 'neutral',
    'Update Delivery Fee': 'neutral',
    'Price Indication': 'neutral',
};
function statusTone(status) {
    return STATUS_TONES[status] || 'neutral';
}

function getCreatedOnString(q) {
    let dateStr = '';
    if (q.history?.entries && q.history.entries.length > 0) {
        // The entries are sorted descending, so the last one is the oldest (creation).
        const oldest = q.history.entries[q.history.entries.length - 1];
        if (oldest?.Tanggal && oldest.Tanggal !== '—') {
            dateStr = oldest.Tanggal;
        }
    }
    if (!dateStr) {
        dateStr = q.general?.['Quotation Date'] || q.general?.['Sample Order Date'] || q.tanggal || '';
    }
    if (!dateStr || dateStr === '—') return '';
    try {
        const parts = dateStr.trim().split(/\s+/);
        const datePart = parts[0];
        const timePart = parts[1] || '';
        
        let formattedDate = datePart;
        if (datePart.includes('-')) {
            const [y, m, d] = datePart.split('-');
            const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
            const monthName = months[parseInt(m, 10) - 1] || m;
            formattedDate = `${parseInt(d, 10)} ${monthName} ${y}`;
        }
        
        let formattedTime = '';
        if (timePart) {
            const tParts = timePart.split(':');
            if (tParts.length >= 2) {
                formattedTime = `${tParts[0]}:${tParts[1]}`;
            }
        }
        
        if (formattedDate && formattedTime) {
            return `Created on ${formattedDate} · ${formattedTime}`;
        } else if (formattedDate) {
            return `Created on ${formattedDate}`;
        }
    } catch (e) {
        // Ignore
    }
    return `Created on ${dateStr}`;
}

const DOC_SECTION = 'relative rounded-xl border border-border bg-card px-4 pt-3.5 pb-3 shadow-sm';
const DOC_HEADING = 'm-0 mb-3 flex items-center gap-2 text-xs font-bold uppercase tracking-wide text-foreground';
const DOC_ICON = 'inline-grid size-6 shrink-0 place-items-center rounded-full border border-primary/50 bg-transparent text-primary';
const BACK_BTN = 'inline-flex h-9 items-center justify-center gap-1.5 rounded-lg border border-input bg-card px-4 text-center text-xs font-bold text-foreground transition-colors hover:border-primary hover:text-primary';

function DocList({ fields }) {
    if (!fields || Object.keys(fields).length === 0)
        return <p className="px-0 py-1 text-[0.82rem] text-muted-foreground">Tidak ada data.</p>;
    return (
        <dl className="grid gap-0">
            {Object.entries(fields).map(([key, val]) => (
                <div key={key} className="grid grid-cols-[minmax(0,110px)_1fr] items-baseline gap-2.5 border-b border-border/40 py-1.75 last:border-b-0">
                    <dt className="m-0 text-[11px] font-medium text-muted-foreground">{key}</dt>
                    <dd className="m-0 wrap-break-word text-xs font-medium text-foreground">{val || '—'}</dd>
                </div>
            ))}
        </dl>
    );
}

// The three decisions post to three separate routes here (Sample Order has one route with an
// {action} segment), so the dialog's action key is mapped to a route name.
const DECISION_ROUTES = {
    approve: 'quotations.approval-sm.approve',
    revise: 'quotations.approval-sm.revise',
    reject: 'quotations.approval-sm.reject',
};

export default function QuotationApprovalSmDetail({ quotation, canAct = false, links = [], linkContext = null }) {
    const { show: showToast } = useToast();
    const q = quotation;

    const customerAr = useCustomerAr(q?.companyId ?? null, 'customer-ar.pending.byCompany');

    const form = useForm({ comment: '' });

    // Per-action summary for the confirm dialog. The stock-check advisory is only true of
    // approve — showing it under Revise/Reject (as the single unconditional summary used to)
    // told the approver to check stock before rejecting, which is nonsense. Revise/reject
    // instead say what actually happens to the quotation, matching applySmDecision().
    const CONFIRM_SUMMARY = {
        approve: 'Pastikan stock barang sudah dicek sebelum approve.',
        revise: 'Quotation dan seluruh line item kembali ke Revise, dan email revisi dikirim ke pembuat.',
        reject: 'Quotation dan seluruh line item ditandai Reject, dan email penolakan dikirim ke pembuat.',
    };

    // Decision runs through DecisionConfirmDialog: the comment is typed and read back there,
    // which window.confirm could neither show nor require.
    const [confirm, setConfirm] = useState(null);   // 'approve' | 'revise' | 'reject' | null

    // The dialog stays OPEN across the request — it is not closed before posting. On success the
    // page redirects to the list and unmounts anyway, and on 422 the comment error then has
    // somewhere visible to land instead of only the generic toast. commentMaxLength={500} below
    // stops the over-length 422 client-side, but NOT the charset one: a comment carrying CJK or
    // emoji cannot fit quotationassignment.Comment (latin1) and only FitsColumnCharset catches
    // it, server-side. Closing first (`setConfirm(null)` before post, which this page used to do)
    // makes the `error` prop passed below unreachable in exactly that case.
    const runConfirmed = () => {
        if (!canAct || form.processing || !confirm) return;
        form.post(route(DECISION_ROUTES[confirm], q.id), {
            onError: () => showToast('Please check the form and try again.', 'error'),
        });
    };

    // Build section fields — fallback ke top-level fields kalau detail belum ada
    const generalFields = q.general || {
        'No': q.id,
        'Quotation Status': q.statusLabel || '—',
        'Feedback Status': q.feedback || '—',
        'Quotation Date': q.tanggal || '—',
        'Creator': q.creator || '—',
        'Sales': q.sales || '—',
    };

    const companyFields = q.companyContact || {
        'Company Name': q.company || '—',
        'Division': q.division || '—',
        'Industry': q.industry || '—',
        'Company Category': q.companyCategory || '—',
    };

    const orderFields = q.order || {
        'Customer PO No': q.poNo || '—',
        'Customer PO Date': q.poDate || '—',
        'Delivery Date': q.deliveryDate || '—',
    };

    const pricingFields   = q.pricing    || {};
    const termsFields     = q.terms      || {};
    const businessFields  = q.business   || { 'Division': q.division || '—', 'Industry': q.industry || '—', 'Company Category': q.companyCategory || '—' };
    const additionalFields = q.additional || { 'Creator': q.creator || '—', 'Sales': q.sales || '—', 'Comment': q.comment || '—' };
    const historyFields   = q.history?.fields || {};
    const lineItems       = q.lineItems  || [];
    const totals          = q.totals     || { usd: '$0', idr: 'Rp 0', dpPct: '0.00%', dpUsd: '$0', deliveryFee: '$0' };

    return (
        <section className="flex min-w-0 flex-col gap-4.5">
            <header className="flex items-center justify-between gap-4">
                <div>
                    <p className="mb-1.5 flex items-center gap-2 text-xs font-semibold text-muted-foreground">
                        <Link href={route('quotations.approval-sm')} className="text-muted-foreground no-underline hover:text-primary">Approval SM</Link>
                        <span aria-hidden="true">›</span>
                        <span className="text-foreground">View Quotation</span>
                    </p>
                </div>
                <Link href={route('quotations.approval-sm')} className={BACK_BTN}>
                    <ArrowLeft className="size-3.5" />
                    Back to List
                </Link>
            </header>

            {/* Hero */}
            <div className="flex items-center justify-between gap-4 mt-1">
                <div className="flex flex-col gap-1 min-w-0">
                    <div className="flex items-center gap-3">
                        <h1 className="m-0 text-2xl font-extrabold tracking-tight text-foreground">Quotation #{q.id}</h1>
                        {q.statusLabel && (
                            <StatusBadge tone={statusTone(q.status)}>{q.statusLabel}</StatusBadge>
                        )}
                    </div>
                    {getCreatedOnString(q) && (
                        <p className="m-0 text-[13px] font-medium text-muted-foreground">{getCreatedOnString(q)}</p>
                    )}
                </div>
            </div>

            {/* Stats Strip */}
            <article className="flex items-center gap-2 rounded-2xl border border-border bg-card shadow-sm p-[14px_18px]">
                <div className="grid min-w-0 flex-1 grid-cols-5 max-[860px]:grid-cols-2 gap-0">
                    {[
                        { label: 'Subtotal (USD)', value: totals.usd },
                        { label: 'Subtotal (IDR)', value: totals.idr },
                        { label: 'DP Percentage', value: totals.dpPct },
                        { label: 'DP Price (USD)', value: totals.dpUsd },
                        { label: 'Delivery Fee', value: totals.deliveryFee },
                    ].map((c, i) => (
                        <div key={c.label} className={`flex min-w-0 flex-col gap-0.5 p-[0_14px] ${i > 0 ? 'border-l border-border' : ''}`}>
                            <small className="block text-[11px] font-medium text-muted-foreground">{c.label}</small>
                            <strong className="block whitespace-nowrap text-base font-extrabold leading-[1.1] text-card-foreground">{c.value}</strong>
                        </div>
                    ))}
                </div>
                {q.history?.entries?.length > 0 && (
                    <div className="flex shrink-0 items-center gap-2 self-center border-l border-border pl-3">
                        <HistoryTimelinePopover entries={q.history.entries} />
                    </div>
                )}
            </article>

            {/* Doc Sections */}
            <div className="grid grid-cols-3 gap-3.5 max-[1180px]:grid-cols-2 max-[860px]:grid-cols-1">
                <section className={DOC_SECTION} data-section-id="general">
                    <h3 className={DOC_HEADING}>
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/>
                            </svg>
                        </span>
                        General Information
                    </h3>
                    <DocList fields={generalFields} />
                </section>

                <section className={DOC_SECTION} data-section-id="company">
                    <h3 className={DOC_HEADING}>
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
                            </svg>
                        </span>
                        Company &amp; Contact
                    </h3>
                    <DocList fields={companyFields} />
                </section>

                <section className={DOC_SECTION} data-section-id="order">
                    <h3 className={DOC_HEADING}>
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>
                            </svg>
                        </span>
                        Order Information
                    </h3>
                    <DocList fields={orderFields} />
                </section>

                <section className={DOC_SECTION} data-section-id="pricing">
                    <h3 className={DOC_HEADING}>
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <line x1="12" y1="2" x2="12" y2="22"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>
                            </svg>
                        </span>
                        Pricing Information
                    </h3>
                    <DocList fields={pricingFields} />
                </section>

                <section className={DOC_SECTION} data-section-id="terms">
                    <h3 className={DOC_HEADING}>
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <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"/><polyline points="9 14 11 16 15 12"/>
                            </svg>
                        </span>
                        Terms &amp; Conditions
                    </h3>
                    <DocList fields={termsFields} />
                </section>

                <section className={DOC_SECTION} data-section-id="business">
                    <h3 className={DOC_HEADING}>
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <path d="M3 21h18"/><path d="M5 21V7l7-4 7 4v14"/>
                                <path d="M10 9h.01"/><path d="M14 9h.01"/><path d="M10 13h.01"/><path d="M14 13h.01"/><path d="M10 17h.01"/><path d="M14 17h.01"/>
                            </svg>
                        </span>
                        Business Information
                    </h3>
                    <DocList fields={businessFields} />
                    <h4 className="mt-4 mb-2 border-t border-dashed border-border pt-3 text-[11px] font-extrabold uppercase tracking-wide text-muted-foreground">Additional Information</h4>
                    <DocList fields={additionalFields} />
                </section>
            </div>

            {/* Line Items */}
            <article className="rounded-2xl border border-border bg-card shadow-sm">
                <header className="flex items-center justify-between gap-3 border-b border-border p-[18px_22px]">
                    <div className="flex items-center gap-2.5">
                        <span className={DOC_ICON} aria-hidden="true">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                                <line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/>
                                <circle cx="4" cy="6" r="1"/><circle cx="4" cy="12" r="1"/><circle cx="4" cy="18" r="1"/>
                            </svg>
                        </span>
                        <div className="[&>h2]:m-0 [&>h2]:text-sm [&>h2]:font-extrabold [&>h2]:leading-[1.2] [&>h2]:text-card-foreground [&>small]:block [&>small]:text-[11px] [&>small]:font-medium [&>small]:text-muted-foreground">
                            <h2>Quotation Details</h2>
                            <small>Line items breakdown</small>
                        </div>
                    </div>
                </header>

                {lineItems.length === 0 ? (
                    <p className="p-6 text-[0.85rem] text-muted-foreground">Tidak ada line item.</p>
                ) : (
                    <div className="overflow-x-auto rounded-xl border border-border">
                        <table className="w-full min-w-575 border-collapse [&_thead_th]:whitespace-nowrap [&_thead_th]:border-b [&_thead_th]:border-border [&_thead_th]:px-3 [&_thead_th]:py-3 [&_thead_th]:text-left [&_thead_th]:text-[11px] [&_thead_th]:font-semibold [&_thead_th]:uppercase [&_thead_th]:tracking-wide [&_thead_th]:text-muted-foreground [&_th.number]:text-right [&_td.number]:text-right [&_th.text-center]:text-center [&_td.text-center]:text-center [&_tbody_td]:whitespace-nowrap [&_tbody_td]:border-b [&_tbody_td]:border-border/50 [&_tbody_td]:px-3 [&_tbody_td]:py-3 [&_tbody_td]:text-[11px] [&_tbody_td]:font-medium [&_tbody_td]:text-foreground [&_tbody_tr:last-child_td]:border-b-0 [&_tbody_tr:hover]:bg-secondary/60">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>Status</th>
                                    <th>Principal</th>
                                    <th>Product Name</th>
                                    <th className="number">Qty</th>
                                    <th>Pack ID</th>
                                    <th>Satuan</th>
                                    <th className="number">Order Qty</th>
                                    <th>Satuan Order</th>
                                    <th className="number">USD Rate</th>
                                    <th className="number">Unit USD</th>
                                    <th className="number">Total USD</th>
                                    <th className="number">Unit IDR</th>
                                    <th className="number">Total IDR</th>
                                    <th>Application</th>
                                    <th>Remarks</th>
                                    <th>Remark Internal</th>
                                    <th className="!text-center">Quotation History</th>
                                    <th className="!text-center">History</th>
                                </tr>
                            </thead>
                            <tbody>
                                {lineItems.map(item => (
                                    <tr key={item.id}>
                                        <td className="tabular-nums">{item.id}</td>
                                        <td>
                                            {item.statusLabel
                                                ? <StatusBadge tone={statusTone(item.status)}>{item.statusLabel}</StatusBadge>
                                                : '—'}
                                        </td>
                                        <td>{item.principalName || '—'}</td>
                                        <td><strong className="font-semibold text-foreground">{item.productName || '—'}</strong></td>
                                        <td className="number tabular-nums">{item.qty || '—'}</td>
                                        <td>{item.quotationPackId || '—'}</td>
                                        <td>{item.satuanId || '—'}</td>
                                        <td className="number tabular-nums">{item.orderQty || '—'}</td>
                                        <td>{item.satuanOrderQty || '—'}</td>
                                        <td className="number tabular-nums">{item.usdRate || '—'}</td>
                                        <td className="number tabular-nums">{item.unitUsd || '—'}</td>
                                        <td className="number tabular-nums"><strong className="font-semibold text-foreground">{item.totalUsd ? '$' + item.totalUsd : '—'}</strong></td>
                                        <td className="number tabular-nums">{item.unitIdr || '—'}</td>
                                        <td className="number tabular-nums">{item.totalIdr ? 'Rp ' + item.totalIdr : '—'}</td>
                                        <td>{item.application || '—'}</td>
                                        <td>{item.remarks || '—'}</td>
                                        <td>{item.remarkInternal || '—'}</td>
                                        {/* Legacy listquotationdetailsview.php "QuotationHistory": last 10 quoted
                                            lines of this product for the company, across all its quotations. */}
                                        <td className="text-center">
                                            <QuotationHistoryCell items={item.quotationHistory} />
                                        </td>
                                        {/* Legacy "History": this line's quotationdetailsassignment audit log. */}
                                        <td className="text-center">
                                            <QuotationAuditCell items={item.history} />
                                        </td>
                                    </tr>
                                ))}
                            </tbody>
                        </table>
                    </div>
                )}
            </article>

            {/* Legacy quotationapprovalsm.php "Link With" — read-only display table. */}
            {linkContext && <QuotationLinks links={links} linkContext={linkContext} readOnly />}

            {/* Legacy quotationapprovalsm.php "AR - Pending" — customer-ar.pending.byCompany. */}
            <CustomerArPending data={customerAr.data} loading={customerAr.loading} />

            {/* Company Records — quotationapprovalsm.php embeds the same 12 panes as the
                quotation detail pages (Complain yes; Project and Visit Report All no). */}
            {q?.companyId > 0 && (
                <CompanyTabs companyId={q.companyId} preset="quotation" />
            )}

            {/* The three decisions, pinned. They used to sit in the page header — on a screen
                that runs hero → stats → line items → AR → history → Company Records, deciding
                meant scrolling back to the top every time.
                Order is the locked one: Approve LEFTMOST, heavier to the right. The header had
                it exactly reversed (Reject · Revise · Approve).
                The comment itself lives in DecisionConfirmDialog, never inside the pill.

                UNMOUNTED, not disabled, when canAct is false. Approval SM is held by every head
                of the division at once, so this page is routinely opened — from the queue, or
                from a `quotation.awaiting_sm` notification — for a record another SM has
                already decided. Greyed-out buttons would say "not right now"; the honest answer
                is that the work is finished. Same shape as MenuProjects/ApprovalSmDetail.
                The pill's own 112px spacer goes with it, which is correct: nothing is floating
                over the content any more. */}
            {canAct ? (
                <DecisionBar>
                    {/* Nothing in a DecisionBar pill may be shrinkable text: it lays children out
                        with sm:flex-nowrap and no child sets flex-shrink:0 by default, so whatever
                        is left shrinkable gets crushed to its min-content width and wraps. Long
                        prose belongs in the confirm dialog, not here (commit 0465272a tried max-w
                        on a paragraph instead and found max-width cannot stop a flex item from
                        shrinking) — which is why the stock-check advisory lives in CONFIRM_SUMMARY
                        and only the short id sits here, pinned with shrink-0 + whitespace-nowrap. */}
                    <span className="shrink-0 whitespace-nowrap text-[12px] font-semibold text-muted-foreground">Quotation #{q.id}</span>
                    <div className="flex items-center gap-2.5">
                        <Button
                            type="button"
                            disabled={form.processing}
                            onClick={() => setConfirm('approve')}
                            className="h-9 gap-1.5 rounded-lg bg-linear-to-br from-violet-500 to-primary px-4 text-xs font-bold text-white shadow-sm transition-[filter] hover:brightness-105"
                        >
                            <Check className="size-3.5" /> Approve SM
                        </Button>
                        <Button
                            type="button"
                            variant="outline"
                            disabled={form.processing}
                            onClick={() => setConfirm('revise')}
                            className="h-9 gap-1.5 rounded-lg border border-primary bg-card px-4 text-xs font-bold text-primary hover:bg-primary/10"
                        >
                            <RotateCcw className="size-3.5" /> Revise
                        </Button>
                        <Button
                            type="button"
                            variant="outline"
                            disabled={form.processing}
                            onClick={() => setConfirm('reject')}
                            className="h-9 gap-1.5 rounded-lg border border-danger/40 bg-card px-4 text-xs font-bold text-danger hover:bg-danger/10"
                        >
                            <X className="size-3.5" /> Reject
                        </Button>
                    </div>
                </DecisionBar>
            ) : (
                /* One muted sentence in place of the panel, following StageActionPanel (Credit
                   Ceiling) — the only precedent in this app for replacing a decision panel
                   rather than disabling it. Two cases, because "not yet" and "already done" are
                   different answers and the reader is entitled to know which one they are
                   looking at. WHO decided is deliberately not repeated here: it lives one click
                   away in the header's history popover, like everywhere else in this app. */
                <p className="m-0 text-sm text-muted-foreground">
                    {q.status === 'Request'
                        ? 'Quotation masih Request — PM belum approve, keputusan SM belum bisa.'
                        : 'Quotation ini sudah diputuskan — keputusan SM tidak bisa dilakukan lagi.'}
                </p>
            )}

            {/* NO commentRequired: the dialog's default is exactly the locked rule — required on
                revise/reject, optional on approve — and QuotationApprovalSmRequest validates the
                same way (its commentIsRequired() reads the route name). origin/main forced it on
                for all three and claimed the FormRequest demanded it; that claim was false at both
                2026-08-10 and this merge. Forcing it here without changing the FormRequest (or
                vice versa) is what makes the asterisk promise something nothing enforces, and
                ui-conventions.md locks the split rule.
                Mounted only alongside the bar — with no buttons there is nothing that can open
                it, and leaving it behind would keep a live comment textarea on a page whose
                whole point is that it is now read-only. */}
            {canAct && (
                <DecisionConfirmDialog
                    action={confirm}
                    onCancel={() => setConfirm(null)}
                    onConfirm={runConfirmed}
                    comment={form.data.comment}
                    onCommentChange={(v) => form.setData('comment', v)}
                    processing={form.processing}
                    error={form.errors.comment}
                    errors={form.errors}
                    label={confirm === 'approve' ? 'Approve SM' : undefined}
                    commentMaxLength={500}
                    summary={confirm && (
                        <>
                            <p className="m-0 text-[12px] leading-snug text-muted-foreground">
                                {CONFIRM_SUMMARY[confirm]}
                            </p>
                            {/* Comment reaches a person on revise/reject — mandatory there, and
                                mailed verbatim by SendQuotationReviseEmails. Not shown on approve,
                                where the comment is optional and nothing gets emailed. */}
                            {confirm !== 'approve' && (
                                <p className="m-0 mt-1.5 text-[12px] leading-snug text-muted-foreground">
                                    Komentar tercatat di history (dikirim ke pembuat saat revise / reject).
                                </p>
                            )}
                        </>
                    )}
                />
            )}
        </section>
    );
}

QuotationApprovalSmDetail.layout = [AppLayout]
