#!/usr/bin/env python3
"""
Modem log collection unit:
- Move modem log directories/files into `mdlog_raw/`
- Move analysis outputs (`auto_analysis/` or `_analysis/`) into `mdlog_filter/`
"""

from __future__ import annotations

from dataclasses import dataclass
from pathlib import Path
from typing import Optional

from fs_utils import copy, ensure_dir, find_prefixed_ancestor, move
from log_patterns import PATTERNS, iter_mdlog_primary_dirs, looks_like_mdlog_dir
from workflow_layout import SessionLayout


@dataclass(frozen=True)
class MdlogCollector:
    layout: SessionLayout

    def collect(self, source_root: Path, session_root: Optional[Path] = None) -> None:
        source_root = source_root.resolve()
        session_root = (session_root or source_root).resolve()
        md_raw_dir = ensure_dir(session_root / self.layout.mdlog_raw)
        md_filter_dir = ensure_dir(session_root / self.layout.mdlog_filter)
        preserve_source = find_prefixed_ancestor(source_root, "input") is not None

        # 1) Move diag_logs/modem directories (pattern-based, no hardcoded names)
        for d in source_root.rglob("*"):
            if not d.is_dir():
                continue
            if not looks_like_mdlog_dir(d):
                continue
            if md_raw_dir in d.parents:
                continue
            try:
                if preserve_source:
                    copy(d, md_raw_dir)
                else:
                    move(d, md_raw_dir)
            except Exception:
                pass

        # 2) Move extra mdlog directories (if any)
        for g in PATTERNS.mdlog_extra_dir_globs:
            for p in list(source_root.glob(g)):
                if md_raw_dir in p.parents or p == md_raw_dir:
                    continue
                try:
                    staged_dir = copy(p, md_raw_dir) if preserve_source else move(p, md_raw_dir)
                    if staged_dir and staged_dir.exists():
                        for sub in staged_dir.rglob("_analysis"):
                            move(sub, md_filter_dir)
                except Exception:
                    pass

        # 3) Move parent dirs for primary mdlog files
        for parent in iter_mdlog_primary_dirs(source_root):
            if md_raw_dir in parent.parents or parent == md_raw_dir:
                continue
            if looks_like_mdlog_dir(parent) or any(looks_like_mdlog_dir(p) for p in parent.parents):
                continue
            try:
                if preserve_source:
                    copy(parent, md_raw_dir)
                else:
                    move(parent, md_raw_dir)
            except Exception:
                pass

    def move_analysis_outputs(self, session_root: Path) -> None:
        md_raw_dir = session_root / self.layout.mdlog_raw
        md_filter_dir = session_root / self.layout.mdlog_filter
        if not md_raw_dir.exists() or not md_filter_dir.exists():
            return
        for name in ("auto_analysis", "_analysis"):
            for d in sorted(md_raw_dir.rglob(name)):
                if not d.is_dir():
                    continue
                try:
                    move(d, md_filter_dir)
                except Exception:
                    pass
