#!/bin/bash
# SecuBox Mail Server Controller
# Unified mail + webmail management for Debian
# Three-fold architecture: Components, Status, Access

VERSION="2.2.0"
CONFIG_FILE="/etc/secubox/mail.toml"
LIB_DIR="/usr/lib/secubox/mail/lib"
DATA_PATH="/data/volumes/mail"
LXC_PATH="/var/lib/lxc"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log() { echo -e "${GREEN}[MAIL]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1" >&2; }

# Load libraries
[ -f "$LIB_DIR/container.sh" ] && . "$LIB_DIR/container.sh"
[ -f "$LIB_DIR/users.sh" ] && . "$LIB_DIR/users.sh"

# ============================================================================
# Configuration (TOML parsing)
# ============================================================================

config_get() {
    local key="$1"
    local default="$2"
    if [ -f "$CONFIG_FILE" ]; then
        local value=$(grep "^${key} *=" "$CONFIG_FILE" 2>/dev/null | head -1 | cut -d= -f2- | tr -d ' "')
        [ -n "$value" ] && echo "$value" || echo "$default"
    else
        echo "$default"
    fi
}

DOMAIN=$(config_get "domain" "secubox.local")
HOSTNAME=$(config_get "hostname" "mail")
CONTAINER=$(config_get "container" "mail")
WEBMAIL_CONTAINER="$CONTAINER"  # legacy alias — webmail merged into single container
LXC_IP=$(config_get "lxc_ip" "10.100.0.10")
LXC_BRIDGE=$(config_get "lxc_bridge" "br-lxc")
LXC_GATEWAY=$(config_get "lxc_gateway" "10.100.0.1")
WEBMAIL_PORT=80  # Roundcube now on standard HTTP inside the LXC, proxied via host nginx :443

# ============================================================================
# LXC Helpers
# ============================================================================

lxc_running() {
    local name="$1"
    lxc-info -n "$name" 2>/dev/null | grep -q "State:.*RUNNING"
}

lxc_exists() {
    local name="$1"
    [ -d "$LXC_PATH/$name/rootfs" ]
}

lxc_attach() {
    local name="$1"
    shift
    lxc-attach -n "$name" -- "$@"
}

# ============================================================================
# THREE-FOLD ARCHITECTURE: Components (What)
# ============================================================================

cmd_components() {
    # Output JSON for API consumption
    local mail_installed=false
    local mail_running=false
    local webmail_installed=false
    local webmail_running=false

    lxc_exists "$CONTAINER" && mail_installed=true
    lxc_running "$CONTAINER" && mail_running=true
    lxc_exists "$WEBMAIL_CONTAINER" && webmail_installed=true
    lxc_running "$WEBMAIL_CONTAINER" && webmail_running=true

    cat <<EOF
{
  "components": [
    {
      "name": "Mail Server",
      "type": "lxc",
      "container": "$CONTAINER",
      "description": "Postfix + Dovecot mail server",
      "installed": $mail_installed,
      "running": $mail_running,
      "ports": [25, 587, 465, 143, 993, 110, 995],
      "ip": "$LXC_IP"
    },
    {
      "name": "Webmail",
      "type": "lxc",
      "container": "$WEBMAIL_CONTAINER",
      "description": "Roundcube webmail interface",
      "installed": $webmail_installed,
      "running": $webmail_running,
      "port": $WEBMAIL_PORT
    },
    {
      "name": "User Database",
      "type": "file",
      "path": "$DATA_PATH/config/users",
      "description": "Dovecot passwd-file users",
      "installed": true
    },
    {
      "name": "SSL Certificates",
      "type": "file",
      "path": "$DATA_PATH/ssl/fullchain.pem",
      "description": "TLS certificates for mail server",
      "installed": $([ -f "$DATA_PATH/ssl/fullchain.pem" ] && echo true || echo false)
    }
  ]
}
EOF
}

# ============================================================================
# THREE-FOLD ARCHITECTURE: Access (How to connect)
# ============================================================================

