<?php
// ============================================================
//  admin/email-compose.php — TinyMCE rich compose
// ============================================================
//
//  Features:
//   - TinyMCE rich text editor (loaded from Cloud CDN)
//   - Per-user signature auto-appended (editable in-place)
//   - File attachments (up to 25MB each) via fetch upload
//   - Recipient pills with member autocomplete
//   - Reply / Reply-all / Forward modes
//
//  Send path:
//   1. Sanitise body HTML (strip dangerous tags)
//   2. SMTP send
//   3. IMAP APPEND to Sent folder
//   4. Mark original as answered (if reply)
//   5. Clean up temp attachments
// ============================================================

require_once __DIR__ . '/../includes/auth.php';
require_once __DIR__ . '/../includes/csrf.php';
require_once __DIR__ . '/../includes/config.php';
require_once __DIR__ . '/../includes/imap_client.php';
require_once __DIR__ . '/../includes/email_sync.php';
require_once __DIR__ . '/../includes/email_sanitize.php';
require_once __DIR__ . '/../includes/email_contacts.php';
auth_require_admin();

$me = auth_admin_user();

$mode = $_GET['mode'] ?? $_POST['mode'] ?? 'new';
if (!in_array($mode, ['new','reply','reply_all','forward'], true)) $mode = 'new';

$source_msg_id = (int)($_GET['id'] ?? $_POST['source_msg_id'] ?? 0);
$account_id    = (int)($_GET['account'] ?? $_POST['account_id'] ?? 0);

// Load source message if any
$source = null;
if ($source_msg_id) {
    $source = db_row(
        "SELECT m.*, a.email_address AS account_email,
                a.imap_host, a.imap_port, a.imap_encryption,
                a.imap_username, a.imap_password
           FROM email_messages m
           JOIN email_account_users u ON u.account_id = m.account_id
           JOIN email_accounts a      ON a.id        = m.account_id
          WHERE m.id=:id AND u.user_id=:uid",
        ['id' => $source_msg_id, 'uid' => $me['id']]
    );
    if (!$source) { http_response_code(404); exit('Source message not found.'); }
    if (!$account_id) $account_id = (int)$source['account_id'];

    if ($source['body_text'] === null && $source['body_html'] === null) {
        try {
            $parts = email_fetch_body_on_demand([
                'imap_host'       => $source['imap_host'],
                'imap_port'       => $source['imap_port'],
                'imap_encryption' => $source['imap_encryption'],
                'imap_username'   => $source['imap_username'],
                'imap_password'   => $source['imap_password'],
            ], $source['folder'], (int)$source['uid']);
            $source['body_text'] = $parts['text'] ?: null;
            $source['body_html'] = $parts['html'] ?: null;
        } catch (Throwable $_) { /* best-effort */ }
    }
}

// Determine sending account
$sending_acct = null;
if ($account_id) {
    $sending_acct = db_row(
        "SELECT a.* FROM email_accounts a
           JOIN email_account_users u ON u.account_id = a.id
          WHERE a.id=:id AND u.user_id=:uid AND u.can_send = 1 AND a.is_active = 1",
        ['id' => $account_id, 'uid' => $me['id']]
    );
}
if (!$sending_acct) {
    $sending_acct = db_row(
        "SELECT a.* FROM email_accounts a
           JOIN email_account_users u ON u.account_id = a.id
          WHERE u.user_id=:uid AND u.can_send = 1 AND a.is_active = 1
       ORDER BY a.display_name LIMIT 1",
        ['uid' => $me['id']]
    );
}
if (!$sending_acct) {
    http_response_code(403);
    exit('You don\'t have permission to send from any mailbox.');
}

$my_accounts = db_all(
    "SELECT a.id, a.display_name, a.email_address, a.colour
       FROM email_accounts a
       JOIN email_account_users u ON u.account_id = a.id
      WHERE u.user_id=:uid AND u.can_send=1 AND a.is_active=1
   ORDER BY a.display_name",
    ['uid' => $me['id']]
);

// User's signature (already sanitised on save)
$signature_html = (string)($me['email_signature'] ?? '');

