"""Nexus — SSH Session & Command Log Repository (Async SQLAlchemy)"""

from typing import Optional, List
from datetime import datetime, timezone, timedelta
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from server.domain.models import SshSession, CommandLog


class SshSessionRepositoryImpl:
    def __init__(self, session: AsyncSession):
        self.session = session

    async def get_by_id(self, session_id: str) -> Optional[SshSession]:
        result = await self.session.execute(select(SshSession).where(SshSession.id == session_id))
        return result.scalar_one_or_none()

    async def get_active_by_admin(self, admin_id: int) -> List[SshSession]:
        result = await self.session.execute(
            select(SshSession)
            .where(SshSession.admin_id == admin_id, SshSession.status == "active")
            .order_by(SshSession.started_at.desc())
        )
        return list(result.scalars().all())

    async def get_by_server(self, server_id: int, limit: int = 50) -> List[SshSession]:
        result = await self.session.execute(
            select(SshSession)
            .where(SshSession.server_id == server_id)
            .order_by(SshSession.started_at.desc())
            .limit(limit)
        )
        return list(result.scalars().all())

    async def create(self, ssh_session: SshSession) -> SshSession:
        self.session.add(ssh_session)
        await self.session.commit()
        return ssh_session

    async def close_session(self, session_id: str) -> Optional[SshSession]:
        ssh_session = await self.get_by_id(session_id)
        if ssh_session:
            ssh_session.status = "closed"
            ssh_session.closed_at = datetime.now(timezone.utc)
            await self.session.commit()
        return ssh_session


class CommandLogRepositoryImpl:
    def __init__(self, session: AsyncSession):
        self.session = session

    async def get_by_session(self, session_id: str, limit: int = 200) -> List[CommandLog]:
        result = await self.session.execute(
            select(CommandLog)
            .where(CommandLog.session_id == session_id)
            .order_by(CommandLog.created_at.asc())
            .limit(limit)
        )
        return list(result.scalars().all())

    async def get_by_server(self, server_id: int, limit: int = 200) -> List[CommandLog]:
        result = await self.session.execute(
            select(CommandLog)
            .where(CommandLog.server_id == server_id)
            .order_by(CommandLog.created_at.desc())
            .limit(limit)
        )
        return list(result.scalars().all())

    async def create(self, log: CommandLog) -> CommandLog:
        self.session.add(log)
        await self.session.commit()
        return log

    async def count_by_admin(self, admin_id: int, hours: int = 24) -> int:
        cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)
        result = await self.session.execute(
            select(func.count(CommandLog.id))
            .where(CommandLog.admin_id == admin_id, CommandLog.created_at >= cutoff)
        )
        return result.scalar_one() or 0