<?php
if (!defined('ABSPATH')) exit;

/**
 * Triage Summary helpers (server side).
 * Guarded with function_exists to avoid redeclare during migration.
 *
 * Guarantees:
 * - No literal "Triage Summary" heading/label appears in HTML or plain paths.
 * - No personal greeting at the very start (e.g., “Thanks, John”, “Hi team”, “Hello …”, “Dear …”).
 * - Output is tidy and structured for Asana.
 */

/** Minimal, Asana-safe allowlist (also fine for .doc content). */
if (!function_exists('afb_allowed_html')) {
function afb_allowed_html() {
    return [
        'a'           => ['href' => true, 'target' => true, 'rel' => true],
        'p'           => [],
        'br'          => [],
        'strong'      => [],
        'b'           => [],
        'em'          => [],
        'i'           => [],
        'u'           => [],
        's'           => [],
        'ul'          => [],
        'ol'          => [],
        'li'          => [],
        'code'        => [],
        'pre'         => [],
        'blockquote'  => [],
        'span'        => [], // no style attrs allowed
        'div'         => [], // harmless wrapper
    ];
}}

/** HTML → plain text (tidy, preserves bullets and spacing for Asana). */
if (!function_exists('afb_plain_text_from_html')) {
function afb_plain_text_from_html($html) {
    $t = (string)$html;

    // Fix literal \n sequences early (in case upstream stored escaped newlines)
    if (function_exists('afb_fix_literal_newlines')) {
        $t = afb_fix_literal_newlines($t);
    }

    // Headings → blank lines so next text doesn't glue to them
    $t = preg_replace('/<h[1-6][^>]*>\s*/i', "\n\n", $t);
    $t = preg_replace('/\s*<\/h[1-6]>\s*/i', "\n\n", $t);

    // Lists → each item on its own line
    $t = preg_replace('/\s*<li[^>]*>\s*/i', "\n- ", $t);
    $t = preg_replace('/\s*<\/li>\s*/i', "\n", $t);
    $t = preg_replace('/\s*<\/(?:ul|ol)>\s*/i', "\n\n", $t);

    // Paragraphs / breaks → newlines
    $t = preg_replace('/<\s*br\s*\/?>/i', "\n",  $t);
    $t = preg_replace('/<\s*\/p\s*>/i', "\n\n", $t);
    $t = preg_replace('/<\s*p[^>]*>/i', '', $t);

    // Strip remaining tags but KEEP line breaks
    $t = wp_strip_all_tags($t, false);
    $t = html_entity_decode($t, ENT_QUOTES | ENT_HTML5, 'UTF-8');

    // Re-run newline fixer after tag-strip (covers cases introduced later)
    if (function_exists('afb_fix_literal_newlines')) {
        $t = afb_fix_literal_newlines($t);
    }

    // If any bullets got glued, force newline before "- Label:" patterns
    $t = preg_replace(
        '/(?<!^)(?<!\n)\s*-\s(?=[A-Za-z][A-Za-z0-9\/&() \-]{1,60}:)/m',
        "\n- ",
        $t
    );

    // Tidy whitespace
    $t = preg_replace('/[ \t]+\n/', "\n", $t);
    $t = preg_replace('/\n{3,}/', "\n\n", $t);
    $t = preg_replace('/\s*:\s*/', ': ', $t);

    return trim($t);
}}


/** Personalise “Thanks there” → “Thanks, {First}”. (Kept for BC; NOT used by default.) */
if (!function_exists('afb_personalize_triage_greeting')) {
function afb_personalize_triage_greeting($html, $first_name) {
    $first = trim((string)$first_name);
    if ($first === '') return (string)$html;

    return preg_replace(
        '/\bThanks,?\s*there(\s*[!.,])?/i',
        'Thanks, ' . esc_html($first) . '$1',
        (string)$html
    );
}}