cmd_access() {
    local fqdn="$HOSTNAME.$DOMAIN"
    local ssl_enabled=false
    [ -f "$DATA_PATH/ssl/fullchain.pem" ] && ssl_enabled=true

    cat <<EOF
{
  "domain": "$DOMAIN",
  "mail_server": "$fqdn",
  "connections": {
    "imap": {
      "host": "$fqdn",
      "port": 993,
      "ssl": true,
      "starttls_port": 143
    },
    "smtp": {
      "host": "$fqdn",
      "port": 587,
      "ssl": false,
      "starttls": true,
      "ssl_port": 465
    },
    "pop3": {
      "host": "$fqdn",
      "port": 995,
      "ssl": true
    }
  },
  "webmail": {
    "url": "https://webmail.$DOMAIN",
    "local_url": "http://localhost:$WEBMAIL_PORT"
  },
  "ssl_enabled": $ssl_enabled,
  "client_configs": {
    "thunderbird": "https://autoconfig.$DOMAIN/mail/config-v1.1.xml",
    "outlook": "https://autodiscover.$DOMAIN/autodiscover/autodiscover.xml",
    "apple": "https://$fqdn/$DOMAIN.mobileconfig"
  }
}
EOF
}

# ============================================================================
# DNS Setup
# ============================================================================

cmd_dns_setup() {
    local fqdn="$HOSTNAME.$DOMAIN"
    log "Generating DNS records for $DOMAIN..."

    echo ""
    echo "============================================"
    echo "  DNS Records for $DOMAIN"
    echo "============================================"
    echo ""
    echo "MX Record:"
    echo "  $DOMAIN.  IN  MX  10  $fqdn."
    echo ""
    echo "A Records:"
    echo "  $HOSTNAME.$DOMAIN.  IN  A  <YOUR_IP>"
    echo "  webmail.$DOMAIN.    IN  A  <YOUR_IP>"
    echo ""
    echo "SPF Record:"
    echo "  $DOMAIN.  IN  TXT  \"v=spf1 mx a:$fqdn -all\""
    echo ""
    echo "DKIM Record (generate with: mailctl dkim-setup):"
    echo "  default._domainkey.$DOMAIN.  IN  TXT  \"v=DKIM1; k=rsa; p=...\""
    echo ""
    echo "DMARC Record:"
    echo "  _dmarc.$DOMAIN.  IN  TXT  \"v=DMARC1; p=quarantine; rua=mailto:postmaster@$DOMAIN\""
    echo ""
}

# ============================================================================
# User Repair (mailbox resync)
# ============================================================================

cmd_user_repair() {
    local email="$1"
    [ -z "$email" ] && { echo "Usage: mailctl user-repair <email>"; return 1; }

    if ! lxc_running "$CONTAINER"; then
        error "Mail container not running"
        return 1
    fi

    log "Repairing mailbox for $email..."
    lxc_attach "$CONTAINER" doveadm force-resync -u "$email" '*'
    log "Mailbox repair complete"
}

# ============================================================================
# Fix Ports (container port checking)
# ============================================================================

cmd_fix_ports() {
    if ! lxc_running "$CONTAINER"; then
        error "Mail container not running"
        return 1
    fi

    log "Checking mail ports..."
    local ports=$(lxc_attach "$CONTAINER" netstat -tln 2>/dev/null)
    local all_ok=true

    for port in 25 587 465 143 993; do
        if echo "$ports" | grep -q ":$port "; then
            echo -e "  Port $port: ${GREEN}OK${NC}"
        else
            echo -e "  Port $port: ${RED}NOT LISTENING${NC}"
            all_ok=false
        fi
    done

    if [ "$all_ok" = "false" ]; then
        warn "Some ports are not listening. Attempting restart..."
        lxc_attach "$CONTAINER" /opt/start-mail.sh &
        sleep 3
        log "Services restarted"
    else
        log "All ports OK"
    fi
}

# ============================================================================
# Install
# ============================================================================

