"""Nexus — Repository Abstract Interfaces
Protocol-based interfaces for dependency inversion.
Concrete implementations in infrastructure/database/.
"""

from typing import Protocol, Optional, List
from server.domain.models import (
    Server, SyncLog, Script, ScriptExecution, DbCredential,
    Admin, LoginAttempt, Setting, PasswordPreset,
    PushSchedule, PushRetryJob, AuditLog,
)


class ServerRepository(Protocol):
    """Server data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[Server]: ...
    async def get_by_ids(self, ids: List[int]) -> List[Server]: ...
    async def get_all(self) -> List[Server]: ...
    async def get_by_category(self, category: str) -> List[Server]: ...
    async def get_online(self) -> List[Server]: ...
    async def create(self, server: Server) -> Server: ...
    async def update(self, server: Server) -> Server: ...
    async def delete(self, id: int) -> bool: ...
    async def update_heartbeat(self, id: int, is_online: bool, system_info: str, agent_version: str) -> None: ...


class SyncLogRepository(Protocol):
    """Sync log data access abstract interface"""

    async def get_by_server_id(self, server_id: int, limit: int = 50) -> List[SyncLog]: ...
    async def create(self, log: SyncLog) -> SyncLog: ...
    async def update_status(self, id: int, status: str, **kwargs) -> SyncLog: ...


class AdminRepository(Protocol):
    """Admin user data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[Admin]: ...
    async def get_by_username(self, username: str) -> Optional[Admin]: ...
    async def create(self, admin: Admin) -> Admin: ...
    async def update(self, admin: Admin) -> Admin: ...


class LoginAttemptRepository(Protocol):
    """Login attempt data access abstract interface"""

    async def create(self, attempt: LoginAttempt) -> LoginAttempt: ...
    async def count_recent_failures(self, username: str, ip_address: str, minutes: int = 15) -> int: ...
    async def clear_failures_for_username(self, username: str) -> int: ...


class SettingRepository(Protocol):
    """System setting data access abstract interface"""

    async def get(self, key: str) -> Optional[str]: ...
    async def set(self, key: str, value: str) -> Setting: ...
    async def get_all(self) -> List[Setting]: ...


class PasswordPresetRepository(Protocol):
    """Password preset data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[PasswordPreset]: ...
    async def get_all(self) -> List[PasswordPreset]: ...
    async def create(self, preset: PasswordPreset) -> PasswordPreset: ...
    async def delete(self, id: int) -> bool: ...


class PushScheduleRepository(Protocol):
    """Push schedule data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[PushSchedule]: ...
    async def get_all(self) -> List[PushSchedule]: ...
    async def get_enabled(self) -> List[PushSchedule]: ...
    async def create(self, schedule: PushSchedule) -> PushSchedule: ...
    async def update(self, schedule: PushSchedule) -> PushSchedule: ...
    async def delete(self, id: int) -> bool: ...


class PushRetryJobRepository(Protocol):
    """Push retry job data access abstract interface"""

    async def get_pending(self, limit: int = 100) -> List[PushRetryJob]: ...
    async def create(self, job: PushRetryJob) -> PushRetryJob: ...
    async def update_status(self, id: int, status: str, **kwargs) -> PushRetryJob: ...


class AuditLogRepository(Protocol):
    """Audit log data access abstract interface"""

    async def create(self, log: AuditLog) -> AuditLog: ...
    async def get_recent(self, limit: int = 200) -> List[AuditLog]: ...
    async def get_by_action(self, action: str, limit: int = 50) -> List[AuditLog]: ...


class ScriptRepository(Protocol):
    """Script library data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[Script]: ...
    async def get_all(self) -> List[Script]: ...
    async def get_by_category(self, category: str) -> List[Script]: ...
    async def create(self, script: Script) -> Script: ...
    async def update(self, script: Script) -> Script: ...
    async def delete(self, id: int) -> bool: ...


class ScriptExecutionRepository(Protocol):
    """Script execution data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[ScriptExecution]: ...
    async def create(self, execution: ScriptExecution) -> ScriptExecution: ...
    async def update_status(self, id: int, status: str, results: str) -> Optional[ScriptExecution]: ...
    async def list_recent(
        self, limit: int = 50, offset: int = 0, status: Optional[str] = None,
    ) -> tuple[List[ScriptExecution], int]: ...


class DbCredentialRepository(Protocol):
    """Database credential data access abstract interface"""

    async def get_by_id(self, id: int) -> Optional[DbCredential]: ...
    async def get_all(self) -> List[DbCredential]: ...
    async def create(self, credential: DbCredential) -> DbCredential: ...
    async def delete(self, id: int) -> bool: ...