/** Clean triage (plain): drop "Triage Summary" and any leading greetings/boilerplate tails. */
if (!function_exists('afb_clean_triage_plain')) {
function afb_clean_triage_plain($triage_html) {
    $t = afb_plain_text_from_html($triage_html);

    // Ensure literal "\n" or stripped "\n" cases are repaired even if input wasn't HTML-y
    if (function_exists('afb_fix_literal_newlines')) {
        $t = afb_fix_literal_newlines($t);
    }

    // Remove 1..5 leading repetitions like "Triage Summary", "Triage Summary:", etc.
    $t = preg_replace('/^\xEF\xBB\xBF?(?:\s*Triage\s+Summary\b[:\-]?\s*){1,5}/iu', '', $t);

    // Remove any standalone "Triage Summary" lines that may remain later
    $t = preg_replace('/^\s*Triage\s+Summary\b[:\-]?\s*$/imu', '', $t);

    // Remove a leading greeting line (first visible line only)
    $t = preg_replace('/^\xEF\xBB\xBF?\s*(?:Thanks(?:,|\s+(?:there|team|all|\w+))?|Thank\s+you|Hi|Hello|Dear)\b[^\r\n]*\r?\n+/iu', '', $t);

    // Drop anything like "below is the copy submitted..." tails
    $t = preg_replace('/\s*below\s+is\s+the\s+copy\s+submitted:?[\s\S]*$/iu', '', $t);

    // Final tidy
    $t = preg_replace('/\n{3,}/', "\n\n", $t);

    return trim($t);
}}


/** Normalize risky HTML to Asana-safe HTML for html_notes (.doc also benefits). */
if (!function_exists('afb_normalize_html_for_asana')) {
function afb_normalize_html_for_asana($html) {
    $html = (string)$html;

    // Remove explicit heading that is exactly "Triage Summary"
    $html = preg_replace('/<h[1-6][^>]*>\s*Triage\s+Summary\s*<\/h[1-6]>\s*/iu', '', $html);
    // Remove bare "Triage Summary" label at the very start (with optional punctuation/nbsp)
    $html = preg_replace('/^\xEF\xBB\xBF?(?:\s|&nbsp;)*(?:Triage\s+Summary\s*[:\-]?\s*)+/iu', '', $html);

    // Remove a leading greeting block (<p>/<div>… or bare text + <br>)
    $html = preg_replace(
        '/^\xEF\xBB\xBF?(?:\s|&nbsp;)*(?:<(?:p|div)[^>]*>)?\s*(?:Thanks(?:,|\s+(?:there|team|all|\w+))?|Thank\s+you|Hi|Hello|Dear)\b.*?(?:<\/(?:p|div)>|<br\s*\/?>)?\s*/iu',
        '',
        $html
    );

    // Headings → <p><strong>…</strong></p> (after removal above)
    $html = preg_replace_callback('/<h[1-6][^>]*>(.*?)<\/h[1-6]>/is', function($m){
        return '<p><strong>' . $m[1] . '</strong></p>';
    }, $html);

    // <hr> → blank lines
    $html = preg_replace('/<hr\s*\/?>/i', '<br><br>', $html);

    // Sanitize to our tight allowlist
    $html = wp_kses($html, afb_allowed_html());

    // Collapse excessive <br>
    $html = preg_replace('/(?:<br>\s*){3,}/i', '<br><br>', $html);

    // Trim leading/trailing whitespace and break clutter
    $html = preg_replace('/^(?:\s|&nbsp;|<br>)+/i', '', $html);
    $html = preg_replace('/(?:\s|&nbsp;|<br>)+$/i', '', $html);

    return trim($html);
}}

/** Build Asana-safe rich description (HTML path) — NO "Triage Summary" heading, NO greeting. */
if (!function_exists('afb_generate_combined_summary_html')) {
function afb_generate_combined_summary_html($triage_html, $request_details_text) {
    $triage_html = afb_normalize_html_for_asana($triage_html);
    $source_heading = 'This request was submitted QH Forms';

    // NEW: prepend triage ref from cookie when available
    $triage_ref = '';
    if (!empty($_COOKIE['triage_gpt_session'])) {
        $triage_ref = sanitize_text_field((string) $_COOKIE['triage_gpt_session']);
    }

    $out  = '';

    if (stripos($triage_html, $source_heading) === false) {
        $out .= '<p><strong>' . esc_html($source_heading) . '</strong></p><br>';
    }

    if ($triage_ref !== '') {
        $out .= '<p><strong>Triage Ref:</strong> ' . esc_html($triage_ref) . '</p><br>';
    }

    $out .= $triage_html;

    $req = trim((string)$request_details_text);
    if ($req !== '') {
        $out .= '<br><p><strong>Request Details (SCB)</strong></p><p>' . esc_html($req) . '</p>';
    }

    return $out;
}}


/** Build plain-text description (NO "Triage Summary" heading, NO greeting). */

