'use client';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { applyStructuredProfileToDocument, BRAND_VOICE_EXPORT_FILENAME, ensureBrandVoiceDocument, parseBrandVoiceDocument, parseStructuredProfile, } from '@actuate-media/cms-core/brand-voice';
import { AlertTriangle, Download, FileUp, Link2, Loader2, Sparkles } from 'lucide-react';
import { useCallback, useId, useMemo, useRef, useState } from 'react';
import { toast } from 'sonner';
import { BrandVoiceAlignmentPanel } from './brand-voice/BrandVoiceAlignmentPanel.js';
import { BrandVoiceRulesSections } from './brand-voice/BrandVoiceRulesSections.js';
import { SettingsCard, SettingsToggleRow } from './components.js';
const INPUT_CLASS = 'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-60';
const TEXTAREA_CLASS = `${INPUT_CLASS} min-h-[88px] resize-y`;
const DOCUMENT_TEXTAREA_CLASS = `${INPUT_CLASS} min-h-[280px] resize-y font-mono text-sm`;
const LABEL_CLASS = 'mb-1 block text-sm font-medium text-foreground';
const TONE_MAX = 400;
const GUIDELINES_MAX = 2000;
const SAMPLE_MAX = 2000;
function contentCollections(config) {
    const cfg = config;
    if (!cfg?.collections)
        return [];
    const raw = cfg.collections;
    const list = Array.isArray(raw)
        ? raw
        : Object.values(raw);
    return list
        .filter((c) => (c.type === 'page' || c.type === 'post') && !c.admin?.hidden && c.slug)
        .map((c) => ({
        slug: c.slug,
        label: c.labels?.plural ?? c.slug.charAt(0).toUpperCase() + c.slug.slice(1),
    }));
}
function downloadTextFile(filename, contents) {
    const blob = new Blob([contents], { type: 'text/markdown;charset=utf-8' });
    const url = URL.createObjectURL(blob);
    const anchor = document.createElement('a');
    anchor.href = url;
    anchor.download = filename;
    anchor.click();
    URL.revokeObjectURL(url);
}
export function BrandVoiceCard({ value, canEdit, onChange, config, onAnalyze, onScore, editMode, onEditModeChange, aiReadiness, }) {
    const nameId = useId();
    const toneId = useId();
    const audienceId = useId();
    const guidelinesId = useId();
    const sampleId = useId();
    const documentId = useId();
    const generatePanelId = useId();
    const importInputId = useId();
    const urlInputId = useId();
    const uploadInputId = useId();
    const importRef = useRef(null);
    const uploadRef = useRef(null);
    const disabled = !canEdit;
    const collections = useMemo(() => contentCollections(config), [config]);
    const [selectedCollections, setSelectedCollections] = useState(() => collections.map((c) => c.slug));
    const [analyzing, setAnalyzing] = useState(false);
    const [lastSampleCount, setLastSampleCount] = useState(null);
    const [urlInput, setUrlInput] = useState('');
    const [uploads, setUploads] = useState([]);
    const [importError, setImportError] = useState(null);
    const showAdvanced = editMode === 'document';
    const handleStructuredChange = useCallback((structured) => {
        const document = applyStructuredProfileToDocument(value.document.trim() || ensureBrandVoiceDocument(value), structured);
        const sampleText = structured.workedExamples.find((example) => example.onBrand.trim())?.onBrand ??
            value.sampleText;
        onChange({ structured, document, sampleText });
    }, [onChange, value]);
    const toggleCollection = useCallback((slug, checked) => {
        setSelectedCollections((prev) => {
            if (checked)
                return prev.includes(slug) ? prev : [...prev, slug];
            return prev.filter((s) => s !== slug);
        });
    }, []);
    const parsedUrls = useMemo(() => urlInput
        .split('\n')
        .map((line) => line.trim())
        .filter(Boolean)
        .slice(0, 5), [urlInput]);
    const canAnalyze = !disabled &&
        !analyzing &&
        (selectedCollections.length > 0 || parsedUrls.length > 0 || uploads.length > 0);
    const handleAnalyze = useCallback(async () => {
        if (!onAnalyze || !canAnalyze)
            return;
        setAnalyzing(true);
        setLastSampleCount(null);
        try {
            const res = await onAnalyze({
                collections: selectedCollections,
                urls: parsedUrls.length ? parsedUrls : undefined,
                uploads: uploads.length ? uploads : undefined,
            });
            if (!res.ok || !res.draft) {
                toast.error(res.error ?? 'Brand voice analysis failed.');
                return;
            }
            onChange({
                ...res.draft,
                enabled: value.enabled || true,
                version: res.draft.version ?? 1,
                status: res.draft.status ?? 'draft',
                generatedFrom: res.draft.generatedFrom ?? [],
                document: res.draft.document ?? '',
                structured: res.draft.document?.trim()
                    ? parseStructuredProfile(res.draft.document)
                    : value.structured,
            });
            onEditModeChange('form');
            setLastSampleCount(res.sampleCount ?? null);
            toast.success(res.sampleCount
                ? `Draft profile generated from ${res.sampleCount} content sample${res.sampleCount === 1 ? '' : 's'}. Review and save when ready.`
                : 'Draft profile generated. Review and save when ready.');
        }
        finally {
            setAnalyzing(false);
        }
    }, [
        canAnalyze,
        onAnalyze,
        onChange,
        onEditModeChange,
        parsedUrls,
        selectedCollections,
        uploads,
        value.enabled,
    ]);
    const handleExport = useCallback(() => {
        const markdown = ensureBrandVoiceDocument(value);
        downloadTextFile(BRAND_VOICE_EXPORT_FILENAME, markdown);
        toast.success('Brand voice profile exported.');
    }, [value]);
    const handleImportFile = useCallback(async (file) => {
        if (!file)
            return;
        setImportError(null);
        try {
            const text = await file.text();
            const parsed = parseBrandVoiceDocument(text);
            if (!parsed.ok) {
                setImportError(parsed.error);
                toast.error(parsed.error);
                return;
            }
            onChange({
                name: parsed.value.fields.name,
                tone: parsed.value.fields.tone,
                audience: parsed.value.fields.audience,
                guidelines: parsed.value.fields.guidelines,
                sampleText: parsed.value.fields.sampleText,
                document: parsed.value.document,
                version: parsed.value.meta.version,
                status: parsed.value.meta.status,
                generatedFrom: parsed.value.meta.generatedFrom,
                structured: parseStructuredProfile(parsed.value.document),
                enabled: value.enabled || true,
            });
            onEditModeChange('document');
            toast.success('Profile imported. Review and save when ready.');
        }
        catch {
            const message = 'Could not read the selected file.';
            setImportError(message);
            toast.error(message);
        }
        finally {
            if (importRef.current)
                importRef.current.value = '';
        }
    }, [onChange, onEditModeChange, value.enabled]);
    const openAdvanced = useCallback(() => {
        onEditModeChange('document');
        if (!value.document.trim()) {
            onChange({ document: ensureBrandVoiceDocument(value) });
        }
    }, [onChange, onEditModeChange, value]);
    const applyDocumentToFields = useCallback(() => {
        const parsed = parseBrandVoiceDocument(value.document);
        if (!parsed.ok) {
            setImportError(parsed.error);
            toast.error(parsed.error);
            return;
        }
        setImportError(null);
        onChange({
            name: parsed.value.fields.name,
            tone: parsed.value.fields.tone,
            audience: parsed.value.fields.audience,
            guidelines: parsed.value.fields.guidelines,
            sampleText: parsed.value.fields.sampleText,
            version: parsed.value.meta.version,
            status: parsed.value.meta.status,
            generatedFrom: parsed.value.meta.generatedFrom,
            structured: parseStructuredProfile(value.document),
        });
        onEditModeChange('form');
        toast.success('Quick-edit fields updated from the profile document.');
    }, [onChange, onEditModeChange, value.document]);
    const handleUploadFiles = useCallback(async (files) => {
        if (!files?.length)
            return;
        const next = [];
        for (const file of Array.from(files).slice(0, 5)) {
            if (!file.type.startsWith('text/') &&
                !file.name.endsWith('.md') &&
                !file.name.endsWith('.txt')) {
                toast.error(`Skipped ${file.name}: only text or markdown files are supported.`);
                continue;
            }
            const text = await file.text();
            if (!text.trim())
                continue;
            next.push({ name: file.name, text });
        }
        if (next.length === 0) {
            toast.error('No readable text found in the selected files.');
            return;
        }
        setUploads((prev) => [...prev, ...next].slice(0, 5));
        toast.success(`Added ${next.length} upload${next.length === 1 ? '' : 's'}.`);
    }, []);
    return (_jsx(SettingsCard, { title: "Brand voice", description: "Teach the AI how your brand sounds. Applied to content writing and SEO copy.", children: _jsxs("div", { className: "space-y-4", children: [_jsx(SettingsToggleRow, { label: "Apply brand voice", description: "When on, generated copy follows the tone and guidelines below.", checked: value.enabled, disabled: disabled, onChange: (v) => onChange({ enabled: v }) }), aiReadiness && !aiReadiness.ready && aiReadiness.message && (_jsxs("div", { role: "status", className: "border-warning/40 bg-warning/10 text-foreground flex items-start gap-3 rounded-lg border p-4 text-sm", children: [_jsx(AlertTriangle, { size: 16, className: "text-warning mt-0.5 shrink-0", "aria-hidden": "true" }), _jsx("p", { children: aiReadiness.message })] })), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsxs("button", { type: "button", onClick: handleExport, disabled: disabled, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(Download, { size: 14, "aria-hidden": "true" }), "Export .md"] }), _jsxs("button", { type: "button", onClick: () => importRef.current?.click(), disabled: disabled, className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(FileUp, { size: 14, "aria-hidden": "true" }), "Import .md"] }), _jsx("input", { ref: importRef, id: importInputId, type: "file", accept: ".md,text/markdown,text/plain", className: "sr-only", disabled: disabled, onChange: (e) => void handleImportFile(e.target.files?.[0]) }), !showAdvanced ? (_jsx("button", { type: "button", onClick: openAdvanced, disabled: disabled, className: "text-primary hover:text-primary/80 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: "Advanced profile document" })) : (_jsx("button", { type: "button", onClick: () => onEditModeChange('form'), disabled: disabled, className: "text-primary hover:text-primary/80 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: "Back to quick edit" }))] }), importError && (_jsx("div", { role: "alert", className: "border-destructive/30 bg-destructive/10 text-destructive rounded-md border p-4 text-sm", children: importError })), onAnalyze && (_jsxs("div", { id: generatePanelId, className: "border-border space-y-3 rounded-md border border-dashed p-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-foreground text-base font-medium", children: "Generate from content" }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: "Scan published pages and posts, public URLs, or uploaded text files to draft a profile you can edit before saving." })] }), collections.length > 0 && (_jsxs("fieldset", { className: "space-y-2", disabled: disabled || analyzing, children: [_jsx("legend", { className: "text-foreground mb-1 text-sm font-medium", children: "CMS collections" }), collections.map((col) => {
                                    const inputId = `${generatePanelId}-${col.slug}`;
                                    const checked = selectedCollections.includes(col.slug);
                                    return (_jsxs("label", { htmlFor: inputId, className: "text-foreground flex cursor-pointer items-center gap-2 text-sm", children: [_jsx("input", { id: inputId, type: "checkbox", checked: checked, disabled: disabled || analyzing, onChange: (e) => toggleCollection(col.slug, e.target.checked), className: "border-border text-primary focus-visible:ring-ring size-4 rounded border focus-visible:ring-2 focus-visible:outline-none" }), col.label] }, col.slug));
                                })] })), _jsxs("div", { children: [_jsx("label", { htmlFor: urlInputId, className: LABEL_CLASS, children: "Public URLs (optional)" }), _jsx("textarea", { id: urlInputId, value: urlInput, disabled: disabled || analyzing, placeholder: 'https://example.com/about\nOne URL per line, up to 5', onChange: (e) => setUrlInput(e.target.value), className: `${TEXTAREA_CLASS} min-h-[72px] font-mono text-sm` })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: uploadInputId, className: LABEL_CLASS, children: "Upload text files (optional)" }), _jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs("button", { type: "button", disabled: disabled || analyzing || uploads.length >= 5, onClick: () => uploadRef.current?.click(), className: "border-border text-foreground hover:bg-accent inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(FileUp, { size: 16, "aria-hidden": "true" }), "Choose files"] }), uploads.length > 0 && (_jsx("ul", { className: "text-muted-foreground text-sm", children: uploads.map((file) => (_jsxs("li", { className: "flex items-center gap-2", children: [_jsx(Link2, { size: 14, "aria-hidden": "true" }), file.name, _jsx("button", { type: "button", className: "text-primary text-xs", onClick: () => setUploads((prev) => prev.filter((u) => u.name !== file.name)), children: "Remove" })] }, file.name))) }))] }), _jsx("input", { ref: uploadRef, id: uploadInputId, type: "file", accept: ".txt,.md,text/plain,text/markdown", multiple: true, className: "sr-only", onChange: (e) => {
                                        void handleUploadFiles(e.target.files);
                                        e.target.value = '';
                                    } })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs("button", { type: "button", onClick: handleAnalyze, disabled: !canAnalyze, className: "bg-primary text-primary-foreground inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50", children: [analyzing ? (_jsx(Loader2, { size: 16, className: "animate-spin", "aria-hidden": "true" })) : (_jsx(Sparkles, { size: 16, "aria-hidden": "true" })), analyzing ? 'Analyzing…' : 'Analyze & draft profile'] }), lastSampleCount != null && (_jsxs("p", { className: "text-muted-foreground text-sm", "aria-live": "polite", children: ["Last run used ", lastSampleCount, " sample", lastSampleCount === 1 ? '' : 's', "."] }))] })] })), showAdvanced ? (_jsxs("div", { className: "border-border space-y-3 border-t pt-4", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [_jsxs("div", { children: [_jsx("p", { className: "text-foreground text-base font-medium", children: "Profile document" }), _jsx("p", { className: "text-muted-foreground mt-1 text-sm", children: "Portable markdown with YAML rules and human guidance. Saving uses this document as the source of truth." })] }), _jsxs("p", { className: "text-muted-foreground text-sm", children: ["v", value.version, " \u00B7 ", value.status] })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: documentId, className: LABEL_CLASS, children: "brand-voice-profile.md" }), _jsx("textarea", { id: documentId, value: value.document, disabled: disabled, onChange: (e) => onChange({ document: e.target.value }), className: DOCUMENT_TEXTAREA_CLASS, spellCheck: false })] }), _jsx("div", { className: "flex flex-wrap gap-3", children: _jsx("button", { type: "button", onClick: applyDocumentToFields, disabled: disabled || !value.document.trim(), className: "border-border text-foreground hover:bg-accent rounded-md border px-3 py-2 text-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50", children: "Apply to quick-edit fields" }) })] })) : (_jsxs("div", { className: "border-border space-y-4 border-t pt-4", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: nameId, className: LABEL_CLASS, children: "Name" }), _jsx("input", { id: nameId, type: "text", value: value.name, disabled: disabled, placeholder: "e.g. Acme Marketing", onChange: (e) => onChange({ name: e.target.value }), className: INPUT_CLASS })] }), _jsxs("div", { children: [_jsx("label", { htmlFor: toneId, className: LABEL_CLASS, children: "Tone" }), _jsx("input", { id: toneId, type: "text", value: value.tone, disabled: disabled, maxLength: TONE_MAX, placeholder: "e.g. confident, warm, plain-spoken", onChange: (e) => onChange({ tone: e.target.value }), className: INPUT_CLASS })] }), _jsxs("div", { children: [_jsxs("label", { htmlFor: audienceId, className: LABEL_CLASS, children: ["Audience ", _jsx("span", { className: "text-muted-foreground font-normal", children: "(optional)" })] }), _jsx("input", { id: audienceId, type: "text", value: value.audience, disabled: disabled, placeholder: "e.g. busy IT directors at mid-market SaaS companies", onChange: (e) => onChange({ audience: e.target.value }), className: INPUT_CLASS })] }), _jsxs("div", { children: [_jsxs("label", { htmlFor: guidelinesId, className: LABEL_CLASS, children: ["Guidelines ", _jsx("span", { className: "text-muted-foreground font-normal", children: "(optional)" })] }), _jsx("textarea", { id: guidelinesId, value: value.guidelines, disabled: disabled, maxLength: GUIDELINES_MAX, placeholder: 'Do: lead with the benefit, use active voice.\nDon\u2019t: use jargon, exclamation points, or hype.', onChange: (e) => onChange({ guidelines: e.target.value }), className: TEXTAREA_CLASS }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: [value.guidelines.length, "/", GUIDELINES_MAX] })] }), _jsxs("div", { children: [_jsxs("label", { htmlFor: sampleId, className: LABEL_CLASS, children: ["Sample copy ", _jsx("span", { className: "text-muted-foreground font-normal", children: "(optional)" })] }), _jsx("textarea", { id: sampleId, value: value.sampleText, disabled: disabled, maxLength: SAMPLE_MAX, placeholder: "Paste a paragraph of on-brand copy the AI can pattern-match against.", onChange: (e) => onChange({ sampleText: e.target.value }), className: TEXTAREA_CLASS }), _jsxs("p", { className: "text-muted-foreground mt-1 text-sm", children: [value.sampleText.length, "/", SAMPLE_MAX] })] }), _jsx(BrandVoiceRulesSections, { structured: value.structured, disabled: disabled, onChange: handleStructuredChange }), onScore && _jsx(BrandVoiceAlignmentPanel, { disabled: disabled, onScore: onScore })] }))] }) }));
}
//# sourceMappingURL=BrandVoiceCard.js.map