"""
core/epoch/epoch_tier1_trigger.py

Story 9.08: EpochTier1Trigger — Autonomous Epistemic Updates Post-Epoch.

Always runs at the end of every epoch (regardless of PR outcome).
Uses EpochKnowledgeWriter for KG + Qdrant.
Uses Tier1AutonomousUpdater for prompt templates + rules.
Logs all updates to data/observability/tier1_updates.jsonl with source="nightly_epoch".

Design rules:
  - Never modifies .py files (Tier 1 = epistemic only).
  - Both EpochKnowledgeWriter AND Tier1AutonomousUpdater are always called.
  - OSError on log write is caught and logged — never surfaces to caller.

# VERIFICATION_STAMP
# Story: 9.08
# Verified By: parallel-builder
# Verified At: 2026-02-25T00:00:00Z
# Tests: 7/7
# Coverage: 100%
"""

from __future__ import annotations

import json
import logging
from dataclasses import dataclass
from datetime import datetime, timezone
from pathlib import Path
from typing import List

from core.epoch.axiom_distiller import Axiom
from core.epoch.epoch_knowledge_writer import EpochKnowledgeWriter
from core.evolution.meta_architect import ArchitectureAnalysis
from core.evolution.tier1_autonomous_updater import Tier1AutonomousUpdater

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Constants
# ---------------------------------------------------------------------------

TIER1_LOG_PATH: str = "data/observability/tier1_updates.jsonl"


# ---------------------------------------------------------------------------
# Result dataclass
# ---------------------------------------------------------------------------


@dataclass
class Tier1EpochResult:
    """Summary of a single EpochTier1Trigger.apply() run."""

    kg_axioms_written: int
    qdrant_scars_updated: int
    prompt_templates_updated: int
    rules_appended: int


# ---------------------------------------------------------------------------
# EpochTier1Trigger
# ---------------------------------------------------------------------------


class EpochTier1Trigger:
    """
    Applies Tier 1 epistemic updates post-epoch.

    Always runs regardless of whether a PR was opened.  The trigger
    orchestrates two sub-systems:

      1. EpochKnowledgeWriter — writes axioms to the KG JSONL file and
         Qdrant L3 (genesis_scars collection).
      2. Tier1AutonomousUpdater — applies prompt template and rules updates
         derived from the epoch's ArchitectureAnalysis.

    Every successful call appends one audit line to *log_path* (JSONL) with
    ``source="nightly_epoch"``.

    Parameters
    ----------
    knowledge_writer : EpochKnowledgeWriter
        Writes axioms to KG + Qdrant.
    tier1_updater : Tier1AutonomousUpdater
        Applies prompt template + rules updates.
    log_path : str
        Path to tier1_updates.jsonl log file.
        Defaults to ``TIER1_LOG_PATH``.
    """

    def __init__(
        self,
        knowledge_writer: EpochKnowledgeWriter,
        tier1_updater: Tier1AutonomousUpdater,
        log_path: str = TIER1_LOG_PATH,
    ) -> None:
        self.knowledge_writer = knowledge_writer
        self.tier1_updater = tier1_updater
        self.log_path = log_path

    # ------------------------------------------------------------------
    # Public API
    # ------------------------------------------------------------------

    def apply(
        self,
        axioms: List[Axiom],
        analysis: ArchitectureAnalysis,
    ) -> Tier1EpochResult:
        """
        Apply all Tier 1 epistemic updates for the current epoch.

        Steps (always in this order):
          1. Write axioms to KG + Qdrant via EpochKnowledgeWriter.write()
          2. Apply prompt template + rules updates via
             Tier1AutonomousUpdater.apply_tier1()
          3. Append an audit log entry with source="nightly_epoch"
          4. Return Tier1EpochResult with all four counts

        This method NEVER modifies any .py files.
        It runs unconditionally — callers do NOT need to pass a PR flag.

        Parameters
        ----------
        axioms:
            List of :class:`~core.epoch.axiom_distiller.Axiom` objects
            distilled from the current epoch.
        analysis:
            :class:`~core.evolution.meta_architect.ArchitectureAnalysis`
            produced by MetaArchitect for the current epoch.

        Returns
        -------
        Tier1EpochResult
            Counts of items updated in each category.
        """
        # Build epoch_id from current UTC date
        epoch_id = f"epoch_{datetime.now(timezone.utc).strftime('%Y_%m_%d')}"

        # Step 1: KG + Qdrant via knowledge_writer
        write_result = self.knowledge_writer.write(axioms, epoch_id)

        # Step 2: Prompt templates + rules via tier1_updater
        tier1_result = self.tier1_updater.apply_tier1(analysis, epoch_id=epoch_id)

        # Step 3: Build result
        result = Tier1EpochResult(
            kg_axioms_written=write_result.jsonl_entries,
            qdrant_scars_updated=write_result.qdrant_upserts,
            prompt_templates_updated=tier1_result.prompts_updated,
            rules_appended=tier1_result.rules_updated,
        )

        # Step 4: Log to tier1_updates.jsonl
        self._log_update(result, epoch_id)

        return result

    # ------------------------------------------------------------------
    # Private helpers
    # ------------------------------------------------------------------

    def _log_update(self, result: Tier1EpochResult, epoch_id: str) -> None:
        """Append one JSONL audit entry with source='nightly_epoch'."""
        entry = {
            "source": "nightly_epoch",
            "epoch_id": epoch_id,
            "timestamp": datetime.now(timezone.utc).isoformat(),
            "kg_axioms_written": result.kg_axioms_written,
            "qdrant_scars_updated": result.qdrant_scars_updated,
            "prompt_templates_updated": result.prompt_templates_updated,
            "rules_appended": result.rules_appended,
        }
        try:
            log_path = Path(self.log_path)
            log_path.parent.mkdir(parents=True, exist_ok=True)
            with open(log_path, "a", encoding="utf-8") as fh:
                fh.write(json.dumps(entry) + "\n")
        except OSError as exc:
            logger.error("EpochTier1Trigger: failed to write log entry: %s", exc)
