from __future__ import annotations

import argparse
import json
import sys
from datetime import datetime, timezone
from pathlib import Path
from zoneinfo import ZoneInfo

import audit_latest_consultation as audit


ROOT = Path(__file__).resolve().parents[1]
WORKSPACE = ROOT.parent
DEFAULT_DATA_DIR = WORKSPACE / "medical-tools-extension-data" / "consultations"
DEFAULT_TIMEZONE = "Europe/Kiev"


def main() -> int:
    parser = argparse.ArgumentParser(
        description="List recent Parallax Health consultation QA summaries without PHI."
    )
    parser.add_argument("--data-dir", default=str(DEFAULT_DATA_DIR), help="Consultations data directory.")
    parser.add_argument("--limit", type=int, default=10, help="Number of recent sessions to list.")
    parser.add_argument("--timezone", default=DEFAULT_TIMEZONE, help="Timezone for local start/finish times.")
    parser.add_argument("--json", action="store_true", help="Print machine-readable JSON.")
    args = parser.parse_args()

    data_dir = Path(args.data_dir).expanduser()
    rows = build_rows(data_dir, max(1, args.limit), args.timezone)
    if args.json:
      print(json.dumps(rows, ensure_ascii=False, indent=2))
    else:
      print(format_table(rows, args.timezone))
    return 0


def build_rows(data_dir: Path, limit: int, timezone_name: str) -> list[dict]:
    if not data_dir.is_dir():
        return []
    tz = ZoneInfo(timezone_name)
    session_dirs = [path for path in data_dir.iterdir() if path.is_dir()]
    session_dirs.sort(key=audit.latest_mtime, reverse=True)
    rows: list[dict] = []
    for session_dir in session_dirs[:limit]:
        report = audit.build_report(session_dir)
        started = local_time(report.get("startedAt"), tz)
        finished = local_time(report.get("finishedAt"), tz)
        mime_types = report.get("mimeTypes") or {}
        rows.append({
            "sessionId": report["sessionId"],
            "verdict": report["verdict"],
            "technicalVerdict": report.get("technicalVerdict", report["verdict"]),
            "clinicalVerdict": report.get("clinicalVerdict", ""),
            "clinicalState": report.get("clinicalState", ""),
            "source": compact_source_label(report.get("sessionSource")),
            "startedLocal": started,
            "finishedLocal": finished,
            "duration": duration_label(report.get("startedAt"), report.get("finishedAt")),
            "chunks": report["chunkCount"],
            "done": report["doneChunkCount"],
            "errors": report["errorChunkCount"],
            "pending": report["pendingChunkCount"],
            "rawWhisper": report.get("rawWhisperSegmentCount", 0),
            "discardedWhisper": report.get("discardedWhisperSegmentCount", 0),
            "segments": report["segmentCount"],
            "draftEligible": report["draftEligibleSegmentCount"],
            "draftFields": report["draftFieldsWithText"],
            "mime": compact_mime_label(mime_types),
            "client": compact_client_label(report),
            "technicalState": classify_technical_state(report),
            "operatorAction": report.get("operatorAction", ""),
        })
    return rows


def local_time(value: object, tz: ZoneInfo) -> str:
    parsed = audit.parse_iso_datetime(value, tz)
    if not parsed:
        return "-"
    return parsed.strftime("%Y-%m-%d %H:%M")


def duration_label(started: object, finished: object) -> str:
    start_dt = audit.parse_iso_datetime(started, timezone.utc)
    finish_dt = audit.parse_iso_datetime(finished, timezone.utc)
    if not start_dt or not finish_dt:
        return "-"
    seconds = max(0, int((finish_dt - start_dt).total_seconds()))
    minutes, seconds = divmod(seconds, 60)
    if minutes >= 60:
        hours, minutes = divmod(minutes, 60)
        return f"{hours}h{minutes:02d}m"
    return f"{minutes}m{seconds:02d}s"


def compact_mime_label(mime_types: dict) -> str:
    labels = []
    for key, count in sorted(mime_types.items()):
        key_lower = str(key).lower()
        if "wav" in key_lower:
            label = "wav"
        elif "webm" in key_lower:
            label = "webm"
        elif not key:
            label = "unknown"
        else:
            label = str(key).split(";")[0].replace("audio/", "").replace("video/", "")
        labels.append(f"{label}:{count}")
    return ",".join(labels) or "-"


