# services/audit_service.py
import os
import json
from pathlib import Path
from typing import List, Optional, Dict, Any
from datetime import datetime

BACKEND_DIR = Path(__file__).resolve().parents[1]
DATA_DIR = Path(os.getenv("VITU_DATA_DIR", BACKEND_DIR / "data"))

AUDIT_FILE = DATA_DIR / "audit_log.jsonl"

def _parse_line(line: str) -> Optional[Dict[str, Any]]:
    try:
        obj = json.loads(line)
        if not isinstance(obj, dict):
            return None
        return obj
    except Exception:
        return None

def _date_in_range(d: str, frm: Optional[str], to: Optional[str]) -> bool:
    """d, frm, to are YYYY-MM-DD strings (frm/to can be None)."""
    try:
        ddt = datetime.strptime(d, "%Y-%m-%d").date()
    except Exception:
        return False
    if frm:
        try:
            if ddt < datetime.strptime(frm, "%Y-%m-%d").date():
                return False
        except Exception:
            pass
    if to:
        try:
            if ddt > datetime.strptime(to, "%Y-%m-%d").date():
                return False
        except Exception:
            pass
    return True

def read_audit_range(frm: Optional[str], to: Optional[str]) -> List[Dict[str, Any]]:
    """
    Read audit_log.jsonl and return ONLY the trimmed columns:
      Date | Run ID | Started | Ended | Received | Processed | Failed

    Each line in audit_log.jsonl is expected to contain (at least):
      {
        "date": "YYYY-MM-DD",
        "run_id": "20250818-090000",
        "started": "2025-08-18T09:00:00",
        "ended": "2025-08-18T09:20:30",
        "received": 20,
        "processed": 18,
        "failed": 2,

        # other keys may be present (trigger, initiated_by, status, notes) but will be ignored
      }
    """
    rows: List[Dict[str, Any]] = []
    if not AUDIT_FILE.exists():
        return rows

    with AUDIT_FILE.open("r", encoding="utf-8") as f:
        for line in f:
            obj = _parse_line(line.strip())
            if not obj:
                continue

            d = str(obj.get("date", "")).strip()
            if not d:
                continue
            if not _date_in_range(d, frm, to):
                continue

            # Trim to the 7 required columns
            row = {
                "date": d,
                "run_id": str(obj.get("run_id", "")),
                "started": str(obj.get("started", "")),
                "ended": str(obj.get("ended", "")),
                "received": int(obj.get("received", 0) or 0),
                "processed": int(obj.get("processed", 0) or 0),
                "failed": int(obj.get("failed", 0) or 0),
            }
            rows.append(row)

    # Sort newest first (optional)
    rows.sort(key=lambda r: (r.get("date", ""), r.get("run_id", "")), reverse=True)
    return rows