cmd_install() {
    [ "$(id -u)" -eq 0 ] || { error "Root required"; return 1; }
    log "Installing SecuBox Mail Server (single LXC '$CONTAINER')..."

    : "${LIB_DIR:=/usr/lib/secubox/mail/lib}"
    if [ ! -f "$LIB_DIR/install.sh" ]; then
        local alt="$(dirname "$0")/../lib/mail"
        [ -f "$alt/install.sh" ] && LIB_DIR="$alt"
    fi
    # shellcheck source=/dev/null
    source "$LIB_DIR/lxc.sh"
    # shellcheck source=/dev/null
    source "$LIB_DIR/install.sh"

    # Persistent data dirs (host-side, bind-mounted into the LXC)
    mkdir -p "$DATA_PATH"/{vmail,config,ssl,backups}
    mkdir -p "$LXC_PATH"

    # Bootstrap rootfs + render LXC config
    if ! lxc_exists "$CONTAINER"; then
        LXC_BASE="$LXC_PATH" bootstrap_debian "$CONTAINER"
    fi
    LXC_BASE="$LXC_PATH" lxc_create_config "$CONTAINER" "$LXC_IP" "$LXC_BRIDGE" "$LXC_GATEWAY"

    # Bring the container up so install steps can chroot/apt
    LXC_BASE="$LXC_PATH" lxc_start_safely "$CONTAINER" || {
        error "container failed to start"; return 1; }

    LXC_BASE="$LXC_PATH" install_mail_packages    "$CONTAINER"
    LXC_BASE="$LXC_PATH" install_webmail_packages "$CONTAINER"
    LXC_BASE="$LXC_PATH" DOMAIN="$DOMAIN" HOSTNAME="$HOSTNAME" \
        configure_postfix   "$CONTAINER"
    LXC_BASE="$LXC_PATH" configure_dovecot   "$CONTAINER"
    LXC_BASE="$LXC_PATH" DOMAIN="$DOMAIN" \
        configure_roundcube "$CONTAINER"

    log "Installation complete!"
    echo ""
    echo "Next steps:"
    echo "  1. Configure: edit $CONFIG_FILE"
    echo "  2. Add users: mailctl user add user@$DOMAIN"
    echo "  3. Start: mailctl start"
}

cmd_uninstall() {
    warn "This will remove mail containers. Data in $DATA_PATH will be preserved."
    read -p "Continue? (yes/no): " confirm
    [ "$confirm" != "yes" ] && { echo "Aborted"; return 1; }

    log "Stopping services..."
    systemctl stop secubox-mail 2>/dev/null

    log "Removing containers..."
    lxc-stop -n "$CONTAINER" 2>/dev/null
    lxc-stop -n "$WEBMAIL_CONTAINER" 2>/dev/null
    rm -rf "$LXC_PATH/$CONTAINER"
    rm -rf "$LXC_PATH/$WEBMAIL_CONTAINER"

    log "Mail server removed. Data preserved in $DATA_PATH"
}

# ============================================================================
# Service Control
# ============================================================================

cmd_start() {
    log "Starting mail LXC '$CONTAINER'..."
    if lxc_running "$CONTAINER"; then
        log "already running"
        return 0
    fi
    if ! lxc_exists "$CONTAINER"; then
        error "container '$CONTAINER' not present at $LXC_PATH/$CONTAINER"
        return 1
    fi
    lxc-start -n "$CONTAINER" -d
    # Wait up to 10s for RUNNING state.
    for _ in 1 2 3 4 5 6 7 8 9 10; do
        lxc_running "$CONTAINER" && { log "mail LXC running"; return 0; }
        sleep 1
    done
    error "mail LXC failed to start within 10s"
    return 1
}

cmd_stop() {
    log "Stopping mail LXC '$CONTAINER'..."
    if ! lxc_running "$CONTAINER"; then
        log "already stopped"
        return 0
    fi
    lxc-stop -n "$CONTAINER" -t 30 || true
    log "mail LXC stopped"
}

cmd_restart() {
    cmd_stop
    sleep 2
    cmd_start
}

