from __future__ import annotations

from datetime import datetime

from sqlalchemy import inspect, select, text

from app.core.agent_enums import (
    AgentAssetStatus,
)
from app.core.logging import get_logger
from app.models.agent_asset import AgentAsset, AgentAssetReview, AgentAssetVersion
from app.models.audit_log import AuditLog
from app.services.agent_asset_access import platform_asset_statement
from app.services.agent_foundation_constants import (
    LEGACY_RULE_CODES,
)

logger = get_logger("app.services.agent_foundation")

class AgentFoundationAssetHelperMixin:
    @staticmethod
    def _platform_asset_stmt():
        return platform_asset_statement()

    def _create_seed_asset(

        self,

        *,

        asset_type: str,

        code: str,

        name: str,

        description: str,

        domain: str,

        scenario_json: list[str],

        owner: str,

        reviewer: str,

        status: str,

        current_version: str,

        config_json: dict[str, object],

    ) -> AgentAsset:

        asset = AgentAsset(

            asset_type=asset_type,

            code=code,

            name=name,

            description=description,

            domain=domain,

            scenario_json=scenario_json,

            owner=owner,

            reviewer=reviewer,

            status=status,

            current_version=current_version,

            published_version=current_version if status == AgentAssetStatus.ACTIVE.value else None,

            working_version=current_version,

            config_json=config_json,

        )

        self.db.add(asset)

        self.db.flush()

        return asset

    def _ensure_asset_version(

        self,

        asset: AgentAsset,

        *,

        version: str,

        content: str,

        content_type: str,

        change_note: str,

        created_by: str,

    ) -> None:

        existing = self.db.scalar(

            select(AgentAssetVersion).where(

                AgentAssetVersion.asset_id == asset.id,

                AgentAssetVersion.version == version,

            )

        )

        if existing is not None:

            return

        self.db.add(

            AgentAssetVersion(

                asset_id=asset.id,

                version=version,

                content=content,

                content_type=content_type,

                change_note=change_note,

                created_by=created_by,

            )

        )

    def _ensure_asset_review(

        self,

        asset: AgentAsset,

        *,

        version: str,

        reviewer: str,

        review_status: str,

        review_note: str,

        reviewed_at: datetime | None,

    ) -> None:

        existing = self.db.scalar(

            select(AgentAssetReview).where(

                AgentAssetReview.asset_id == asset.id,

                AgentAssetReview.version == version,

                AgentAssetReview.review_status == review_status,

            )

        )

        if existing is not None:

            return

        self.db.add(

            AgentAssetReview(

                asset_id=asset.id,

                version=version,

                reviewer=reviewer,

                review_status=review_status,

                review_note=review_note,

                reviewed_at=reviewed_at,

            )

        )

    def _remove_legacy_rule_assets(self) -> None:

        assets = list(

            self.db.scalars(

                self._platform_asset_stmt().where(AgentAsset.code.in_(LEGACY_RULE_CODES))

            ).all()

        )

        for asset in assets:

            self.db.delete(asset)

        obsolete_logs = list(

            self.db.scalars(

                select(AuditLog).where(AuditLog.resource_id.in_(LEGACY_RULE_CODES))

            ).all()

        )

        for log in obsolete_logs:

            self.db.delete(log)

    def _ensure_agent_asset_schema(self) -> None:

        bind = self.db.get_bind()

        inspector = inspect(bind)

        if "agent_assets" not in inspector.get_table_names():

            return

        column_names = {column["name"] for column in inspector.get_columns("agent_assets")}

        migration_statements: list[str] = []

        if "published_version" not in column_names:

            migration_statements.append("ALTER TABLE agent_assets ADD COLUMN published_version VARCHAR(30)")

        if "working_version" not in column_names:

            migration_statements.append("ALTER TABLE agent_assets ADD COLUMN working_version VARCHAR(30)")

        for statement in migration_statements:

            self.db.execute(text(statement))

        self.db.execute(

            text(

                "UPDATE agent_assets "

                "SET working_version = COALESCE(working_version, current_version), "

                "published_version = CASE "

                "WHEN published_version IS NOT NULL THEN published_version "

                "WHEN status = 'active' THEN current_version "

                "ELSE published_version END"

            )

        )

        if migration_statements:

            self.db.commit()
