"""Core logic for the ``mld logs`` command.

Reads and tails log files written by ``mld dev`` in ``.mld/logs/``.
"""

from __future__ import annotations

import argparse
import sys
import time
from pathlib import Path

LOG_DIR_NAME = ".mld/logs"


def _find_log_dir(project_dir: Path) -> Path | None:
    """Locate the .mld/logs directory."""
    log_dir = project_dir / LOG_DIR_NAME
    return log_dir if log_dir.is_dir() else None


def _list_logs(log_dir: Path, filter_name: str | None = None) -> list[Path]:
    """List log files, optionally filtered by process name."""
    logs = sorted(log_dir.glob("*.log"))
    if filter_name:
        needle = filter_name.lower().replace(" ", "-")
        logs = [f for f in logs if needle in f.stem.lower()]
    return logs


def _tail_lines(path: Path, n: int) -> list[str]:
    """Read the last *n* lines from a file."""
    try:
        lines = path.read_text().splitlines()
    except OSError:
        return []
    return lines[-n:] if n > 0 else lines


def _follow(log_files: list[Path]) -> None:
    """Tail log files continuously until interrupted."""
    positions: dict[Path, int] = {}
    for lf in log_files:
        try:
            positions[lf] = lf.stat().st_size
        except OSError:
            positions[lf] = 0

    # Print marker
    print("Following logs (Ctrl+C to stop)...\n")

    try:
        while True:
            for lf in log_files:
                try:
                    size = lf.stat().st_size
                except OSError:
                    continue
                if size > positions[lf]:
                    with open(lf) as f:
                        f.seek(positions[lf])
                        new_content = f.read()
                    label = lf.stem
                    for line in new_content.splitlines():
                        print(f"[{label}] {line}")
                    positions[lf] = size
            time.sleep(0.3)
    except KeyboardInterrupt:
        print()


def cmd_logs(args: argparse.Namespace) -> None:
    """Execute the ``mld logs`` command."""
    project_dir = Path.cwd()
    log_dir = _find_log_dir(project_dir)

    if log_dir is None:
        print(
            "No logs found. Run 'mld dev' first to generate log files in .mld/logs/.",
            file=sys.stderr,
        )
        sys.exit(1)

    filter_name = getattr(args, "process", None)

    # --clear: remove log files
    if getattr(args, "clear", False):
        log_files = _list_logs(log_dir)
        for lf in log_files:
            lf.unlink(missing_ok=True)
        print(f"Cleared {len(log_files)} log file(s).")
        return

    # --list: show available log files
    if getattr(args, "list_logs", False):
        log_files = _list_logs(log_dir, filter_name)
        if not log_files:
            print("No log files found.")
            return
        for lf in log_files:
            try:
                size = lf.stat().st_size
                lines = len(lf.read_text().splitlines())
            except OSError:
                size = 0
                lines = 0
            print(f"  {lf.stem:30s}  {lines:>6} lines  ({size:>8} bytes)")
        return

    log_files = _list_logs(log_dir, filter_name)
    if not log_files:
        if filter_name:
            all_logs = _list_logs(log_dir)
            names = ", ".join(lf.stem for lf in all_logs)
            print(f"No logs matching '{filter_name}'. Available: {names}", file=sys.stderr)
        else:
            print("No log files found.", file=sys.stderr)
        sys.exit(1)

    # --follow: tail logs continuously
    if getattr(args, "follow", False):
        _follow(log_files)
        return

    # Default: show last N lines from each log file
    n = getattr(args, "lines", 50)
    for lf in log_files:
        label = lf.stem
        lines = _tail_lines(lf, n)
        if lines:
            print(f"--- {label} (last {len(lines)} lines) ---")
            for line in lines:
                print(line)
            print()