cmd_status() {
    echo ""
    echo "========================================"
    echo "  SecuBox Mail Server v$VERSION"
    echo "========================================"
    echo ""

    echo "Configuration:"
    echo "  Domain:      $DOMAIN"
    echo "  Hostname:    $HOSTNAME.$DOMAIN"
    echo "  Mail IP:     $LXC_IP"
    echo ""

    # Mail server status
    echo "Mail Server ($CONTAINER):"
    if lxc_running "$CONTAINER"; then
        echo -e "  Status:    ${GREEN}Running${NC}"
        # Check ports
        local ports=$(lxc_attach "$CONTAINER" netstat -tln 2>/dev/null)
        for port in 25 587 465 993 995; do
            if echo "$ports" | grep -q ":$port "; then
                echo -e "  Port $port:  ${GREEN}listening${NC}"
            else
                echo -e "  Port $port:  ${RED}closed${NC}"
            fi
        done
    elif lxc_exists "$CONTAINER"; then
        echo -e "  Status:    ${YELLOW}Stopped${NC}"
    else
        echo -e "  Status:    ${RED}Not installed${NC}"
    fi
    echo ""

    # Webmail status
    echo "Webmail ($WEBMAIL_CONTAINER):"
    if lxc_running "$WEBMAIL_CONTAINER"; then
        echo -e "  Status:    ${GREEN}Running${NC}"
        echo "  Port:      $WEBMAIL_PORT"
    elif lxc_exists "$WEBMAIL_CONTAINER"; then
        echo -e "  Status:    ${YELLOW}Stopped${NC}"
    else
        echo -e "  Status:    ${RED}Not installed${NC}"
    fi
    echo ""

    # User count
    local users_file="$DATA_PATH/config/users"
    if [ -f "$users_file" ]; then
        local user_count=$(wc -l < "$users_file")
        echo "Users:       $user_count"
    fi

    # Storage
    if [ -d "$DATA_PATH/mail" ]; then
        local storage=$(du -sh "$DATA_PATH/mail" 2>/dev/null | cut -f1)
        echo "Storage:     ${storage:-0}"
    fi
    echo ""
}

# ============================================================================
# User Management
# ============================================================================

cmd_sync() {
    # Phase 1 rev. 2: persistent config is bind-mounted from
    # $DATA_PATH/config into $LXC_PATH/$CONTAINER/rootfs/etc/mail-config,
    # so there is no copy step. Rebuild Postfix LMDB indexes if the
    # container is running; otherwise it's a no-op until next start.
    if lxc_running "$CONTAINER"; then
        for map in vmailbox virtual; do
            lxc_attach "$CONTAINER" postmap "lmdb:/etc/mail-config/$map" 2>/dev/null || true
        done
    fi
}

cmd_user() {
    local action="${1:-list}"
    shift

    case "$action" in
        add)
            local email="$1"
            local password="$2"
            [ -z "$email" ] && { echo "Usage: mailctl user add <email> [password]"; return 1; }

            if [ -z "$password" ]; then
                read -s -p "Password: " password
                echo ""
            fi

            user_add "$email" "$password"
            cmd_sync
            ;;
        del|delete|remove)
            local email="$1"
            [ -z "$email" ] && { echo "Usage: mailctl user del <email>"; return 1; }
            user_del "$email"
            cmd_sync
            ;;
        passwd|password)
            local email="$1"
            local password="$2"
            [ -z "$email" ] && { echo "Usage: mailctl user passwd <email> [password]"; return 1; }

            if [ -z "$password" ]; then
                read -s -p "New password: " password
                echo ""
            fi

            user_passwd "$email" "$password"
            cmd_sync
            ;;
        list)
            user_list
            ;;
        *)
            echo "User commands:"
            echo "  user add <email> [pass]   Add mail user"
            echo "  user del <email>          Delete mail user"
            echo "  user list                 List all users"
            echo "  user passwd <email>       Change password"
            ;;
    esac
}

