"""
email_tools.py — Email and spam analysis functions.
"""

import os
import re
import socket
from datetime import date

from modules.output import warn, info, header, good, bad
from modules.utils import require_bin, run, is_cpanel


def spamcheck():
    """
    Full email health report: queue, frozen messages, top senders,
    relay logs, Dovecot logins, eximstats, and blacklist check URL.
    """
    if not require_bin('exim', 'spamcheck'):
        return

    cpanel = is_cpanel()
    exim_log = '/var/log/exim_mainlog' if cpanel else '/var/log/exim/main_log'

    print()
    print("=" * 51)
    print("              EMAIL REPORT")
    print("=" * 51)
    print(f"  {date.today().strftime('%A, %B %d %Y')}")
    print()

    # Queue count
    out, _, _ = run(['exim', '-bpc'])
    print(f"Total emails in exim queue:         {out.strip()}")

    # Frozen count
    if require_bin('exiqgrep', 'frozen message count'):
        out2, _, _ = run(['exiqgrep', '-iz'])
        frozen = len(out2.strip().splitlines()) if out2.strip() else 0
        print(f"Total frozen emails in exim queue:  {frozen}")

    # Top senders by volume
    print()
    if require_bin('exiqsumm', 'queue summary'):
        bp_out, _, _ = run(['exim', '-bp'])
        summ_result = _pipe_exiqsumm(bp_out)
        if summ_result:
            header("Top Senders by Volume:")
            for line in summ_result:
                print(line)

    print()

    # LFD relay check
    if os.path.isfile('/var/log/lfd.log'):
        print("Checking for relay entries within LFD log files.")
        with open('/var/log/lfd.log', 'r', errors='replace') as f:
            for line in f:
                if 'relay' in line.lower():
                    print(f"  {line.rstrip()}")
    print()

    # High-volume Dovecot logins
    print("Checking for high volume dovecot logins (potential compromised accounts).")
    if os.path.isfile(exim_log):
        _dovecot_logins(exim_log)
    print()

    # Eximstats
    if require_bin('eximstats', 'eximstats summary') and os.path.isfile(exim_log):
        print("Eximstats Summary:")
        out, _, _ = run(['eximstats', exim_log])
        lines = out.splitlines()
        for line in lines[:11]:
            print(f"  {line}")
        # Rejection stats
        in_rejection = False
        rej_lines = []
        for line in lines:
            if 'rejection' in line.lower():
                in_rejection = True
            if in_rejection:
                if 'sending' in line.lower():
                    continue
                rej_lines.append(line)
                if len(rej_lines) > 6:
                    break
        if rej_lines:
            print()
            for line in rej_lines:
                print(f"  {line}")

    print()

    # Blacklist check
    ip = socket.gethostbyname(socket.gethostname())
    print(f"Blacklist Check URL: https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3A{ip}")
    print()


def _pipe_exiqsumm(bp_output):
    """Run exiqsumm on exim -bp output, return formatted lines."""
    import subprocess
    try:
        proc = subprocess.run(
            ['exiqsumm'],
            input=bp_output.encode() if isinstance(bp_output, str) else bp_output,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        results = []
        for line in proc.stdout.decode('utf-8', errors='replace').splitlines():
            if re.match(r'^\s*-', line) or 'Volume' in line or not line.strip():
                continue
            parts = line.split()
            if len(parts) >= 5:
                results.append(f"  Volume: {parts[0]:<10} Domain: {parts[4]}")
        return results
    except FileNotFoundError:
        return []


def _dovecot_logins(log_path):
    """Extract and count high-volume Dovecot logins from Exim log."""
    pattern = re.compile(r'dovecot_(?:plain|login):(\S+)')
    counts = {}
    try:
        with open(log_path, 'r', errors='replace') as f:
            for line in f:
                m = pattern.search(line)
                if m:
                    user = m.group(1)
                    counts[user] = counts.get(user, 0) + 1
    except PermissionError:
        warn("Cannot read Exim log (permission denied).")
        return

    if not counts:
        info("  No high-volume Dovecot logins detected.")
        return

    sorted_users = sorted(counts.items(), key=lambda x: x[1])
    for user, count in sorted_users[-10:]:
        print(f"  {count:>6}  {user}")


def lsforwards():
    """
    List all active email forwarders by parsing the Exim mainlog.
    """
    cpanel = is_cpanel()
    log_path = '/var/log/exim_mainlog' if cpanel else '/var/log/exim/main_log'

    if not os.path.isfile(log_path):
        warn(f"Exim log not found: {log_path}")
        return

    pattern = re.compile(r'=> .*?@.*?@.*?lookuphost')
    addr_pattern = re.compile(r'<([^>]+@[^>]+)>.*?<([^>]+@[^>]+)>')
    counts = {}

    try:
        with open(log_path, 'r', errors='replace') as f:
            for line in f:
                if 'lookuphost' in line and '=>' in line:
                    # Extract source and dest addresses
                    parts = line.split()
                    # Fields: ... (src) => (dest)
                    try:
                        arrow_idx = parts.index('=>')
                        dest = parts[arrow_idx + 1].strip('<>()')
                        src = parts[arrow_idx - 1].strip('<>()')
                        if '@' in src and '@' in dest:
                            key = f"{dest} <- {src}"
                            counts[key] = counts.get(key, 0) + 1
                    except (ValueError, IndexError):
                        continue
    except PermissionError:
        warn("Cannot read Exim log (permission denied).")
        return

    if not counts:
        info("No active forwarders found in log.")
        return

    header(f"{'Count':<8} Forward")
    print("-" * 60)
    for fwd, count in sorted(counts.items(), key=lambda x: x[1]):
        print(f"{count:<8} {fwd}")