if (!function_exists('afb_generate_combined_summary_plain')) {
function afb_generate_combined_summary_plain($triage_html, $request_details_text) {
    $triage_plain = afb_clean_triage_plain($triage_html);
    $source_heading = 'This request was submitted through QH Forms';

    // Triage ref from cookie when available
    $triage_ref = '';
    if (!empty($_COOKIE['triage_gpt_session'])) {
        $triage_ref = sanitize_text_field((string) $_COOKIE['triage_gpt_session']);
    }

    $out  = '';
    $out .= $source_heading;

    if ($triage_plain !== '') {
        $out .= "\r\n\r\n" . $triage_plain;
    }

    $req = trim((string)$request_details_text);
    if ($req !== '') {
        $out .= "\r\n\r\nRequest Details (SCB)\r\n" . $req;
    }

    // Append triage ref at the end
    if ($triage_ref !== '') {
        $out .= "\r\n\r\nTriage Ref: {$triage_ref}";
    }

    // Normalize to CRLF so Asana displays line breaks reliably
    $out = preg_replace("/(?<!\r)\n/", "\r\n", $out);

    return trim($out);
}}


/** Fix literal "\n" sequences and repair the common "n" glue when "\" got stripped. */
if (!function_exists('afb_fix_literal_newlines')) {
function afb_fix_literal_newlines($text) {
    $t = (string)$text;

    // 1) Convert literal backslash escapes into actual newlines
    // "\\r\\n" -> "\n", "\\n" -> "\n", "\\r" -> "\n"
    $t = str_replace(["\\r\\n", "\\n", "\\r"], "\n", $t);

    // 2) Repair cases where the backslash got stripped, leaving "...nNext"
    // Only do this when:
    // - the "n" is immediately followed by an Uppercase letter (start of a new sentence/heading)
    // - and preceded by punctuation/number/closing bracket/quote where a newline is plausible
    $t = preg_replace('/([:\.\!\?\)\]\}0-9])n(?=[A-Z])/', "$1\n", $t);

    // Also handle "...wordnBelow" (rare but matches your example "2026nBelow")
    $t = preg_replace('/([A-Za-z0-9])n(?=[A-Z][a-z])/', "$1\n", $t);

    // Normalize line endings to \n for subsequent cleanup
    $t = preg_replace("/\r\n?/", "\n", $t);

    return $t;
}}

if (!function_exists('afb_triage_value_to_string')) {
function afb_triage_value_to_string($value): string {
    if (is_scalar($value)) {
        return trim((string)$value);
    }

    if (is_array($value)) {
        $parts = [];
        foreach ($value as $item) {
            if (is_scalar($item)) {
                $s = trim((string)$item);
                if ($s !== '') $parts[] = $s;
            }
        }
        return implode(', ', $parts);
    }

    return '';
}}

if (!function_exists('afb_triage_answer_first')) {
function afb_triage_answer_first(array $answers, array $keys): string {
    foreach ($keys as $k) {
        if (!array_key_exists($k, $answers)) continue;
        $v = afb_triage_value_to_string($answers[$k]);
        if ($v !== '') return $v;
    }
    return '';
}}

if (!function_exists('afb_triage_ref_from_state')) {
function afb_triage_ref_from_state(array $state = [], array $answers = []): string {
    $candidates = [
        $state['triage_ref'] ?? null,
        $state['session_key'] ?? null,
        $state['meta']['triage_ref'] ?? null,
        $state['meta']['session_key'] ?? null,
        $answers['triage_ref'] ?? null,
        $answers['session_key'] ?? null,
        $_COOKIE['triage_gpt_session'] ?? null,
    ];

    foreach ($candidates as $candidate) {
        $v = is_scalar($candidate) ? trim((string)$candidate) : '';
        if ($v !== '') return sanitize_text_field($v);
    }

    return '';
}}