cmd_alias() {
    local action="${1:-list}"
    shift

    case "$action" in
        add)
            alias_add "$@"
            cmd_sync
            ;;
        del|delete)
            alias_del "$@"
            cmd_sync
            ;;
        list)
            alias_list
            ;;
        *)
            echo "Alias commands:"
            echo "  alias add <alias> <target>  Add email alias"
            echo "  alias del <alias>           Delete email alias"
            echo "  alias list                  List aliases"
            ;;
    esac
}

# ============================================================================
# Migration from OpenWrt (192.168.255.1)
# ============================================================================

cmd_migrate() {
    local source="${1:-192.168.255.1}"

    log "Migrating mail data from $source..."

    # Check SSH connectivity
    if ! ssh -o ConnectTimeout=5 "root@$source" "echo ok" >/dev/null 2>&1; then
        error "Cannot connect to $source via SSH"
        echo "Ensure SSH key is configured: ssh-copy-id root@$source"
        return 1
    fi

    # Create backup directory
    local backup_dir="$DATA_PATH/migration_$(date +%Y%m%d_%H%M%S)"
    mkdir -p "$backup_dir"

    # Migrate mail data
    log "Migrating mailboxes..."
    rsync -avz --progress "root@$source:/srv/mailserver/mail/" "$DATA_PATH/mail/"

    # Migrate config (users, aliases)
    log "Migrating configuration..."
    rsync -avz --progress "root@$source:/srv/mailserver/config/" "$DATA_PATH/config/"

    # Migrate SSL certificates
    log "Migrating SSL certificates..."
    rsync -avz --progress "root@$source:/srv/mailserver/ssl/" "$DATA_PATH/ssl/"

    # Import UCI config
    log "Importing UCI configuration..."
    ssh "root@$source" "uci show mailserver" > "$backup_dir/mailserver.uci" 2>/dev/null || true

    # Convert UCI to TOML
    if [ -f "$backup_dir/mailserver.uci" ]; then
        local uci_domain=$(grep "main.domain=" "$backup_dir/mailserver.uci" | cut -d"'" -f2)
        local uci_hostname=$(grep "main.hostname=" "$backup_dir/mailserver.uci" | cut -d"'" -f2)

        if [ -n "$uci_domain" ]; then
            log "Setting domain: $uci_domain"
            sed -i "s/^domain = .*/domain = \"$uci_domain\"/" "$CONFIG_FILE" 2>/dev/null || \
                echo "domain = \"$uci_domain\"" >> "$CONFIG_FILE"
        fi

        if [ -n "$uci_hostname" ]; then
            log "Setting hostname: $uci_hostname"
            sed -i "s/^hostname = .*/hostname = \"$uci_hostname\"/" "$CONFIG_FILE" 2>/dev/null || \
                echo "hostname = \"$uci_hostname\"" >> "$CONFIG_FILE"
        fi
    fi

    log "Migration complete!"
    log "Data backed up to: $backup_dir"
    log "Restart services: systemctl restart secubox-mail"
}

# ============================================================================
# Backup / Restore
# ============================================================================

cmd_backup() {
    local name="${1:-$(date +%Y%m%d_%H%M%S)}"
    local backup_file="$DATA_PATH/backups/mail_$name.tar.gz"

    log "Creating backup: $backup_file"

    mkdir -p "$DATA_PATH/backups"

    tar -czf "$backup_file" \
        -C "$DATA_PATH" \
        mail config ssl \
        2>/dev/null

    log "Backup created: $backup_file"
    echo "$backup_file"
}

cmd_restore() {
    local backup_file="$1"

    if [ -z "$backup_file" ] || [ ! -f "$backup_file" ]; then
        echo "Usage: mailctl restore <backup_file>"
        echo ""
        echo "Available backups:"
        ls -la "$DATA_PATH/backups/"*.tar.gz 2>/dev/null || echo "  No backups found"
        return 1
    fi

    warn "This will overwrite current mail data!"
    read -p "Continue? (yes/no): " confirm
    [ "$confirm" != "yes" ] && { echo "Aborted"; return 1; }

    log "Stopping services..."
    cmd_stop

    log "Restoring from: $backup_file"
    tar -xzf "$backup_file" -C "$DATA_PATH"

    log "Starting services..."
    cmd_start

    log "Restore complete!"
}

