import { router, useForm } from '@inertiajs/react';
import { Eye, Plus, Trash2 } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
import { Select } from '@/components/ui/input';
import { PageHeader } from '@/components/PageHeader';
import { SettingsNav } from '@/components/SettingsNav';
import { Button } from '@/components/ui/button';
import { Card, CardBody, CardHeader } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { EmailEditor } from '@/components/EmailEditor';
import { Field } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout';
import { cn } from '@/lib/utils';

type Template = { type: string; label: string; subject: string; body: string; customised: boolean; default_subject: string; default_body: string; custom: boolean; purpose: string | null };

/** Settings → Emails: the text of every email the app sends to clients, per company. */
type Rule = { label: string; unit: 'hours' | 'days' | 'views'; value: number; template: 'follow_up_1' | 'follow_up_2'; enabled: boolean; description: string };

export default function EmailSettings({ templates, placeholders, canEdit, companyName, followUps, purposes }: {
    templates: Template[]; placeholders: Record<string, string>; canEdit: boolean; companyName: string; followUps: Record<string, Rule>; purposes: Record<string, string>;
}) {
    const [active, setActive] = useState(templates[0]?.type);
    const t = templates.find((x) => x.type === active) ?? templates[0];
    // Select a newly added template once the list comes back with it.
    const known = useRef(new Set(templates.map((x) => x.type)));
    useEffect(() => {
        const added = templates.find((x) => !known.current.has(x.type));
        if (added) setActive(added.type);
        known.current = new Set(templates.map((x) => x.type));
    }, [templates]);
    const [adding, setAdding] = useState(false);
    const add = useForm({ name: '', purpose: 'new_quote' });
    const standard = templates.filter((x) => !x.custom);
    const custom = templates.filter((x) => x.custom);
    const item = (x: Template) => (
        <button key={x.type} type="button" onClick={() => setActive(x.type)} aria-current={x.type === active ? 'true' : undefined} data-testid={`template-${x.type}`}
            className={cn('flex items-center justify-between rounded-[5px] px-3 py-2 text-left text-sm', x.type === active ? 'bg-accent-fill text-accent-ink' : 'hover:bg-accent-soft')}>
            <span className="truncate">{x.label}</span>{!x.custom && x.customised && <span className="ml-2 text-[10px] uppercase tracking-wide opacity-75">Edited</span>}
        </button>
    );
    return (
        <AppLayout title="Email templates">
            <PageHeader title="Email templates" breadcrumbs={[{ label: 'Settings', href: '/settings/company' }, { label: 'Emails' }]}
                description={`What clients receive from ${companyName}. Placeholders like {client_first_name} are filled for each person.`} />
            <SettingsNav />
            <div className="grid gap-6 lg:grid-cols-[240px_minmax(0,1fr)]">
                <nav className="flex flex-row flex-wrap gap-1 lg:flex-col" aria-label="Email templates">
                    {standard.map(item)}
                    <div className="mt-3 w-full px-3 text-[11px] font-semibold uppercase tracking-wide text-ink-muted">Your templates</div>
                    {custom.length === 0 && <p className="px-3 text-xs text-ink-muted">None yet.</p>}
                    {custom.map(item)}
                    {canEdit && (adding ? (
                        <form className="mt-2 w-full space-y-2 rounded-md border border-line bg-surface p-3" data-testid="add-template-form"
                            onSubmit={(e) => { e.preventDefault(); add.post('/settings/emails', { preserveScroll: true, onSuccess: () => { add.reset(); setAdding(false); } }); }}>
                            <Field label="Name" htmlFor="new-tpl-name" error={add.errors.name}><Input id="new-tpl-name" value={add.data.name} onChange={(e) => add.setData('name', e.target.value)} placeholder="e.g. Website quote intro" autoFocus /></Field>
                            <Field label="Use as" htmlFor="new-tpl-purpose" hint="What sending it does (e.g. a follow-up counts as following up).">
                                <Select id="new-tpl-purpose" value={add.data.purpose} onChange={(e) => add.setData('purpose', e.target.value)}>
                                    {Object.entries(purposes).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
                                </Select>
                            </Field>
                            <div className="flex justify-end gap-2">
                                <Button type="button" size="sm" variant="ghost" onClick={() => setAdding(false)}>Cancel</Button>
                                <Button type="submit" size="sm" disabled={add.processing} data-testid="add-template-submit">Add</Button>
                            </div>
                        </form>
                    ) : (
                        <Button type="button" variant="secondary" size="sm" className="mt-2" onClick={() => setAdding(true)} data-testid="add-template"><Plus className="h-4 w-4" /> Add template</Button>
                    ))}
                </nav>
                {t && <Editor key={t.type} t={t} placeholders={placeholders} canEdit={canEdit} purposes={purposes} onDeleted={() => setActive(templates[0]?.type)} />}
            </div>
            <FollowUpRules rules={followUps} canEdit={canEdit} companyName={companyName} />
        </AppLayout>
    );
}

function Editor({ t, placeholders, canEdit, purposes, onDeleted }: { t: Template; placeholders: Record<string, string>; canEdit: boolean; purposes: Record<string, string>; onDeleted: () => void }) {
    const form = useForm({ subject: t.subject, body: t.body, reset: false, name: t.label, purpose: t.purpose ?? 'new_quote' });
    const remove = () => {
        if (!confirm(`Delete the "${t.label}" template?`)) return;
        router.delete(`/settings/emails/${t.type}`, { preserveScroll: true, onSuccess: onDeleted });
    };
    const save = () => { form.transform((d) => ({ ...d, reset: false })); form.put(`/settings/emails/${t.type}`, { preserveScroll: true }); };
    const reset = () => {
        if (!confirm('Reset this email to the default text?')) return;
        form.transform(() => ({ subject: t.default_subject, body: t.default_body, reset: true }));
        form.put(`/settings/emails/${t.type}`, { preserveScroll: true, onSuccess: () => form.setData({ subject: t.default_subject, body: t.default_body, reset: false }) });
    };
    return (
        <Card data-testid="email-template-editor">
            <CardHeader title={t.label} description="Format the text and add images with the toolbar. “Quote button” adds the quote card with its “View quote” button; placeholders are filled in for each client."
                actions={<a href={`/settings/emails/${t.type}/preview`} target="_blank" rel="noopener" className="inline-flex items-center gap-1.5 text-sm text-link underline" data-testid="preview-email"><Eye className="h-4 w-4" /> Preview</a>} />
            <CardBody className="space-y-4">
                <fieldset disabled={!canEdit} className="space-y-4">
                    {t.custom && (
                        <div className="grid gap-4 sm:grid-cols-2">
                            <Field label="Template name" htmlFor="tpl-name" error={(form.errors as Record<string, string>).name}><Input id="tpl-name" value={form.data.name} onChange={(e) => form.setData('name', e.target.value)} /></Field>
                            <Field label="Use as" htmlFor="tpl-purpose"><Select id="tpl-purpose" value={form.data.purpose} onChange={(e) => form.setData('purpose', e.target.value)}>
                                {Object.entries(purposes).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
                            </Select></Field>
                        </div>
                    )}
                    <Field label="Subject" htmlFor="tpl-subject" error={form.errors.subject}><Input id="tpl-subject" value={form.data.subject} onChange={(e) => form.setData('subject', e.target.value)} /></Field>
                    <Field label="Message" htmlFor="tpl-body" error={form.errors.body}>
                        <EmailEditor id="tpl-body" label="Message" value={form.data.body} onChange={(html) => form.setData('body', html)} placeholders={placeholders} disabled={!canEdit} minHeight="min-h-72" />
                    </Field>
                </fieldset>
                <div className="rounded-md bg-page p-3 text-xs">
                    <div className="mb-1 font-semibold">Placeholders</div>
                    <div className="grid gap-x-4 gap-y-0.5 sm:grid-cols-2">
                        {Object.entries(placeholders).map(([k, v]) => <div key={k}><code className="text-link">{k}</code> <span className="text-ink-muted">{v}</span></div>)}
                    </div>
                </div>
                {canEdit && (
                    <div className="flex justify-end gap-2">
                        {t.custom && <Button type="button" variant="ghost" onClick={remove} data-testid="delete-template"><Trash2 className="h-4 w-4" /> Delete</Button>}
                        {!t.custom && t.customised && <Button type="button" variant="ghost" onClick={reset}>Reset to default</Button>}
                        <Button type="button" onClick={save} disabled={form.processing || !form.isDirty} data-testid="save-email-template">Save</Button>
                    </div>
                )}
            </CardBody>
        </Card>
    );
}

const RULE_TEXT: Record<string, (v: React.ReactNode) => React.ReactNode> = {
    not_opened: (v) => <>Not opened {v} hours after sending</>,
    opened_not_accepted: (v) => <>Opened but not accepted {v} days after sending</>,
    not_accepted: (v) => <>Not accepted {v} days after sending</>,
    viewed_often: (v) => <>Viewed {v} or more times but not accepted</>,
};

/** Follow-up prompts: when the dashboard suggests a follow-up (never sent automatically). */
function FollowUpRules({ rules, canEdit, companyName }: { rules: Record<string, Rule>; canEdit: boolean; companyName: string }) {
    const form = useForm<{ rules: Record<string, { enabled: boolean; value: number; template: string }> }>({ rules: Object.fromEntries(Object.entries(rules).map(([k, r]) => [k, { enabled: r.enabled, value: r.value, template: r.template as string }])) });
    const set = (k: string, patch: Partial<{ enabled: boolean; value: number; template: string }>) =>
        form.setData('rules', { ...form.data.rules, [k]: { ...form.data.rules[k], ...patch } });
    return (
        <Card className="mt-6" id="follow-ups" data-testid="follow-up-rules">
            <CardHeader title="Follow-up prompts" description={`When the dashboard suggests following up a ${companyName} quote. Each prompt appears once per quote and stops when the client asks a question, accepts or declines. Nothing is emailed automatically.`} />
            <CardBody>
                <form onSubmit={(e) => { e.preventDefault(); form.put('/settings/follow-ups', { preserveScroll: true }); }} className="space-y-3">
                    {Object.entries(rules).map(([k, r]) => {
                        const v = form.data.rules[k];
                        return (
                            <div key={k} className="flex flex-wrap items-center gap-3 rounded-md border border-line px-3 py-2.5 text-sm">
                                <label className="inline-flex min-w-0 flex-1 cursor-pointer items-center gap-2">
                                    <input type="checkbox" className="h-4 w-4" checked={v.enabled} disabled={!canEdit} onChange={(e) => set(k, { enabled: e.target.checked })} aria-label={`${r.label} enabled`} />
                                    <span>{RULE_TEXT[k]?.(
                                        <Input type="number" min={1} aria-label={`${r.label} ${r.unit}`} className="mx-1 inline-block h-8 w-20" value={v.value} disabled={!canEdit}
                                            onChange={(e) => set(k, { value: Number(e.target.value) || 1 })} />,
                                    ) ?? r.description}</span>
                                </label>
                                <select aria-label={`${r.label} email`} className="h-8 rounded-md border border-line bg-surface px-2 text-sm" value={v.template} disabled={!canEdit} onChange={(e) => set(k, { template: e.target.value })}>
                                    <option value="follow_up_1">Suggest Follow-up 1</option>
                                    <option value="follow_up_2">Suggest Follow-up 2</option>
                                </select>
                            </div>
                        );
                    })}
                    {Object.keys(form.errors).length > 0 && <p role="alert" className="text-sm text-danger">{Object.values(form.errors)[0]}</p>}
                    {canEdit && <div className="flex justify-end"><Button type="submit" disabled={form.processing || !form.isDirty} data-testid="save-follow-ups">Save follow-up rules</Button></div>}
                </form>
            </CardBody>
        </Card>
    );
}
