from __future__ import annotations

import time

from django.core.management.base import BaseCommand

from core.events.behavior import summarize_metrics
from core.events.manticore import get_event_ledger_backend
from core.util import logs

log = logs.get_logger("gia_analysis")


class Command(BaseCommand):
    help = "Compute behavioral metrics from Manticore event rows into gia_metrics."

    def add_arguments(self, parser):
        parser.add_argument("--once", action="store_true", default=False)
        parser.add_argument("--user-id", type=int)
        parser.add_argument("--person-id")
        parser.add_argument("--sleep-seconds", type=float, default=60.0)
        parser.add_argument("--window-days", nargs="*", type=int, default=[1, 7, 30, 90])

    def _run_cycle(
        self,
        *,
        user_id: int | None = None,
        person_id: str = "",
        window_days: list[int] | None = None,
    ) -> int:
        backend = get_event_ledger_backend()
        now_ms = int(time.time() * 1000)
        baseline_since = now_ms - (90 * 86400000)
        windows = sorted({max(1, int(value)) for value in list(window_days or [1, 7, 30, 90])})

        targets = backend.list_event_targets(user_id=user_id)
        if person_id:
            targets = [
                row
                for row in targets
                if str(row.get("person_id") or "").strip() == str(person_id).strip()
            ]

        written = 0
        for target in targets:
            target_user_id = int(target.get("user_id") or 0)
            target_person_id = str(target.get("person_id") or "").strip()
            if target_user_id <= 0 or not target_person_id:
                continue
            baseline_rows = backend.fetch_events(
                user_id=target_user_id,
                person_id=target_person_id,
                since_ts=baseline_since,
            )
            if not baseline_rows:
                continue
            for window in windows:
                since_ts = now_ms - (int(window) * 86400000)
                window_rows = [
                    row
                    for row in baseline_rows
                    if int(row.get("ts") or 0) >= since_ts
                ]
                metrics = summarize_metrics(window_rows, baseline_rows)
                for metric, values in metrics.items():
                    backend.upsert_metric(
                        user_id=target_user_id,
                        person_id=target_person_id,
                        window_days=int(window),
                        metric=metric,
                        value_ms=int(values.get("value_ms") or 0),
                        baseline_ms=int(values.get("baseline_ms") or 0),
                        z_score=float(values.get("z_score") or 0.0),
                        sample_n=int(values.get("sample_n") or 0),
                        computed_at=now_ms,
                    )
                    written += 1
        return written

    def handle(self, *args, **options):
        once = bool(options.get("once"))
        sleep_seconds = max(1.0, float(options.get("sleep_seconds") or 60.0))
        user_id = options.get("user_id")
        person_id = str(options.get("person_id") or "").strip()
        window_days = list(options.get("window_days") or [1, 7, 30, 90])

        while True:
            written = self._run_cycle(
                user_id=user_id,
                person_id=person_id,
                window_days=window_days,
            )
            self.stdout.write(f"gia-analysis wrote={written}")
            if once:
                return
            time.sleep(sleep_seconds)