# ============================================================================
# SSL
# ============================================================================

cmd_ssl() {
    local action="${1:-status}"
    shift

    case "$action" in
        status)
            if [ -f "$DATA_PATH/ssl/fullchain.pem" ]; then
                echo "SSL Certificate:"
                openssl x509 -in "$DATA_PATH/ssl/fullchain.pem" -noout -subject -dates 2>/dev/null | sed 's/^/  /'
            else
                echo "No SSL certificate installed"
                echo "Use: mailctl ssl setup"
            fi
            ;;
        setup)
            local fqdn="$HOSTNAME.$DOMAIN"
            log "Setting up SSL for $fqdn..."

            if command -v certbot >/dev/null 2>&1; then
                certbot certonly --standalone -d "$fqdn" \
                    --cert-path "$DATA_PATH/ssl/fullchain.pem" \
                    --key-path "$DATA_PATH/ssl/privkey.pem"
            elif command -v acme.sh >/dev/null 2>&1; then
                acme.sh --issue -d "$fqdn" --standalone
                acme.sh --install-cert -d "$fqdn" \
                    --fullchain-file "$DATA_PATH/ssl/fullchain.pem" \
                    --key-file "$DATA_PATH/ssl/privkey.pem"
            else
                error "No ACME client found. Install certbot or acme.sh"
                return 1
            fi

            chmod 600 "$DATA_PATH/ssl/"*.pem
            log "SSL certificate installed"
            cmd_restart
            ;;
        *)
            echo "SSL commands:"
            echo "  ssl status   Show certificate info"
            echo "  ssl setup    Obtain Let's Encrypt certificate"
            ;;
    esac
}

# ============================================================================
# DKIM
# ============================================================================

cmd_dkim() {
    local action="${1:-status}"
    shift

    case "$action" in
        setup|generate)
            # OpenDKIM setup is deferred to Phase 2 (Rspamd replaces it).
            # Phase 1 stub: tell the user where to look.
            warn "DKIM setup will move to Rspamd in Phase 2."
            warn "Phase 1: configure DKIM manually inside the LXC if needed."
            ;;
        status)
            if [ -f "$DATA_PATH/dkim/default.txt" ]; then
                log "DKIM key exists"
                cat "$DATA_PATH/dkim/default.txt"
            else
                warn "DKIM not configured. Run: mailctl dkim setup"
            fi
            ;;
        *)
            echo "DKIM commands:"
            echo "  dkim setup    Generate DKIM keys"
            echo "  dkim status   Show DKIM DNS record"
            ;;
    esac
}

# ============================================================================
# Logs
# ============================================================================

cmd_logs() {
    local lines="${1:-50}"

    if lxc_running "$CONTAINER"; then
        lxc_attach "$CONTAINER" tail -n "$lines" /var/log/mail.log 2>/dev/null
    else
        error "Mail container not running"
    fi
}

# ============================================================================
# Help
# ============================================================================

show_help() {
    cat << EOF
SecuBox Mail Server v$VERSION
Three-fold architecture: Components, Status, Access

Usage: mailctl <command> [options]

Information (Three-fold):
  components           List system components (JSON)
  status               Show service status
  access               Show connection info (JSON)

Setup:
  install              Install mail server + webmail
  uninstall            Remove mail server
  migrate [host]       Migrate data from OpenWrt (default: 192.168.255.1)

Service:
  start                Start mail services
  stop                 Stop mail services
  restart              Restart mail services

Users:
  user add <email>     Add mail user
  user del <email>     Delete mail user
  user list            List all users
  user passwd <email>  Change password
  user-repair <email>  Repair user mailbox

Aliases:
  alias add <a> <t>    Add email alias
  alias del <alias>    Delete alias
  alias list           List aliases

Backup:
  backup [name]        Create backup
  restore <file>       Restore from backup

SSL & DNS:
  ssl status           Show certificate info
  ssl setup            Obtain Let's Encrypt certificate
  dns-setup            Show DNS records to configure

Diagnostics:
  logs [lines]         View mail logs
  fix-ports            Check and fix listening ports

Examples:
  mailctl install
  mailctl components                 # List what's installed
  mailctl access                     # Show connection details
  mailctl user add admin@example.com
  mailctl migrate 192.168.255.1
  mailctl dns-setup                  # Show DNS records

EOF
}