// ── POST: send ──────────────────────────────────────────────
$flash_error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'send') {
    csrf_verify();

    $to_raw   = trim((string)($_POST['to']   ?? ''));
    $cc_raw   = trim((string)($_POST['cc']   ?? ''));
    $bcc_raw  = trim((string)($_POST['bcc']  ?? ''));
    $subject  = trim((string)($_POST['subject'] ?? ''));
    $body_html_raw = (string)($_POST['body_html'] ?? '');
    $in_reply_to = (string)($_POST['in_reply_to'] ?? '');
    $references  = (string)($_POST['references']  ?? '');
    $from_acct_id = (int)($_POST['from_account_id'] ?? $sending_acct['id']);
    $attachment_tokens = array_filter(explode(',', (string)($_POST['attachment_tokens'] ?? '')));

    $send_acct = db_row(
        "SELECT a.* FROM email_accounts a
           JOIN email_account_users u ON u.account_id = a.id
          WHERE a.id=:id AND u.user_id=:uid AND u.can_send=1 AND a.is_active=1",
        ['id' => $from_acct_id, 'uid' => $me['id']]
    );
    if (!$send_acct) {
        $flash_error = 'You can\'t send from that account.';
    } elseif ($to_raw === '') {
        $flash_error = 'At least one recipient is required.';
    } elseif ($subject === '' && trim(strip_tags($body_html_raw)) === '') {
        $flash_error = 'Empty message — add a subject or body.';
    } else {
        $to  = imc_normalize_addr_list($to_raw);
        $cc  = imc_normalize_addr_list($cc_raw);
        $bcc = imc_normalize_addr_list($bcc_raw);

        if (empty($to)) {
            $flash_error = 'Invalid recipient address.';
        } else {
            // Sanitise outgoing HTML (Word paste cleanup, security)
            $sanitised = email_sanitize_html($body_html_raw, true);
            $body_html = $sanitised['html'];

            // Convert URL-referenced images on our server into inline cid: parts
            // — Outlook/corporate clients block remote images by default, so
            // we embed them directly into the email.
            $inlined   = imc_inline_referenced_images($body_html);
            $body_html = $inlined['html'];
            $inline_attachments = $inlined['inline_attachments'];

            // Generate a plain-text alternative from the HTML for clients
            // that prefer it (and for spam filters that look for both)
            $body_text = trim(html_entity_decode(
                preg_replace(['#<br\s*/?>#i', '#</p>#i'], "\n", strip_tags($body_html)),
                ENT_QUOTES | ENT_HTML5,
                'UTF-8'
            ));

            // Load attachment data (user-uploaded files)
            $attachments = [];
            foreach ($attachment_tokens as $token) {
                $token = trim($token);
                if ($token === '') continue;
                $att = imc_load_temp_attachment((int)$me['id'], $token);
                if ($att) $attachments[] = $att;
            }

            // Combine: inline images first, then regular attachments
            $all_attachments = array_merge($inline_attachments, $attachments);

            $msg_payload = [
                'to' => $to, 'cc' => $cc, 'bcc' => $bcc,
                'subject'     => $subject ?: '(no subject)',
                'body_text'   => $body_text,
                'body_html'   => $body_html,
                'attachments' => $all_attachments,
                'in_reply_to' => $in_reply_to !== '' ? $in_reply_to : null,
                'references'  => $references !== ''  ? $references  : null,
            ];

            try {
                $message_id = imc_smtp_send($send_acct, $msg_payload);

                $sent_folder = $send_acct['imap_sent_folder'] ?: 'Sent';
                $raw = imc_build_raw_message($send_acct, $msg_payload, $message_id);
                try {
                    imc_append_to_folder($send_acct, $sent_folder, $raw);
                } catch (Throwable $e) {
                    app_log("email: SMTP send OK but IMAP append failed: " . $e->getMessage());
                }

                if ($source && in_array($mode, ['reply','reply_all'], true)) {
                    db_exec('UPDATE email_messages SET is_answered=1 WHERE id=:id', ['id' => $source['id']]);
                    try {
                        $conn = imc_open([
                            'imap_host'       => $source['imap_host'],
                            'imap_port'       => $source['imap_port'],
                            'imap_encryption' => $source['imap_encryption'],
                            'imap_username'   => $source['imap_username'],
                            'imap_password'   => $source['imap_password'],
                        ], $source['folder']);
                        @imap_setflag_full($conn, (string)$source['uid'], '\\Answered', ST_UID);
                        imc_close($conn);
                    } catch (Throwable $_e) { /* best-effort */ }
                }

                // Clean up temp attachment files
                imc_cleanup_temp_attachments((int)$me['id'], $attachment_tokens);

                header('Location: email.php?account=' . (int)$send_acct['id']
                    . '&msg=' . urlencode('Message sent.'));
                exit;
            } catch (Throwable $e) {
                $flash_error = 'Send failed: ' . $e->getMessage();
                app_log('email send failed: ' . $e->getMessage());
            }
        }
    }
}

// Build initial values based on mode
$initial_to_emails = [];
$initial_cc_emails = [];
$initial_subject = '';
$initial_quote_html = '';
$initial_in_reply_to = '';
$initial_references = '';

