from __future__ import annotations

from sqlalchemy import desc, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.agents.schemas.learning import SessionRetrospective
from app.models.learning import LearningArtifactRecord, SessionRetrospectiveRecord


class SessionRetrospectiveStore:
    def __init__(self, db: AsyncSession):
        self.db = db

    async def save(self, retrospective: SessionRetrospective) -> SessionRetrospectiveRecord:
        payload = retrospective.model_dump(mode="json")
        record = SessionRetrospectiveRecord(
            user_id=retrospective.user_id,
            conversation_id=retrospective.conversation_id,
            request_message_id=retrospective.request_message_id,
            response_message_id=retrospective.response_message_id,
            query_text=retrospective.query_text,
            final_response=retrospective.final_response,
            summary_text=retrospective.summary,
            task_type=retrospective.task_type,
            execution_mode=retrospective.execution_mode,
            primary_agent=retrospective.primary_agent,
            verification_status=retrospective.verification_status,
            verification_summary=retrospective.verification_summary,
            skill_names=retrospective.used_skill_names,
            evidence=retrospective.evidence_refs,
            task_refs=retrospective.task_refs,
            payload=payload,
        )
        self.db.add(record)
        await self.db.commit()
        await self.db.refresh(record)
        return record

    async def list_recent(
        self,
        *,
        user_id: str,
        limit: int = 20,
    ) -> list[SessionRetrospectiveRecord]:
        result = await self.db.execute(
            select(SessionRetrospectiveRecord)
            .where(SessionRetrospectiveRecord.user_id == user_id)
            .order_by(desc(SessionRetrospectiveRecord.recorded_at), desc(SessionRetrospectiveRecord.created_at))
            .limit(limit)
        )
        return list(result.scalars().all())


class LearningArtifactStore:
    def __init__(self, db: AsyncSession):
        self.db = db

    async def save_batch(
        self,
        *,
        user_id: str,
        conversation_id: str,
        retrospective_id: str | None,
        artifacts: list[dict[str, object]],
    ) -> list[LearningArtifactRecord]:
        records: list[LearningArtifactRecord] = []
        for artifact in artifacts:
            record = LearningArtifactRecord(
                user_id=user_id,
                conversation_id=conversation_id,
                retrospective_id=retrospective_id,
                artifact_type=str(artifact.get("artifact_type") or "unknown"),
                artifact_key=str(artifact.get("artifact_key") or "") or None,
                summary_text=str(artifact.get("summary_text") or ""),
                payload=dict(artifact.get("payload") or {}),
            )
            self.db.add(record)
            records.append(record)

        await self.db.commit()
        for record in records:
            await self.db.refresh(record)
        return records

    async def list_recent(
        self,
        *,
        user_id: str,
        artifact_type: str | None = None,
        limit: int = 50,
    ) -> list[LearningArtifactRecord]:
        query = select(LearningArtifactRecord).where(LearningArtifactRecord.user_id == user_id)
        if artifact_type:
            query = query.where(LearningArtifactRecord.artifact_type == artifact_type)
        result = await self.db.execute(
            query.order_by(
                desc(LearningArtifactRecord.recorded_at),
                desc(LearningArtifactRecord.created_at),
            ).limit(limit)
        )
        return list(result.scalars().all())

    async def aggregate_counts_by_key(
        self,
        *,
        user_id: str,
        artifact_type: str,
        limit: int = 100,
    ) -> dict[str, int]:
        records = await self.list_recent(user_id=user_id, artifact_type=artifact_type, limit=limit)
        counts: dict[str, int] = {}
        for record in records:
            key = record.artifact_key or "unknown"
            counts[key] = counts.get(key, 0) + 1
        return counts


def append_retrospective_attachment(
    attachments: list[dict] | None,
    retrospective: SessionRetrospective,
) -> list[dict]:
    next_attachments = list(attachments or [])
    next_attachments.append(
        {
            "kind": "session_retrospective",
            "payload": retrospective.model_dump(mode="json"),
        }
    )
    return next_attachments
