from __future__ import annotations

from sqlalchemy import or_, select
from sqlalchemy.orm import Session

from app.models.agent_asset import AgentAsset, AgentAssetReview, AgentAssetVersion


class AgentAssetRepository:
    def __init__(self, db: Session) -> None:
        self.db = db

    def list(
        self,
        *,
        asset_type: str | None = None,
        status: str | None = None,
        domain: str | None = None,
        keyword: str | None = None,
    ) -> list[AgentAsset]:
        stmt = select(AgentAsset)

        if asset_type:
            stmt = stmt.where(AgentAsset.asset_type == asset_type)
        if status:
            stmt = stmt.where(AgentAsset.status == status)
        if domain:
            stmt = stmt.where(AgentAsset.domain == domain)
        if keyword:
            like_keyword = f"%{keyword.strip()}%"
            stmt = stmt.where(
                or_(
                    AgentAsset.name.ilike(like_keyword),
                    AgentAsset.code.ilike(like_keyword),
                    AgentAsset.description.ilike(like_keyword),
                )
            )

        stmt = stmt.order_by(AgentAsset.updated_at.desc(), AgentAsset.created_at.desc())
        return list(self.db.scalars(stmt).all())

    def get(self, asset_id: str) -> AgentAsset | None:
        return self.db.get(AgentAsset, asset_id)

    def get_by_code(self, code: str) -> AgentAsset | None:
        stmt = select(AgentAsset).where(AgentAsset.code == code)
        return self.db.scalar(stmt)

    def list_versions(self, asset_id: str, *, limit: int | None = None) -> list[AgentAssetVersion]:
        stmt = (
            select(AgentAssetVersion)
            .where(AgentAssetVersion.asset_id == asset_id)
            .order_by(AgentAssetVersion.created_at.desc())
        )
        if limit is not None:
            stmt = stmt.limit(limit)
        return list(self.db.scalars(stmt).all())

    def get_version(self, asset_id: str, version: str) -> AgentAssetVersion | None:
        stmt = select(AgentAssetVersion).where(
            AgentAssetVersion.asset_id == asset_id,
            AgentAssetVersion.version == version,
        )
        return self.db.scalar(stmt)

    def list_reviews(self, asset_id: str, *, limit: int | None = None) -> list[AgentAssetReview]:
        stmt = (
            select(AgentAssetReview)
            .where(AgentAssetReview.asset_id == asset_id)
            .order_by(AgentAssetReview.created_at.desc())
        )
        if limit is not None:
            stmt = stmt.limit(limit)
        return list(self.db.scalars(stmt).all())

    def get_review(
        self, asset_id: str, version: str, review_status: str | None = None
    ) -> AgentAssetReview | None:
        stmt = select(AgentAssetReview).where(
            AgentAssetReview.asset_id == asset_id,
            AgentAssetReview.version == version,
        )
        if review_status:
            stmt = stmt.where(AgentAssetReview.review_status == review_status)
        stmt = stmt.order_by(AgentAssetReview.created_at.desc())
        return self.db.scalar(stmt)

    def create_asset(self, asset: AgentAsset) -> AgentAsset:
        self.db.add(asset)
        self.db.commit()
        self.db.refresh(asset)
        return asset

    def save_asset(self, asset: AgentAsset) -> AgentAsset:
        self.db.add(asset)
        self.db.commit()
        self.db.refresh(asset)
        return asset

    def create_version(self, version: AgentAssetVersion) -> AgentAssetVersion:
        self.db.add(version)
        self.db.commit()
        self.db.refresh(version)
        return version

    def create_review(self, review: AgentAssetReview) -> AgentAssetReview:
        self.db.add(review)
        self.db.commit()
        self.db.refresh(review)
        return review