# ============================================================================
# Phase 1 config migration (rev. 2)
# ============================================================================

cmd_migrate_config() {
    [ "$(id -u)" -eq 0 ] || { error "Root required"; return 1; }
    : "${LIB_DIR:=/usr/lib/secubox/mail/lib}"
    # Installed layout: /usr/lib/secubox/mail/lib/migrate.sh
    # In-tree layout:   packages/secubox-mail/lib/mail/migrate.sh
    if [ ! -f "$LIB_DIR/migrate.sh" ]; then
        local alt="$(dirname "$0")/../lib/mail"
        [ -f "$alt/migrate.sh" ] && LIB_DIR="$alt"
    fi
    # shellcheck source=/dev/null
    source "$LIB_DIR/migrate.sh"

    local cfg="${CONFIG_FILE:-/etc/secubox/mail.toml}"
    [ -f "$cfg" ] || { warn "no config to migrate at $cfg"; return 0; }

    if grep -q "^container *=" "$cfg" 2>/dev/null; then
        log "config already migrated (has 'container =' key)"
        return 0
    fi

    if ! detect_legacy_toml_keys "$cfg" >/dev/null; then
        log "no legacy keys to migrate"
        return 0
    fi

    local backup="${cfg}.pre-phase1.$(date +%s).bak"
    cp "$cfg" "$backup"
    log "backup written to $backup"

    python3 - "$cfg" <<'PY'
import sys, re
path = sys.argv[1]
src = open(path).read()
inject = (
    'container = "mail"\n'
    'lxc_ip = "10.100.0.10"\n'
    'lxc_bridge = "br-lxc"\n'
    'lxc_gateway = "10.100.0.1"\n'
    'data_path = "/data/volumes/mail"\n'
    'lxc_path = "/var/lib/lxc"\n'
)
# Comment out legacy keys FIRST so we don't end up with duplicates of
# data_path / lxc_path after injection.
for k in ("mail_container", "webmail_container", "mail_ip", "webmail_ip",
         "webmail_port", "data_path", "lxc_path"):
    src = re.sub(rf"^({k} *=.*)$", r"# DEPRECATED Phase 1: \1", src, flags=re.MULTILINE)
src = re.sub(r"(\[mail\]\n)", r"\1" + inject, src, count=1)
open(path, "w").write(src)
PY
    log "config migrated to single-container schema"
}

# ============================================================================
# Phase 2 — Rspamd subcommand
# ============================================================================

