from __future__ import annotations

import glob
import os
import re
import subprocess
from logger import get_logger

log = get_logger("actions.logs")

ALLOWED_LOG_TYPES = {"nginx_access", "nginx_error", "php", "system"}


def handle_log_read(payload: dict) -> dict:
    """Read the last N lines of log files safely."""
    try:
        log_type = payload.get("log_type")
        if not log_type or log_type not in ALLOWED_LOG_TYPES:
            return {
                "success": False,
                "error": f"Invalid log type: {log_type}"
            }

        domain = payload.get("domain", "")
        # Sanitize domain: allow only alphanumeric, dots and hyphens
        if domain:
            domain = re.sub(r"[^a-zA-Z0-9.-]", "", domain)
            # If domain became empty after sanitization, or still fails regex
            if not domain or not re.match(r"^[a-zA-Z0-9.-]+$", domain):
                return {
                    "success": False,
                    "error": "Invalid domain name format"
                }

        lines_raw = payload.get("lines", 200)
        try:
            lines = int(lines_raw)
        except (ValueError, TypeError):
            lines = 200

        # Enforce limits: min 1, max 1000
        if lines < 1:
            lines = 200
        elif lines > 1000:
            lines = 1000

        # Determine log source path/command
        path = None
        cmd = None

        if log_type == "nginx_access":
            if domain:
                path = f"/var/log/nginx/{domain}.access.log"
            else:
                path = "/var/log/nginx/access.log"
        elif log_type == "nginx_error":
            if domain:
                path = f"/var/log/nginx/{domain}.error.log"
            else:
                path = "/var/log/nginx/error.log"
        elif log_type == "php":
            # Scan common PHP paths using glob
            php_files = glob.glob("/var/log/php*-fpm.log") + glob.glob("/var/log/php*.log")
            if php_files:
                path = php_files[0]
            else:
                path = "/var/log/php-fpm.log"  # fallback path
        elif log_type == "system":
            cmd = ["journalctl", "-n", str(lines), "--no-pager"]

        # Run command to fetch lines
        ret_lines: list[str] = []
        if cmd:
            try:
                res = subprocess.run(
                    cmd,
                    capture_output=True,
                    text=True,
                    errors="ignore",
                    shell=False,
                    check=False
                )
                if res.returncode == 0:
                    ret_lines = res.stdout.splitlines()
                else:
                    log.warning("System log command failed with code %d: %s", res.returncode, res.stderr)
            except Exception as e:
                log.error("Failed to run system log command: %s", e)
        elif path:
            # Check if file exists
            if os.path.exists(path) and os.path.isfile(path):
                try:
                    res = subprocess.run(
                        ["tail", "-n", str(lines), path],
                        capture_output=True,
                        text=True,
                        errors="ignore",
                        shell=False,
                        check=False
                    )
                    if res.returncode == 0:
                        ret_lines = res.stdout.splitlines()
                    else:
                        log.warning("Tail command failed with code %d: %s", res.returncode, res.stderr)
                except Exception as e:
                    log.error("Failed to tail log file %s: %s", path, e)
            else:
                # If file doesn't exist, return empty list without error
                log.info("Log file does not exist: %s", path)
                ret_lines = []

        return {
            "success": True,
            "lines": ret_lines,
            "log_type": log_type,
            "path": path or "journald"
        }

    except Exception as exc:
        log.error("Log read exception: %s", exc)
        return {
            "success": False,
            "error": str(exc)
        }