if (!function_exists('afb_generate_structured_triage_summary_plain')) {
function afb_generate_structured_triage_summary_plain(array $triage_state = [], array $triage_answers = []): string {
    $answers = [];

    if (!empty($triage_state['answers']) && is_array($triage_state['answers'])) {
        $answers = $triage_state['answers'];
    }
    if (!empty($triage_answers) && is_array($triage_answers)) {
        $answers = array_merge($answers, $triage_answers);
    }

    if (empty($answers)) return '';

    $service    = afb_triage_answer_first($answers, ['service', 'service_name']);
    $subservice = afb_triage_answer_first($answers, ['subservice', 'subservice_name']);

    // Fallback: check top-level triage_state keys (not just answers)
    if ($service === '' && !empty($triage_state['service_name'])) {
        $service = trim((string)$triage_state['service_name']);
    }
    if ($subservice === '' && !empty($triage_state['subservice_name'])) {
        $subservice = trim((string)$triage_state['subservice_name']);
    }

    $headingTarget = $subservice !== '' ? $subservice : ($service !== '' ? $service : 'service');
    if (preg_match('/\brequest\b\s*$/i', $headingTarget)) {
        $headingTarget = preg_replace('/\brequest\b\s*$/i', '', $headingTarget);
        $headingTarget = trim((string)$headingTarget);
        if ($headingTarget === '') {
            $headingTarget = 'service';
        }
    }

    $first = afb_triage_answer_first($answers, ['first_name']);
    $last  = afb_triage_answer_first($answers, ['last_name']);
    $full  = afb_triage_answer_first($answers, ['full_name']);
    $name  = '';
    if ($full !== '') {
        $name = $full;
    } elseif ($first !== '' || $last !== '') {
        $name = trim($first . ' ' . $last);
    }

    if ($name !== '') {
        $out = esc_html($name) . ' has made a ' . $headingTarget . " request. The details are below:\n\n";
    } else {
        $out = 'You have submitted a ' . $headingTarget . " request. The details are below:\n\n";
    }

    $lines = [];
    if ($service !== '')    $lines[] = 'Service: ' . $service;
    if ($subservice !== '') $lines[] = 'Subservice: ' . $subservice;

    $fieldOrder = [
        'Broadcast Type'    => ['broadcast_type'],
        'Audience'          => ['audience', 'target_group'],
        'Audience Segment'  => ['audience_segment'],
        'Staff Relevance'   => ['staff_relevance'],
        'Subject'           => ['broadcast_title', 'ealert_heading', 'title'],
        'Requested Date'    => ['broadcast_date', 'date', 'date_qh'],
        'Approval'          => ['approval'],
        'Approver Name'     => ['approver_name'],
        'Approver Position' => ['approver_position'],
        'Copy under 100 words' => ['copy_ready'],
        'Plain English check'  => ['clarity'],
        'Start Date'        => ['start_date'],
        'End Date'          => ['end_date'],
        'Stage'             => ['stage'],
        'System Campaign'   => ['system_campaign'],
        'DDG'               => ['ddg_other', 'qh_update_ddg'],
        'Content Source'    => ['broadcast_content_source', 'ealert_content_source'],
        'Display Channel'   => ['display_channel'],
        'Asset Ready'       => ['asset_ready'],
        'Created by SCB'    => ['created_by_scb'],
        'Brand Check'       => ['brand_check'],
        'Asset Size'        => ['asset_size'],
        'Asset Link'        => ['asset_link'],
        'Related Service'   => ['related_service'],
    ];

    foreach ($fieldOrder as $label => $keys) {
        $v = afb_triage_answer_first($answers, $keys);
        if ($v === '') continue;

        $v = preg_replace('/^\s*[-•]\s*/u', '', (string)$v);
        $v = preg_replace('/\s*\n+\s*/', ' ', (string)$v);
        $v = trim((string)$v);
        if ($v === '') continue;

        $lines[] = $label . ': ' . $v;
    }

    // ── Dynamic: append any remaining answer keys not covered by $fieldOrder ──
    $coveredKeys = array_merge(
        ['service', 'service_name', 'subservice', 'subservice_name'],
        ...array_values($fieldOrder)
    );
    // Internal / meta keys to never show in summary
    $skipKeys = array_flip([
        'triage_summary', 'triage_summary_html',
        'submitted_copy_html', 'submitted_copy_plain',
        'first_name', 'last_name', 'work_email', 'full_name',
        'triage_ref', 'session_key',
    ]);
    $coveredFlip = array_flip($coveredKeys);

    foreach ($answers as $rawKey => $rawVal) {
        if (isset($coveredFlip[$rawKey]) || isset($skipKeys[$rawKey])) continue;
        if (preg_match('/^follow_up_\d+$/i', (string)$rawKey)) continue;
        $val = is_string($rawVal) ? trim($rawVal) : '';
        if ($val === '') continue;
        // Convert snake_case to Title Case label
        $label = ucwords(str_replace('_', ' ', sanitize_text_field($rawKey)));
        $lines[] = $label . ': ' . sanitize_text_field($val);
    }

    if (!empty($lines)) $out .= implode("\n", $lines);

    $triageRef = afb_triage_ref_from_state($triage_state, $answers);
    if ($triageRef !== '') {
        $out .= "\n\nTriage Ref: " . $triageRef;
    }

    return trim($out);
}}

if (!function_exists('afb_generate_structured_triage_summary_html')) {
function afb_generate_structured_triage_summary_html(array $triage_state = [], array $triage_answers = []): string {
    $plain = afb_generate_structured_triage_summary_plain($triage_state, $triage_answers);
    if ($plain === '') return '';

    return '<p>' . nl2br(esc_html($plain)) . '</p>';
}}