cmd_rspamd() {
    [ "$(id -u)" -eq 0 ] || { error "Root required"; return 1; }
    : "${LIB_DIR:=/usr/lib/secubox/mail/lib}"
    [ -f "$LIB_DIR/rspamd.sh" ] || LIB_DIR="$(dirname "$0")/../lib/mail"
    # shellcheck source=/dev/null
    source "$LIB_DIR/rspamd.sh"

    local sub="${1:-status}"
    shift || true
    case "$sub" in
        install)
            LXC_BASE="$LXC_PATH" install_rspamd "$CONTAINER"
            LXC_BASE="$LXC_PATH" configure_rspamd_milter "$CONTAINER"
            LXC_BASE="$LXC_PATH" configure_rspamd_controller "$CONTAINER"
            LXC_BASE="$LXC_PATH" configure_rspamd_dkim "$CONTAINER" "$DOMAIN" "default"
            LXC_BASE="$LXC_PATH" configure_rspamd_postfix_milter "$CONTAINER"
            log "Rspamd installed. Start with: mailctl rspamd start"
            ;;
        start|restart)
            lxc-attach -n "$CONTAINER" -- systemctl restart rspamd
            ;;
        stop)
            lxc-attach -n "$CONTAINER" -- systemctl stop rspamd
            ;;
        reload)
            lxc-attach -n "$CONTAINER" -- systemctl reload rspamd
            ;;
        status)
            lxc-attach -n "$CONTAINER" -- rspamc stat 2>&1 | head -40
            ;;
        dkim-keygen)
            local domain="${1:-$DOMAIN}"
            local sel="${2:-default}"
            # Delegate to the lib function — runs rspamadm inside the LXC and
            # resolves _rspamd uid via kernel idmap (image-agnostic).
            LXC_BASE="$LXC_PATH" DATA_PATH="$DATA_PATH" \
                rspamd_keygen "$CONTAINER" "$domain" "$sel"
            log "DKIM keypair generated for $domain (selector $sel)"
            ;;
        dns-records)
            local domain="${1:-$DOMAIN}"
            local sel="${2:-default}"
            cat "$DATA_PATH/rspamd/dkim/$domain/$sel.txt" 2>/dev/null \
                || error "no DNS record for $domain/$sel"
            ;;
        learn-spam)
            local target="${1:-}"
            [ -n "$target" ] || { echo "Usage: mailctl rspamd learn-spam <maildir-or-file>"; return 1; }
            lxc-attach -n "$CONTAINER" -- rspamc learn_spam "$target"
            ;;
        learn-ham)
            local target="${1:-}"
            [ -n "$target" ] || { echo "Usage: mailctl rspamd learn-ham <maildir-or-file>"; return 1; }
            lxc-attach -n "$CONTAINER" -- rspamc learn_ham "$target"
            ;;
        purge-legacy)
            LXC_BASE="$LXC_PATH" rspamd_purge_legacy "$CONTAINER"
            ;;
        *)
            cat <<USAGE
Usage:
  mailctl rspamd install
  mailctl rspamd start | stop | restart | reload
  mailctl rspamd status
  mailctl rspamd dkim-keygen [<domain>] [<selector>]
  mailctl rspamd dns-records [<domain>] [<selector>]
  mailctl rspamd learn-spam <maildir-or-file>
  mailctl rspamd learn-ham  <maildir-or-file>
  mailctl rspamd purge-legacy            # purge SA/OpenDKIM after Rspamd verified
USAGE
            ;;
    esac
}

# ============================================================================
# Main
# ============================================================================

case "${1:-}" in
    # Three-fold architecture
    components)  cmd_components ;;
    access)      cmd_access ;;
    status)      shift; cmd_status "$@" ;;
    # Setup
    install)     shift; cmd_install "$@" ;;
    uninstall)   shift; cmd_uninstall "$@" ;;
    migrate)     shift; cmd_migrate "$@" ;;
    migrate-config) shift; cmd_migrate_config "$@" ;;
    # Phase 2 — Rspamd
    rspamd)      shift; cmd_rspamd "$@" ;;
    # Service control
    start)       shift; cmd_start "$@" ;;
    stop)        shift; cmd_stop "$@" ;;
    restart)     shift; cmd_restart "$@" ;;
    # Users and aliases
    user)        shift; cmd_user "$@" ;;
    user-repair) shift; cmd_user_repair "$@" ;;
    alias)       shift; cmd_alias "$@" ;;
    # Backup
    backup)      shift; cmd_backup "$@" ;;
    restore)     shift; cmd_restore "$@" ;;
    # SSL, DNS, DKIM
    ssl)         shift; cmd_ssl "$@" ;;
    dkim)        shift; cmd_dkim "$@" ;;
    dns-setup)   cmd_dns_setup ;;
    # Diagnostics
    logs)        shift; cmd_logs "$@" ;;
    fix-ports)   cmd_fix_ports ;;
    sync)        cmd_sync ;;
    # Help
    help|--help|-h|'') show_help ;;
    *)           error "Unknown command: $1"; show_help >&2; exit 1 ;;
esac

exit 0