if ($source) {
    $orig_to_list = $source['to_list'] ?: '';
    $orig_cc_list = $source['cc_list'] ?: '';

    $initial_in_reply_to = $source['message_id'] ?? '';
    $initial_references  = trim(($source['references'] ?? '') . ' ' . ($source['message_id'] ?? ''));

    // Build a quote block as HTML
    $orig_body_html = '';
    if ($source['body_html']) {
        // Sanitise the original for safe embedding in the quote
        $orig_body_html = email_sanitize_html($source['body_html'], true)['html'];
    } elseif ($source['body_text']) {
        $orig_body_html = nl2br(htmlspecialchars((string)$source['body_text']));
    }

    $sent_at_fmt = date('j M Y H:i', strtotime($source['sent_at'] ?? 'now'));
    $from_disp   = htmlspecialchars(($source['from_name'] ?: $source['from_email']));

    if ($mode === 'reply' || $mode === 'reply_all') {
        $initial_to_emails = [$source['from_email']];
        if ($mode === 'reply_all') {
            $cc_parts = [];
            foreach (explode(',', $orig_to_list . ',' . $orig_cc_list) as $piece) {
                $piece = trim($piece);
                if ($piece === '') continue;
                if (preg_match('/<([^>]+)>/', $piece, $m)) $piece = $m[1];
                if (strcasecmp($piece, $source['account_email']) === 0) continue;
                if (filter_var($piece, FILTER_VALIDATE_EMAIL)) $cc_parts[] = $piece;
            }
            $initial_cc_emails = array_values(array_unique($cc_parts));
        }
        $initial_subject = (stripos($source['subject'] ?? '', 'Re:') === 0)
            ? $source['subject']
            : 'Re: ' . ($source['subject'] ?: '');

        $initial_quote_html = '<br><br><div style="border-left:3px solid #cbd5e1;padding-left:12px;color:#475569;margin-top:12px;">'
            . '<p style="margin:0 0 8px;font-size:0.9em;color:#64748b;">On ' . $sent_at_fmt . ', ' . $from_disp . ' wrote:</p>'
            . $orig_body_html
            . '</div>';

    } elseif ($mode === 'forward') {
        $initial_subject = (stripos($source['subject'] ?? '', 'Fwd:') === 0)
            ? $source['subject']
            : 'Fwd: ' . ($source['subject'] ?: '');

        $initial_quote_html = '<br><br><div style="border:1px solid #e5e7eb;border-radius:6px;padding:12px;margin-top:12px;">'
            . '<p style="margin:0 0 8px;font-size:0.85em;color:#64748b;"><strong>Forwarded message</strong></p>'
            . '<p style="margin:0;font-size:0.85em;color:#64748b;">'
            . '<strong>From:</strong> ' . $from_disp . '<br>'
            . '<strong>Date:</strong> ' . $sent_at_fmt . '<br>'
            . '<strong>Subject:</strong> ' . htmlspecialchars($source['subject'] ?: '(no subject)') . '<br>'
            . '<strong>To:</strong> ' . htmlspecialchars($source['to_list'] ?: '') . '</p>'
            . '<hr style="border:none;border-top:1px solid #e5e7eb;margin:12px 0;">'
            . $orig_body_html
            . '</div>';
    }
}

// Resolve initial pills
$initial_to_resolved = [];
foreach ($initial_to_emails as $e) $initial_to_resolved[] = email_resolve_contact($e);
$initial_cc_resolved = [];
foreach ($initial_cc_emails as $e) $initial_cc_resolved[] = email_resolve_contact($e);

// Build the initial editor content
// Order: [user typing area] + signature + [quoted original]
$initial_editor_html = '<p><br></p>';   // placeholder for cursor

if ($signature_html !== '') {
    $initial_editor_html .= '<div data-buylocal-signature="1">' . $signature_html . '</div>';
}

if ($initial_quote_html !== '') {
    $initial_editor_html .= $initial_quote_html;
}

// Carry over POST values on error
if ($flash_error && isset($_POST['body_html'])) {
    $initial_editor_html = (string)$_POST['body_html'];
    $to_post = trim((string)($_POST['to'] ?? ''));
    $cc_post = trim((string)($_POST['cc'] ?? ''));
    $initial_to_resolved = $to_post !== ''
        ? array_map('email_resolve_contact', array_filter(array_map('trim', explode(',', $to_post))))
        : $initial_to_resolved;
    $initial_cc_resolved = $cc_post !== ''
        ? array_map('email_resolve_contact', array_filter(array_map('trim', explode(',', $cc_post))))
        : $initial_cc_resolved;
    $initial_subject = $_POST['subject'] ?? $initial_subject;
}

$mode_label = ['new'=>'New message','reply'=>'Reply','reply_all'=>'Reply all','forward'=>'Forward'][$mode] ?? 'Compose';
$page_title = $mode_label;
require __DIR__ . '/_guard.php';
?>

