"""cortex/storage/queries/cornerstone_queries.py — Cornerstone storage mixin."""

from __future__ import annotations

from typing import Any, Dict, List, Optional

from cortex.storage._helpers import _now, _sha256, _row_to_cornerstone, _row_to_evolution_proposal
from cortex.validation import validate_cornerstone_fields


class CornerstoneQueryMixin:
    """Mixin providing cornerstonequery methods."""

    async def get_cornerstones(
        self, owner_id: str = "default", status: str = "active"
    ) -> List[CornerstoneMemory]:
        """Return active cornerstone memories for an owner ordered by injection_order."""
        conn = await self._get_conn()
        async with conn.execute(
            """
            SELECT * FROM cornerstone_memory
            WHERE owner_id = ? AND status = ?
            ORDER BY injection_order ASC
            """,
            (owner_id, status),
        ) as cur:
            rows = await cur.fetchall()
        return [_row_to_cornerstone(r) for r in rows]


    async def seal_cornerstone(
        self,
        label: str,
        content: str,
        owner_id: str = "default",
        **kwargs,
    ) -> CornerstoneMemory:
        """Create a sealed cornerstone memory with a golden-copy hash and return it."""
        # Validate and sanitize label and content
        label, content = validate_cornerstone_fields(label, content)

        conn = await self._get_conn()
        now = _now()
        golden_hash = _sha256(content)
        token_count = kwargs.get("token_count", len(content.split()))
        injection_order = kwargs.get("injection_order", 0)
        sealed_by = kwargs.get("sealed_by", "operator")

        async with self._write_lock:
            async with conn.execute(
                """
                INSERT INTO cornerstone_memory
                    (owner_id, label, content, golden_copy, golden_hash, current_hash,
                     token_count, injection_order, sealed_at, sealed_by,
                     created_at, updated_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                RETURNING *
                """,
                (owner_id, label, content, content, golden_hash, golden_hash,
                 token_count, injection_order, now, sealed_by, now, now),
            ) as cur:
                row = await cur.fetchone()
            await conn.commit()
        return _row_to_cornerstone(row)


    async def update_cornerstone_drift(
        self, cs_id: str, drift_score: float
    ) -> None:
        """Update drift_score and last_drift_check for a cornerstone in-place; returns None."""
        async with self._write_lock:
            conn = await self._get_conn()
            now = _now()
            await conn.execute(
                """
                UPDATE cornerstone_memory
                   SET drift_score = ?, last_drift_check = ?, updated_at = ?
                 WHERE id = ?
                """,
                (drift_score, now, now, cs_id),
            )
            await conn.commit()


    async def get_cornerstone_by_id(self, cs_id: str, owner_id: Optional[str] = None) -> Optional[CornerstoneMemory]:
        """Return a cornerstone by ID regardless of owner_id, or None."""
        conn = await self._get_conn()
        if owner_id is None:
            async with conn.execute(
                "SELECT * FROM cornerstone_memory WHERE id = ?", (cs_id,)
            ) as cur:
                row = await cur.fetchone()
        else:
            async with conn.execute(
                "SELECT * FROM cornerstone_memory WHERE id = ? AND owner_id = ?",
                (cs_id, owner_id),
            ) as cur:
                row = await cur.fetchone()
        if row is None:
            return None
        return _row_to_cornerstone(row)


    async def retire_cornerstone(self, cs_id: str) -> CornerstoneMemory:
        """Set cornerstone status to 'retired' and return the updated row."""
        async with self._write_lock:
            conn = await self._get_conn()
            now = _now()
            await conn.execute(
                """
                UPDATE cornerstone_memory
                   SET status = 'retired', updated_at = ?
                 WHERE id = ?
                """,
                (now, cs_id),
            )
            await conn.commit()

            async with conn.execute(
                "SELECT * FROM cornerstone_memory WHERE id = ?", (cs_id,)
            ) as cur:
                row = await cur.fetchone()
            assert row is not None
            return _row_to_cornerstone(row)


    async def restore_cornerstone(self, cs_id: str) -> CornerstoneMemory:
        """Reset a cornerstone's content to its golden_copy, clear drift_score, bump revision; returns updated row."""
        async with self._write_lock:
            conn = await self._get_conn()
            now = _now()
            await conn.execute(
                """
                UPDATE cornerstone_memory
                   SET content = golden_copy,
                       current_hash = golden_hash,
                       drift_score = 0.0,
                       last_drift_check = ?,
                       updated_at = ?,
                       revision = revision + 1
                 WHERE id = ?
                """,
                (now, now, cs_id),
            )
            await conn.commit()

            async with conn.execute(
                "SELECT * FROM cornerstone_memory WHERE id = ?", (cs_id,)
            ) as cur:
                row = await cur.fetchone()
            assert row is not None
            return _row_to_cornerstone(row)


    async def create_evolution_proposal(
        self,
        cornerstone_id: str,
        owner_id: str,
        new_evidence: str,
        proposed_content: str,
        diff: str,
        reasoning: str,
        confidence: float = 0.0,
    ) -> EvolutionProposal:
        """Insert a new evolution proposal with status='pending'."""
        async with self._write_lock:
            conn = await self._get_conn()
            now = _now()
            async with conn.execute(
                """
                INSERT INTO cornerstone_evolution_proposal
                    (cornerstone_id, owner_id, new_evidence, proposed_content,
                     diff, reasoning, confidence, status, created_at)
                VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?)
                RETURNING *
                """,
                (cornerstone_id, owner_id, new_evidence, proposed_content,
                 diff, reasoning, confidence, now),
            ) as cur:
                row = await cur.fetchone()
            await conn.commit()
            return _row_to_evolution_proposal(row)


    async def get_evolution_proposals(
        self,
        cornerstone_id: str,
        status: str = "pending",
    ) -> List[EvolutionProposal]:
        """Return proposals for a cornerstone filtered by status."""
        conn = await self._get_conn()
        async with conn.execute(
            """
            SELECT * FROM cornerstone_evolution_proposal
            WHERE cornerstone_id = ? AND status = ?
            ORDER BY created_at DESC
            """,
            (cornerstone_id, status),
        ) as cur:
            rows = await cur.fetchall()
        return [_row_to_evolution_proposal(r) for r in rows]


    async def get_evolution_proposal(
        self, proposal_id: str
    ) -> Optional[EvolutionProposal]:
        """Return a single evolution proposal by ID, or None."""
        conn = await self._get_conn()
        async with conn.execute(
            "SELECT * FROM cornerstone_evolution_proposal WHERE id = ?",
            (proposal_id,),
        ) as cur:
            row = await cur.fetchone()
        return _row_to_evolution_proposal(row) if row else None


    async def update_evolution_proposal_status(
        self,
        proposal_id: str,
        status: str,
        applied_at: Optional[str] = None,
    ) -> EvolutionProposal:
        """Update the status of an evolution proposal."""
        async with self._write_lock:
            conn = await self._get_conn()
            now = _now()
            await conn.execute(
                """
                UPDATE cornerstone_evolution_proposal
                SET status = ?, applied_at = ?
                WHERE id = ?
                """,
                (status, applied_at or (now if status == "applied" else None), proposal_id),
            )
            await conn.commit()
            async with conn.execute(
                "SELECT * FROM cornerstone_evolution_proposal WHERE id = ?",
                (proposal_id,),
            ) as cur:
                row = await cur.fetchone()
            if row is None:
                raise ValueError(f"Evolution proposal not found: {proposal_id}")
            return _row_to_evolution_proposal(row)


    async def get_cornerstone_drift_history(
        self, cornerstone_id: str, limit: int = 50
    ) -> List[Dict[str, Any]]:
        conn = await self._get_conn()
        async with conn.execute(
            """
            SELECT drift_score, checked_at, action_taken AS action
            FROM drift_log
            WHERE cornerstone_id = ?
            ORDER BY checked_at DESC
            LIMIT ?
            """,
            (cornerstone_id, limit),
        ) as cur:
            rows = await cur.fetchall()
        return [dict(r) for r in rows]


    async def update_cornerstone_content(
        self,
        cs_id: str,
        content: str,
        reason: Optional[str] = None,
    ) -> "CornerstoneMemory":
        """Revise cornerstone content and bump revision counter."""
        async with self._write_lock:
            conn = await self._get_conn()
            now = _now()
            new_hash = _sha256(content)
            token_count = len(content.split())

            # Fetch current revision + hashes for changelog and drift recompute
            async with conn.execute(
                "SELECT revision, revision_history, golden_hash FROM cornerstone_memory WHERE id = ?",
                (cs_id,),
            ) as cur:
                row = await cur.fetchone()
            if row is None:
                raise ValueError(f"Cornerstone {cs_id} not found")

            current_revision = row[0]
            stored_history = row[1]
            golden_hash = row[2]
            drift_score = 0.0 if new_hash == golden_hash else 1.0
            try:
                import json as _json
                history = _json.loads(stored_history or "[]")
            except Exception:
                history = []

            new_revision = current_revision + 1
            history.append({
                "revision": new_revision,
                "reason": reason or "",
                "updated_at": now,
            })

            await conn.execute(
                """
                UPDATE cornerstone_memory
                   SET content = ?,
                       current_hash = ?,
                       token_count = ?,
                       revision = ?,
                       revision_history = ?,
                       drift_score = ?,
                       last_drift_check = ?,
                       updated_at = ?
                 WHERE id = ?
                """,
                (
                    content,
                    new_hash,
                    token_count,
                    new_revision,
                    _json.dumps(history),
                    drift_score,
                    now,
                    now,
                    cs_id,
                ),
            )
            await conn.commit()

            async with conn.execute(
                "SELECT * FROM cornerstone_memory WHERE id = ?", (cs_id,)
            ) as cur:
                updated = await cur.fetchone()
            assert updated is not None
            return _row_to_cornerstone(updated)