def compact_client_label(report: dict) -> str:
    version = str(report.get("clientExtensionVersion") or "").strip()
    policy = str(report.get("clientLiveChunkPolicy") or "").strip()
    pipeline = str(report.get("clientAudioPipeline") or "").strip()
    if version or policy:
        return "/".join(item for item in (version, policy) if item) or "-"
    if pipeline:
        return pipeline
    return "-"


def classify_technical_state(report: dict) -> str:
    if report["errorChunkCount"]:
        return "chunk_errors"
    mime_types = report.get("mimeTypes") or {}
    if any("webm" in str(key).lower() for key in mime_types):
        return "legacy_webm"
    if report["chunkCount"] and report["doneChunkCount"] == report["chunkCount"]:
        if not report["transcriptBytes"] and int(report.get("discardedWhisperSegmentCount") or 0) > 0:
            return "filtered_noise_only"
        if report.get("educationalContent") or report.get("draftEmptyReason") == "educational_content":
            return "educational_no_lakmus_fields"
        if report["transcriptBytes"] and report["draftEligibleSegmentCount"] == 0:
            return "transcript_no_lakmus_fields"
        return "processed"
    if report["pendingChunkCount"]:
        return "pending"
    return "check_needed"


def format_table(rows: list[dict], timezone_name: str) -> str:
    lines = [
        "Parallax Health recent consultation QA index",
        "privacy: no audio, no transcript text, no Lakmus field text, no license key",
        f"checkedAt: {datetime.now(timezone.utc).replace(microsecond=0).isoformat()}",
        f"timezone: {timezone_name}",
        "",
    ]
    if not rows:
        lines.append("No consultation sessions found.")
        return "\n".join(lines) + "\n"

    headers = [
        "verdict",
        "tech",
        "clinical",
        "source",
        "finished",
        "duration",
        "chunks",
        "errors",
        "pending",
        "segments",
        "draft",
        "mime",
        "client",
        "state",
        "action",
        "sessionId",
    ]
    data_rows = []
    for row in rows:
        data_rows.append([
            row["verdict"],
            row["technicalVerdict"],
            clinical_label(row),
            row["source"],
            row["finishedLocal"],
            row["duration"],
            str(row["chunks"]),
            str(row["errors"]),
            str(row["pending"]),
            str(row["segments"]),
            f"{row['draftEligible']}/{row['draftFields']}",
            row["mime"],
            row["client"],
            row["technicalState"],
            action_label(row),
            row["sessionId"],
        ])
    widths = [
        max(len(headers[index]), *(len(item[index]) for item in data_rows))
        for index in range(len(headers))
    ]
    lines.append("  ".join(headers[index].ljust(widths[index]) for index in range(len(headers))))
    lines.append("  ".join("-" * width for width in widths))
    for item in data_rows:
        lines.append("  ".join(item[index].ljust(widths[index]) for index in range(len(headers))))
    return "\n".join(lines) + "\n"


def clinical_label(row: dict) -> str:
    verdict = str(row.get("clinicalVerdict") or "-")
    state = str(row.get("clinicalState") or "")
    if state == "no_clinical_field_text":
        return "NONE/no_fields"
    if state == "fields_ready":
        return "PASS/fields"
    if state == "clinical_segments_without_fields":
        return "WARN/mapper"
    return verdict


def action_label(row: dict) -> str:
    action = str(row.get("operatorAction") or "")
    labels = {
        "technical_failure_do_not_rely_on_recording": "tech_fail",
        "review_technical_warnings_before_clinical_use": "review_tech",
        "review_mapper_fields_before_lakmus_fill": "review_fields",
        "recording_transcribed_no_lakmus_fields_expected": "no_fields_ok",
        "review_fields_then_fill_visible_lakmus": "fill_after_review",
        "recording_technical_path_ok": "tech_ok",
    }
    return labels.get(action, action or "-")


def compact_source_label(value: object) -> str:
    source = str(value or "").strip()
    labels = {
        "microphone": "mic",
        "readiness_microphone_test": "ready_test",
        "file_test": "file_test",
        "file_test_probe": "file_probe",
    }
    return labels.get(source, source or "-")


if __name__ == "__main__":
    sys.exit(main())
