'use client';
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState, useMemo } from 'react';
import { build_issue_tree, format_month } from '../../../utils/issue_bucketing.js';
import { cn } from './shared.js';
/** Below this total, all levels start expanded. At or above, only the rule summary is visible. */
const AUTO_EXPAND_THRESHOLD = 10;
export function IssueGroupTree({ mode, result, on_send_back, hide_actions }) {
    const tree = useMemo(() => build_issue_tree(result), [result]);
    const auto_expand = tree.total_count <= AUTO_EXPAND_THRESHOLD;
    const [rule_open, set_rule_open] = useState(auto_expand);
    const [open_categories, set_open_categories] = useState(() => auto_expand ? new Set(tree.categories.map(c => c.kind)) : new Set());
    const [open_buckets, set_open_buckets] = useState(() => auto_expand ? new Set(all_bucket_keys(tree)) : new Set());
    const [send_back_open_kinds, set_send_back_open_kinds] = useState(new Set());
    const [feedback_overrides, set_feedback_overrides] = useState({});
    const get_feedback = (cat) => feedback_overrides[cat.kind] ?? compose_default_feedback(cat, tree);
    const is_send_back_open = (kind) => send_back_open_kinds.has(kind);
    const toggle_category = (kind) => {
        set_open_categories(prev => {
            const next = new Set(prev);
            if (next.has(kind))
                next.delete(kind);
            else
                next.add(kind);
            return next;
        });
    };
    const toggle_bucket = (key) => {
        set_open_buckets(prev => {
            const next = new Set(prev);
            if (next.has(key))
                next.delete(key);
            else
                next.add(key);
            return next;
        });
    };
    const handle_open_send_back = (kind) => {
        set_send_back_open_kinds(prev => new Set([...prev, kind]));
    };
    const handle_cancel_send_back = (kind) => {
        set_send_back_open_kinds(prev => {
            const next = new Set(prev);
            next.delete(kind);
            return next;
        });
    };
    const handle_set_feedback = (kind, text) => {
        set_feedback_overrides(prev => ({ ...prev, [kind]: text }));
    };
    const handle_confirm_send_back = (kind) => {
        const cat = tree.categories.find(c => c.kind === kind);
        if (!cat)
            return;
        const all_issues = collect_issues(cat);
        const total_amount = aggregate_amount(all_issues.map(i => i.amount));
        const date_range_str = tree.date_range
            ? `${tree.date_range.earliest} - ${tree.date_range.latest}`
            : undefined;
        const send_back = {
            rule_id: tree.rule_id,
            rule_name: tree.rule_name,
            issue_description: compose_group_summary(cat, tree),
            agent_feedback: get_feedback(cat),
            category_kind: kind,
            amount: total_amount,
            date: date_range_str,
            child_issues: all_issues.map(issue => ({
                issue_id: issue.issue_id,
                issue_description: issue.issue_description,
                date: issue.date,
                kind: issue.kind,
                amount: issue.amount,
            })),
        };
        on_send_back?.([send_back], []);
        // close the form after confirming
        set_send_back_open_kinds(prev => {
            const next = new Set(prev);
            next.delete(kind);
            return next;
        });
    };
    // Single-category trees promote the per-category Send Back button to the rule row,
    // because the category header is hidden when there's only one. Accept stays file-level only
    // in v1 (per-category Accept would require per-category persistence on ContentItem).
    const single_category = tree.categories.length === 1;
    const single_cat = single_category ? tree.categories[0] : null;
    return (_jsxs("div", { className: "border border-[#E2E8F0] rounded-md bg-white", children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-2", children: [_jsxs("button", { type: "button", onClick: () => set_rule_open(o => !o), "aria-expanded": rule_open, className: "flex items-center gap-2 flex-1 text-left hover:bg-[#FAFBFC] transition-colors", children: [_jsx(Chevron, { open: rule_open }), _jsx("span", { className: "text-[12px] font-medium text-[#1E293B] flex-1", children: tree.rule_name }), _jsxs("span", { className: "text-[11px] text-[#64748B]", children: [tree.total_count, " issue", tree.total_count !== 1 ? 's' : ''] }), tree.date_range && (_jsxs("span", { className: "text-[10px] text-[#94A3B8]", children: ["(", format_month(tree.date_range.earliest), " \u2013 ", format_month(tree.date_range.latest), ")"] }))] }), mode === 'agent' && !hide_actions && single_cat && !is_send_back_open(single_cat.kind) && (_jsx("button", { type: "button", onClick: () => handle_open_send_back(single_cat.kind), className: "text-[11px] font-medium text-white bg-[#F59E0B] hover:bg-[#D97706] px-2.5 py-0.5 rounded cursor-pointer", children: "Send Back" }))] }), rule_open && (_jsx("div", { className: "border-t border-[#E2E8F0]", children: tree.categories.map(cat => (_jsx(CategoryRow, { cat: cat, total: tree.total_count, degenerate_category: single_category, open: open_categories.has(cat.kind), send_back_open: is_send_back_open(cat.kind), feedback: get_feedback(cat), mode: mode, hide_actions: hide_actions, open_buckets: open_buckets, on_toggle: () => toggle_category(cat.kind), on_toggle_bucket: toggle_bucket, on_open_send_back: () => handle_open_send_back(cat.kind), on_cancel_send_back: () => handle_cancel_send_back(cat.kind), on_set_feedback: text => handle_set_feedback(cat.kind, text), on_confirm_send_back: () => handle_confirm_send_back(cat.kind) }, cat.kind))) }))] }));
}
function CategoryRow({ cat, degenerate_category, open, send_back_open, feedback, mode, hide_actions, open_buckets, on_toggle, on_toggle_bucket, on_open_send_back, on_cancel_send_back, on_set_feedback, on_confirm_send_back, }) {
    // Hide the category tier when there's only one — render its contents directly under the rule.
    if (degenerate_category) {
        return (_jsx(CategoryBody, { cat: cat, send_back_open: send_back_open, feedback: feedback, mode: mode, open_buckets: open_buckets, on_toggle_bucket: on_toggle_bucket, on_cancel_send_back: on_cancel_send_back, on_set_feedback: on_set_feedback, on_confirm_send_back: on_confirm_send_back }));
    }
    return (_jsxs("div", { className: "border-b border-[#E2E8F0] last:border-b-0", children: [_jsxs("div", { className: "flex items-center gap-2 px-3 py-1.5 pl-6", children: [_jsxs("button", { type: "button", onClick: on_toggle, "aria-expanded": open, className: "flex items-center gap-2 flex-1 text-left", children: [_jsx(Chevron, { open: open, small: true }), _jsx("span", { className: "text-[11px] font-medium text-[#334155]", children: cat.label }), _jsxs("span", { className: "text-[11px] text-[#64748B]", children: ["\u2014 ", cat.count] })] }), mode === 'agent' && !hide_actions && !send_back_open && (_jsx("button", { type: "button", onClick: on_open_send_back, className: "text-[10px] font-medium text-white bg-[#F59E0B] hover:bg-[#D97706] px-2 py-0.5 rounded cursor-pointer", children: "Send Back" }))] }), open && (_jsx(CategoryBody, { cat: cat, send_back_open: send_back_open, feedback: feedback, mode: mode, open_buckets: open_buckets, on_toggle_bucket: on_toggle_bucket, on_cancel_send_back: on_cancel_send_back, on_set_feedback: on_set_feedback, on_confirm_send_back: on_confirm_send_back }))] }));
}
function CategoryBody({ cat, send_back_open, feedback, mode, open_buckets, on_toggle_bucket, on_cancel_send_back, on_set_feedback, on_confirm_send_back, }) {
    const degenerate_buckets = cat.time_buckets.length === 0;
    return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "px-3 pb-2 pl-9", children: [!degenerate_buckets && cat.time_buckets.map(bucket => (_jsx(BucketRow, { bucket: bucket, open: open_buckets.has(bucket.key), on_toggle: () => on_toggle_bucket(bucket.key) }, bucket.key))), cat.undated_issues.length > 0 && (_jsx("ul", { className: "space-y-0.5 text-[11px] font-mono text-[#64748B]", children: cat.undated_issues.map((issue, idx) => (_jsx("li", { children: issue.issue_description }, `${issue.issue_id}-${idx}`))) }))] }), mode === 'agent' && send_back_open && (_jsxs("div", { className: "px-3 pb-3 pl-9 space-y-1.5", children: [_jsx("div", { className: "text-[10px] font-semibold text-[#D97706] uppercase tracking-wider", children: "Message to client" }), _jsx("textarea", { className: "w-full border border-amber-200 rounded px-2 py-1.5 text-[12px] resize-none focus:outline-none focus:ring-1 focus:ring-amber-400 placeholder:text-[#CBD5E1] bg-white", rows: 3, value: feedback, onChange: e => on_set_feedback(e.target.value) }), _jsxs("div", { className: "flex justify-end gap-2", children: [_jsx("button", { type: "button", onClick: on_cancel_send_back, className: "text-[11px] text-[#94A3B8] px-3 py-1.5 cursor-pointer", children: "Cancel" }), _jsx("button", { type: "button", onClick: on_confirm_send_back, className: "text-[11px] font-medium text-white bg-[#F59E0B] hover:bg-[#D97706] px-3 py-1.5 rounded cursor-pointer", children: "Confirm Send Back" })] })] }))] }));
}
function BucketRow({ bucket, open, on_toggle }) {
    return (_jsxs("div", { children: [_jsxs("button", { type: "button", onClick: on_toggle, "aria-expanded": open, className: "w-full flex items-center gap-1 text-left hover:text-[#1E293B] transition-colors py-0.5", children: [_jsx(Chevron, { open: open, small: true }), _jsx("span", { className: "text-[11px] font-medium text-[#475569]", children: bucket.label }), _jsxs("span", { className: "text-[11px] text-[#94A3B8]", children: ["\u2014 ", bucket.count] })] }), open && (_jsx("ul", { className: "pl-5 mt-0.5 space-y-0.5 text-[11px] font-mono text-[#64748B]", children: bucket.issues.map((issue, idx) => (_jsxs("li", { children: [_jsx("span", { className: "text-[#94A3B8]", children: issue.date }), _jsx("span", { className: "ml-2", children: issue.issue_description })] }, `${issue.issue_id}-${idx}`))) }))] }));
}
function Chevron({ open, small }) {
    const cls = small ? 'w-3 h-3' : 'w-3.5 h-3.5';
    return (_jsx("svg", { "aria-hidden": "true", className: cn(cls, 'flex-shrink-0 text-[#94A3B8] transition-transform', open && 'rotate-90'), fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }));
}
function all_bucket_keys(tree) {
    const keys = [];
    for (const cat of tree.categories) {
        for (const b of cat.time_buckets)
            keys.push(b.key);
    }
    return keys;
}
function collect_issues(cat) {
    const out = [];
    for (const b of cat.time_buckets)
        for (const i of b.issues)
            out.push(i);
    for (const i of cat.undated_issues)
        out.push(i);
    return out;
}
function compose_group_summary(cat, tree) {
    const range = tree.date_range;
    if (range)
        return `${cat.count} ${cat.label.toLowerCase()} between ${format_month(range.earliest)} and ${format_month(range.latest)}`;
    return `${cat.count} ${cat.label.toLowerCase()}`;
}
function compose_default_feedback(cat, tree) {
    const issues = collect_issues(cat);
    if (issues.length === 0)
        return compose_group_summary(cat, tree);
    // Per-issue line: prefer client_comment (LLM's client-facing draft) over
    // issue_description (agent-facing summary). Both are populated by the validation
    // rule's LLM prompt — edit the rule prompt in Prompt Editor to control the wording.
    const get_line = (issue) => (issue.client_comment?.trim() || issue.issue_description).trim();
    if (issues.length === 1)
        return get_line(issues[0]);
    // Multi-issue: prepend a friendly header and list each issue as a bullet.
    const intro = `I found ${issues.length} issues with the document I'd like to clarify:`;
    const bullets = issues.map(i => `- ${get_line(i)}`).join('\n');
    return `${intro}\n\n${bullets}`;
}
/** Sum a list of amount strings (e.g. ["$437.47", "$12.10"]) into a formatted total string.
 *  Returns undefined if any entry is missing or unparseable — partial totals would mislead. */
function aggregate_amount(amounts) {
    if (amounts.length === 0)
        return undefined;
    let total = 0;
    for (const a of amounts) {
        if (!a)
            return undefined;
        const cleaned = a.replace(/[^\d.-]/g, '');
        const num = parseFloat(cleaned);
        if (isNaN(num))
            return undefined;
        total += num;
    }
    return `$${total.toFixed(2)}`;
}
//# sourceMappingURL=issue_group_tree.js.map