/**
 * Charset normalization for incoming email bodies.
 *
 * Many senders (esp. PHPMailer-driven marketing) declare
 * `charset=iso-8859-1` but emit UTF-8 bytes. simpleParser honors the
 * declared charset and produces "â??" garbage for every non-ASCII
 * codepoint (em-dash, smart quotes, …). When the raw body bytes are
 * valid UTF-8, rewrite the charset header before parsing. We only
 * override the obviously-wrong legacy declarations; explicit utf-8 /
 * koi8 / etc. pass through.
 */

/** Returns either the original buffer (no change needed) or a copy with
 *  the leading charset declaration rewritten to utf-8. */
export function sniffAndFixCharset(raw: Buffer): Buffer {
    const HEAD_LIMIT = 16384;
    const head = raw.subarray(0, Math.min(HEAD_LIMIT, raw.length)).toString("latin1");
    const re = /charset\s*=\s*"?(iso-8859-1|us-ascii|windows-1252|latin1)"?/gi;
    if (!re.test(head)) return raw;
    if (!isValidUtf8(raw)) return raw;
    const fixed = head.replace(/charset\s*=\s*"?(iso-8859-1|us-ascii|windows-1252|latin1)"?/gi, "charset=utf-8");
    return Buffer.concat([Buffer.from(fixed, "latin1"), raw.subarray(head.length)]);
}

/** Strict UTF-8 validity check: rejects overlong forms, invalid start
 *  bytes, and dangling continuations. Used to confirm the body is really
 *  UTF-8 before overriding a Latin-1 declaration. */
function isValidUtf8(buf: Buffer): boolean {
    let i = 0;
    while (i < buf.length) {
        const b = buf[i];
        if (b < 0x80) { i++; continue; }
        let need: number;
        if ((b & 0xE0) === 0xC0) { if (b < 0xC2) return false; need = 1; }
        else if ((b & 0xF0) === 0xE0) need = 2;
        else if ((b & 0xF8) === 0xF0) { if (b > 0xF4) return false; need = 3; }
        else return false;
        if (i + need >= buf.length) return false;
        for (let k = 1; k <= need; k++) {
            if ((buf[i + k] & 0xC0) !== 0x80) return false;
        }
        i += need + 1;
    }
    return true;
}