<style>
.cx-wrap{max-width:900px;margin:0 auto;}
.cx-back{display:inline-flex;align-items:center;gap:.35rem;color:var(--ink-muted);text-decoration:none;font-size:.86rem;margin-bottom:.75rem;}
.cx-back:hover{color:var(--ink);}

.cx-card{background:#fff;border:1px solid var(--line);border-radius:10px;overflow:hidden;}
.cx-head{padding:1rem 1.5rem;border-bottom:1px solid var(--line);background:var(--surface-alt);
    display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:.5rem;}
.cx-head h1{margin:0;font-size:1.15rem;}
.cx-head a{font-size:.78rem;color:var(--ink-muted);text-decoration:underline dotted;}
.cx-head a:hover{color:var(--ink);}

.cx-field{padding:.85rem 1.5rem;border-bottom:1px solid var(--line);}
.cx-field-label{
    font-size:.7rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
    color:var(--ink-muted);margin-bottom:.35rem;display:flex;justify-content:space-between;align-items:center;
}
.cx-field-label .right{font-weight:normal;letter-spacing:0;text-transform:none;font-size:.78rem;}
.cx-field-label button{color:var(--ink-muted);text-decoration:underline dotted;cursor:pointer;background:none;border:none;font-family:inherit;font-size:inherit;padding:0;}
.cx-field-label button:hover{color:var(--ink);}

.cx-input-bare{width:100%;border:none;font-size:.94rem;font-family:inherit;padding:.35rem 0;background:transparent;}
.cx-input-bare:focus{outline:none;}
.cx-input-bare.big{font-size:1.05rem;font-weight:600;}

.cx-from-display{display:flex;align-items:center;gap:.5rem;padding:.35rem 0;font-size:.94rem;}
.cx-from-display .dot{width:10px;height:10px;border-radius:50%;flex-shrink:0;}

.cx-select-bare{border:none;background:transparent;font-size:.94rem;font-family:inherit;padding:.35rem 0;width:100%;cursor:pointer;}
.cx-select-bare:focus{outline:none;}

/* Recipient pills */
.cx-pills{display:flex;flex-wrap:wrap;gap:.35rem;align-items:center;min-height:34px;position:relative;}
.cx-pill{display:inline-flex;align-items:center;gap:.4rem;padding:.25rem .5rem .25rem .65rem;background:#e0e7ff;color:#3730a3;border:1px solid #c7d2fe;border-radius:999px;font-size:.82rem;max-width:100%;}
.cx-pill .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:240px;}
.cx-pill.is-unknown{background:#fff7ed;color:#9a3412;border-color:#fed7aa;}
.cx-pill.match-domain{background:#fef3c7;color:#92400e;border-color:#fde68a;}
.cx-pill .rm{background:none;border:none;color:inherit;cursor:pointer;font-size:1.05rem;line-height:1;padding:0 .15rem;border-radius:50%;font-family:inherit;}
.cx-pill .rm:hover{background:rgba(0,0,0,.1);}
.cx-pill-input{border:none;outline:none;font-family:inherit;font-size:.92rem;padding:.3rem .25rem;background:transparent;flex:1;min-width:120px;}

.cx-ac{position:absolute;top:100%;left:0;right:0;z-index:50;background:#fff;border:1px solid var(--line);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.08);margin-top:.25rem;max-height:300px;overflow-y:auto;display:none;}
.cx-ac.on{display:block;}
.cx-ac-item{padding:.55rem .75rem;border-bottom:1px solid var(--line);cursor:pointer;display:flex;align-items:center;gap:.65rem;}
.cx-ac-item:last-child{border-bottom:none;}
.cx-ac-item:hover, .cx-ac-item.active{background:#f3f4f6;}
.cx-ac-icon{width:28px;height:28px;border-radius:50%;background:#dbeafe;color:#1e40af;display:flex;align-items:center;justify-content:center;font-size:.7rem;font-weight:700;flex-shrink:0;}
.cx-ac-text{flex:1;min-width:0;}
.cx-ac-name{font-size:.88rem;color:var(--ink);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.cx-ac-email{font-size:.78rem;color:var(--ink-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.cx-ac-match{font-size:.68rem;background:#e5e7eb;color:#374151;padding:.1em .4em;border-radius:3px;flex-shrink:0;}

.cx-cc-row, .cx-bcc-row{display:none;}
.cx-cc-row.on, .cx-bcc-row.on{display:block;}

/* Quill editor container */
.cx-editor-wrap{padding:0;border-bottom:1px solid var(--line);}
.cx-editor-wrap .ql-toolbar{
    border:none !important;
    border-bottom:1px solid var(--line) !important;
    background:var(--surface-alt);
    padding:.55rem 1rem !important;
}
.cx-editor-wrap .ql-container{
    border:none !important;
    font-family:inherit;
    font-size:.94rem;
}
.cx-editor-wrap .ql-editor{
    min-height:340px;
    padding:1rem 1.5rem;
    line-height:1.55;
}
.cx-editor-wrap .ql-editor.ql-blank::before{
    left:1.5rem;color:var(--ink-muted);font-style:normal;
}
/* The signature area gets a subtle visual separation */
.cx-editor-wrap .ql-editor div[data-buylocal-signature="1"]{
    color:#475569;
}

/* Attachments */
.cx-attach{padding:.85rem 1.5rem;border-bottom:1px solid var(--line);}
.cx-attach-list{display:flex;flex-wrap:wrap;gap:.4rem;margin-bottom:.5rem;}
.cx-attach-item{display:inline-flex;align-items:center;gap:.4rem;background:var(--surface-alt);border:1px solid var(--line);border-radius:5px;padding:.35rem .6rem;font-size:.82rem;}
.cx-attach-item.uploading{opacity:.5;}
.cx-attach-item .rm{background:none;border:none;color:#991b1b;cursor:pointer;font-size:1rem;line-height:1;padding:0 .15rem;font-family:inherit;}
.cx-attach-add{
    background:#fff;border:1px dashed var(--line);border-radius:5px;
    padding:.35rem .85rem;font-size:.82rem;cursor:pointer;
    color:var(--ink-muted);font-family:inherit;
}
.cx-attach-add:hover{border-color:var(--brand-primary);color:var(--brand-primary);}
.cx-attach-err{color:#991b1b;font-size:.78rem;margin-top:.25rem;}

.cx-foot{padding:.95rem 1.5rem;border-top:1px solid var(--line);background:var(--surface-alt);display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:.75rem;}
.cx-foot .left{display:flex;gap:.5rem;align-items:center;}
.cx-foot .hint{font-size:.75rem;color:var(--ink-muted);}

.flash{padding:.7rem 1rem;border-radius:6px;margin-bottom:1rem;font-size:.88rem;background:#fef2f2;color:#991b1b;border:1px solid #fca5a5;}
</style>

<section class="section"><div class="container cx-wrap">

<?php
$back_href = $source ? 'email-message.php?id=' . (int)$source['id']
                     : 'email.php?account=' . (int)$sending_acct['id'];
?>
<a href="<?= htmlspecialchars($back_href) ?>" class="cx-back">← Cancel</a>

<?php if ($flash_error): ?>
    <div class="flash"><?= htmlspecialchars($flash_error) ?></div>
<?php endif; ?>

<div class="cx-card">
    <div class="cx-head">
        <h1><?= htmlspecialchars($mode_label) ?></h1>
        <a href="email-signature.php">✎ Edit signature</a>
    </div>

    <form method="post" id="cx-form" enctype="multipart/form-data">
        <?= csrf_field() ?>
        <input type="hidden" name="action" value="send">
        <input type="hidden" name="mode" value="<?= htmlspecialchars($mode) ?>">
        <input type="hidden" name="source_msg_id" value="<?= $source_msg_id ?>">
        <input type="hidden" name="in_reply_to" value="<?= htmlspecialchars($initial_in_reply_to) ?>">
        <input type="hidden" name="references" value="<?= htmlspecialchars($initial_references) ?>">
        <input type="hidden" name="attachment_tokens" id="cx-attach-tokens" value="">
        <input type="hidden" name="body_html" id="cx-body-html" value="">

        <!-- FROM -->
        <div class="cx-field">
            <div class="cx-field-label">From</div>
            <?php if (count($my_accounts) === 1): ?>
                <div class="cx-from-display">
                    <span class="dot" style="background:<?= htmlspecialchars($sending_acct['colour']) ?>;"></span>
                    <strong><?= htmlspecialchars($sending_acct['display_name']) ?></strong>
                    <span style="color:var(--ink-muted);">&lt;<?= htmlspecialchars($sending_acct['email_address']) ?>&gt;</span>
                </div>
                <input type="hidden" name="from_account_id" value="<?= (int)$sending_acct['id'] ?>">
            <?php else: ?>
                <select name="from_account_id" class="cx-select-bare">
                    <?php foreach ($my_accounts as $a): ?>
                        <option value="<?= (int)$a['id'] ?>" <?= (int)$a['id'] === (int)$sending_acct['id'] ? 'selected' : '' ?>>
                            <?= htmlspecialchars($a['display_name']) ?> &lt;<?= htmlspecialchars($a['email_address']) ?>&gt;
                        </option>
                    <?php endforeach; ?>
                </select>
            <?php endif; ?>
        </div>

        <!-- TO -->
        <div class="cx-field">
            <div class="cx-field-label">
                <span>To</span>
                <span class="right">
                    <button type="button" data-target=".cx-cc-row">Add Cc</button>
                    &nbsp;·&nbsp;
                    <button type="button" data-target=".cx-bcc-row">Add Bcc</button>
                </span>
            </div>
            <div class="cx-pills" data-field="to">
                <input type="text" class="cx-pill-input" placeholder="Type a name, business or email…">
                <div class="cx-ac"></div>
            </div>
            <input type="hidden" name="to" id="cx-to-hidden" value="">
        </div>

        <!-- CC -->
        <div class="cx-field cx-cc-row <?= !empty($initial_cc_resolved) ? 'on' : '' ?>">
            <div class="cx-field-label">Cc</div>
            <div class="cx-pills" data-field="cc">
                <input type="text" class="cx-pill-input" placeholder="Type a name, business or email…">
                <div class="cx-ac"></div>
            </div>
            <input type="hidden" name="cc" id="cx-cc-hidden" value="">
        </div>

        <!-- BCC -->
        <div class="cx-field cx-bcc-row">
            <div class="cx-field-label">Bcc</div>
            <div class="cx-pills" data-field="bcc">
                <input type="text" class="cx-pill-input" placeholder="Hidden recipients…">
                <div class="cx-ac"></div>
            </div>
            <input type="hidden" name="bcc" id="cx-bcc-hidden" value="">
        </div>

        <!-- SUBJECT -->
        <div class="cx-field">
            <div class="cx-field-label">Subject</div>
            <input type="text" name="subject" class="cx-input-bare big" autocomplete="off"
                   value="<?= htmlspecialchars($initial_subject) ?>"
                   placeholder="What's this about?">
        </div>

        <!-- BODY: Quill rich editor -->
        <div class="cx-editor-wrap">
            <div id="cx-editor"><?= $initial_editor_html /* NOTE: already-trusted sanitised HTML; do NOT htmlspecialchars */ ?></div>
        </div>

        <!-- ATTACHMENTS -->
        <div class="cx-attach">
            <div class="cx-field-label">Attachments</div>
            <div class="cx-attach-list" id="cx-attach-list"></div>
            <button type="button" class="cx-attach-add" onclick="document.getElementById('cx-attach-input').click();">
                📎 Add file
            </button>
            <input type="file" id="cx-attach-input" multiple style="display:none;">
            <div class="cx-attach-err" id="cx-attach-err" style="display:none;"></div>
            <p style="font-size:.72rem;color:var(--ink-muted);margin:.4rem 0 0;">Max 25 MB per file.</p>
        </div>

        <div class="cx-foot">
            <div class="left">
                <button type="submit" class="btn" id="cx-send-btn">Send</button>
                <a href="<?= htmlspecialchars($back_href) ?>" class="btn btn-outline">Cancel</a>
            </div>
            <span class="hint">Signature auto-included · Inline images upload to server</span>
        </div>
    </form>
</div>

</div></section>

<!-- Quill rich text editor -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.snow.css">
<script src="https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.min.js"></script>
<script>
// Custom image handler: upload to server, insert URL
function quillImageHandler() {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/jpeg,image/png,image/gif,image/webp';
    input.onchange = async () => {
        const file = input.files && input.files[0];
        if (!file) return;
        if (file.size > 10 * 1024 * 1024) {
            alert('Image too large — 10 MB maximum.');
            return;
        }

        const fd = new FormData();
        fd.append('file', file);

        try {
            const resp = await fetch('email-upload-image.php', {
                method: 'POST',
                body: fd,
                credentials: 'same-origin',
            });
            const data = await resp.json();
            if (!resp.ok || !data.location) {
                alert((data.error && data.error.message) || 'Image upload failed.');
                return;
            }
            const range = window.cxQuill.getSelection(true);
            window.cxQuill.insertEmbed(range.index, 'image', data.location, 'user');
            window.cxQuill.setSelection(range.index + 1);
        } catch (err) {
            alert('Image upload error: ' + err.message);
        }
    };
    input.click();
}

// Initialise Quill with a Word-like toolbar
window.cxQuill = new Quill('#cx-editor', {
    theme: 'snow',
    placeholder: 'Write your message…',
    modules: {
        toolbar: {
            container: [
                [{ header: [false, 1, 2, 3] }],
                ['bold', 'italic', 'underline', 'strike'],
                [{ color: [] }, { background: [] }],
                [{ list: 'ordered' }, { list: 'bullet' }],
                [{ align: [] }],
                ['blockquote', 'link', 'image'],
                ['clean']
            ],
            handlers: { image: quillImageHandler }
        }
    }
});

(function () {
    // ── Recipient pills + autocomplete (unchanged logic from previous version)
    const initial = {
        to: <?= json_encode($initial_to_resolved, JSON_UNESCAPED_UNICODE) ?>,
        cc: <?= json_encode($initial_cc_resolved, JSON_UNESCAPED_UNICODE) ?>,
        bcc: []
    };

    document.querySelectorAll('.cx-pills').forEach(container => {
        const field = container.dataset.field;
        setupPillField(container, field, initial[field] || []);
    });

    document.querySelectorAll('.cx-field-label button[data-target]').forEach(btn => {
        btn.addEventListener('click', () => {
            const target = document.querySelector(btn.dataset.target);
            if (target) {
                target.classList.toggle('on');
                if (target.classList.contains('on')) {
                    const input = target.querySelector('.cx-pill-input');
                    if (input) input.focus();
                }
            }
        });
    });

    // ── Attachments
    const attachInput = document.getElementById('cx-attach-input');
    const attachList  = document.getElementById('cx-attach-list');
    const attachErr   = document.getElementById('cx-attach-err');
    const attachTokensField = document.getElementById('cx-attach-tokens');
    const uploadedTokens = [];

    attachInput.addEventListener('change', async (e) => {
        attachErr.style.display = 'none';
        attachErr.textContent = '';
        const files = Array.from(e.target.files || []);
        e.target.value = '';
        for (const file of files) {
            await uploadAttachment(file);
        }
    });

    async function uploadAttachment(file) {
        if (file.size > 25 * 1024 * 1024) {
            showAttachError(`${file.name} is larger than 25 MB.`);
            return;
        }

        // Placeholder while uploading
        const placeholder = document.createElement('div');
        placeholder.className = 'cx-attach-item uploading';
        placeholder.innerHTML = `<span>📎 ${escapeHtml(file.name)} <em>uploading…</em></span>`;
        attachList.appendChild(placeholder);

        const fd = new FormData();
        fd.append('file', file);

        try {
            const resp = await fetch('email-upload-attachment.php', {
                method: 'POST',
                body: fd,
                credentials: 'same-origin',
            });
            const data = await resp.json();
            placeholder.remove();
            if (!resp.ok || data.error) {
                showAttachError(data.error || `Upload failed (${resp.status})`);
                return;
            }
            uploadedTokens.push(data.token);
            updateTokensField();
            addAttachItem(data);
        } catch (err) {
            placeholder.remove();
            showAttachError('Network error: ' + err.message);
        }
    }

    function addAttachItem(data) {
        const item = document.createElement('div');
        item.className = 'cx-attach-item';
        item.dataset.token = data.token;
        const sizeKB = (data.size / 1024).toFixed(0);
        item.innerHTML = `<span>📎 ${escapeHtml(data.name)}</span><span style="color:var(--ink-muted);font-size:.72rem;">${sizeKB} KB</span>`;
        const rm = document.createElement('button');
        rm.type = 'button';
        rm.className = 'rm';
        rm.textContent = '×';
        rm.title = 'Remove';
        rm.addEventListener('click', () => {
            const i = uploadedTokens.indexOf(data.token);
            if (i >= 0) uploadedTokens.splice(i, 1);
            updateTokensField();
            item.remove();
        });
        item.appendChild(rm);
        attachList.appendChild(item);
    }

    function updateTokensField() {
        attachTokensField.value = uploadedTokens.join(',');
    }

    function showAttachError(msg) {
        attachErr.textContent = msg;
        attachErr.style.display = 'block';
    }

    function escapeHtml(s) {
        return (s||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
    }

    // ── Form submit: serialise pills + grab editor HTML
    document.getElementById('cx-form').addEventListener('submit', (e) => {
        ['to','cc','bcc'].forEach(field => {
            const container = document.querySelector(`.cx-pills[data-field="${field}"]`);
            const hidden = document.getElementById(`cx-${field}-hidden`);
            if (!container || !hidden) return;
            const pills = Array.from(container.querySelectorAll('.cx-pill')).map(p => p.dataset.email).filter(Boolean);
            const input = container.querySelector('.cx-pill-input');
            if (input && input.value.trim()) {
                const v = input.value.trim();
                if (v && !pills.includes(v.toLowerCase())) pills.push(v);
            }
            hidden.value = pills.join(', ');
        });

        // Grab editor HTML from Quill
        if (window.cxQuill) {
            document.getElementById('cx-body-html').value = window.cxQuill.root.innerHTML;
        }
    });

    // ── Pill field setup (autocomplete dropdown + keyboard)
    function setupPillField(container, field, initialPills) {
        const input = container.querySelector('.cx-pill-input');
        const drop  = container.querySelector('.cx-ac');
        let currentResults = [];
        let activeIndex = -1;
        let debounce = null;

        initialPills.forEach(p => addPill(p));

        function addPill(data) {
            if (!data || !data.email) return;
            const email = data.email.toLowerCase();
            if (container.querySelector(`.cx-pill[data-email="${cssEscape(email)}"]`)) return;
            const pill = document.createElement('span');
            pill.className = 'cx-pill';
            pill.dataset.email = email;
            if (data.match === 'none')   pill.classList.add('is-unknown');
            if (data.match === 'domain') pill.classList.add('match-domain');
            const label = data.label || data.email;
            pill.title = (label !== data.email ? label + ' — ' : '') + data.email;
            const nm = document.createElement('span');
            nm.className = 'nm';
            nm.textContent = label;
            pill.appendChild(nm);
            const rm = document.createElement('button');
            rm.type = 'button';
            rm.className = 'rm';
            rm.textContent = '×';
            rm.addEventListener('click', () => pill.remove());
            pill.appendChild(rm);
            container.insertBefore(pill, input);
        }

        function commitInputAsEmail() {
            const v = input.value.trim().replace(/[,;]$/, '').trim();
            if (!v) return;
            if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) return;
            input.value = '';
            fetch('email-resolve-contacts.php?emails=' + encodeURIComponent(v))
                .then(r => r.json())
                .then(arr => addPill((arr && arr[0]) || { email: v, label: v, match: 'none' }))
                .catch(() => addPill({ email: v, label: v, match: 'none' }));
            hideDropdown();
        }

        function search(q) {
            if (q.length < 2) { hideDropdown(); return; }
            fetch('email-search-contacts.php?q=' + encodeURIComponent(q))
                .then(r => r.json())
                .then(arr => {
                    currentResults = Array.isArray(arr) ? arr : [];
                    activeIndex = currentResults.length ? 0 : -1;
                    renderDropdown();
                })
                .catch(() => hideDropdown());
        }

        function renderDropdown() {
            if (currentResults.length === 0) { hideDropdown(); return; }
            drop.innerHTML = '';
            currentResults.forEach((r, i) => {
                const item = document.createElement('div');
                item.className = 'cx-ac-item' + (i === activeIndex ? ' active' : '');
                const ico = document.createElement('div');
                ico.className = 'cx-ac-icon';
                ico.textContent = initials(r.name || r.business || r.email);
                item.appendChild(ico);
                const txt = document.createElement('div');
                txt.className = 'cx-ac-text';
                const nm = document.createElement('div');
                nm.className = 'cx-ac-name';
                nm.textContent = r.label || r.email;
                txt.appendChild(nm);
                const em = document.createElement('div');
                em.className = 'cx-ac-email';
                em.textContent = r.email;
                txt.appendChild(em);
                item.appendChild(txt);
                if (r.match) {
                    const mt = document.createElement('span');
                    mt.className = 'cx-ac-match';
                    mt.textContent = r.match;
                    item.appendChild(mt);
                }
                item.addEventListener('mousedown', e => {
                    e.preventDefault();
                    addPill(r);
                    input.value = '';
                    hideDropdown();
                    input.focus();
                });
                drop.appendChild(item);
            });
            drop.classList.add('on');
        }

        function hideDropdown() {
            drop.classList.remove('on');
            currentResults = [];
            activeIndex = -1;
        }

        function initials(s) { return (s || '?').split(/\s+/).map(p => p[0] || '').join('').toUpperCase().slice(0, 2) || '?'; }
        function cssEscape(s) { return (s||'').replace(/["\\]/g, '\\$&'); }

        input.addEventListener('input', () => {
            clearTimeout(debounce);
            const v = input.value.trim();
            if (v.endsWith(',') || v.endsWith(';')) { commitInputAsEmail(); return; }
            debounce = setTimeout(() => search(v), 150);
        });

        input.addEventListener('keydown', e => {
            if (e.key === 'Enter' || e.key === 'Tab') {
                if (currentResults.length && activeIndex >= 0) {
                    e.preventDefault();
                    addPill(currentResults[activeIndex]);
                    input.value = '';
                    hideDropdown();
                } else if (input.value.trim()) {
                    e.preventDefault();
                    commitInputAsEmail();
                }
            } else if (e.key === 'ArrowDown' && currentResults.length) {
                e.preventDefault();
                activeIndex = (activeIndex + 1) % currentResults.length;
                renderDropdown();
            } else if (e.key === 'ArrowUp' && currentResults.length) {
                e.preventDefault();
                activeIndex = (activeIndex - 1 + currentResults.length) % currentResults.length;
                renderDropdown();
            } else if (e.key === 'Escape') {
                hideDropdown();
            } else if (e.key === 'Backspace' && input.value === '') {
                const pills = container.querySelectorAll('.cx-pill');
                if (pills.length) pills[pills.length - 1].remove();
            }
        });

        input.addEventListener('blur', () => {
            setTimeout(() => {
                if (input.value.trim()) commitInputAsEmail();
                hideDropdown();
            }, 200);
        });
    }
})();
</script>

<?php require __DIR__ . '/_footer.php'; ?>