"""Nexus — PendingServer Repository (SSH poll failures queue)"""

from datetime import datetime, timezone
from typing import Optional, List

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

from server.domain.models import PendingServer


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

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

    async def get_all(self) -> List[PendingServer]:
        result = await self.session.execute(
            select(PendingServer).order_by(PendingServer.last_attempt_at.desc(), PendingServer.id.desc())
        )
        return list(result.scalars().all())

    async def create(self, pending: PendingServer) -> PendingServer:
        self.session.add(pending)
        await self.session.commit()
        await self.session.refresh(pending)
        return pending

    async def update(self, pending: PendingServer) -> PendingServer:
        await self.session.commit()
        await self.session.refresh(pending)
        return pending

    async def delete(self, id: int) -> bool:
        row = await self.get_by_id(id)
        if not row:
            return False
        await self.session.delete(row)
        await self.session.commit()
        return True

    async def record_failure(
        self,
        *,
        name: str,
        domain: str,
        port: int,
        agent_port: int,
        target_path: str | None,
        category: str | None,
        platform_id: int | None,
        node_id: int | None,
        last_error: str,
        existing_id: int | None = None,
    ) -> PendingServer:
        now = datetime.now(timezone.utc)
        if existing_id:
            row = await self.get_by_id(existing_id)
            if row:
                row.attempts = (row.attempts or 0) + 1
                row.last_error = last_error[:4000]
                row.last_attempt_at = now
                return await self.update(row)

        pending = PendingServer(
            name=name,
            domain=domain,
            port=port,
            agent_port=agent_port,
            target_path=target_path,
            category=category,
            platform_id=platform_id,
            node_id=node_id,
            attempts=1,
            last_error=last_error[:4000],
            last_attempt_at=now,
        )
        return await self.create(pending)
