"""Trusted device service - skip TOTP on remembered devices (InTalk-style)."""
from __future__ import annotations
from datetime import datetime, timedelta, timezone
from typing import Optional
from uuid import UUID

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

from src.core.security.hashing import generate_secure_token


class TrustedDeviceRepository:
    """Trusted device CRUD."""

    def __init__(self, db: AsyncSession):
        self._db = db

    async def is_trusted(self, user_id: UUID, device_id: str) -> bool:
        if not device_id:
            return False
        from src.domain.auth.mfa_models import TrustedDevice

        result = await self._db.execute(
            select(TrustedDevice).where(
                and_(
                    TrustedDevice.user_id == user_id,
                    TrustedDevice.device_id == device_id,
                    TrustedDevice.expires_at > datetime.now(timezone.utc),
                )
            )
        )
        return result.scalar_one_or_none() is not None

    async def trust_device(
        self,
        user_id: UUID,
        device_id: Optional[str] = None,
        days: int = 30,
        user_agent: Optional[str] = None,
        ip_address: Optional[str] = None,
    ) -> str:
        from src.domain.auth.mfa_models import TrustedDevice

        device_id = device_id or generate_secure_token(32)
        expires_at = datetime.now(timezone.utc) + timedelta(days=days)

        result = await self._db.execute(
            select(TrustedDevice).where(
                and_(
                    TrustedDevice.user_id == user_id,
                    TrustedDevice.device_id == device_id,
                )
            )
        )
        existing = result.scalar_one_or_none()

        if existing:
            existing.expires_at = expires_at
            existing.user_agent = user_agent
            existing.ip_address = ip_address
        else:
            self._db.add(
                TrustedDevice(
                    user_id=user_id,
                    device_id=device_id,
                    user_agent=user_agent,
                    ip_address=ip_address,
                    expires_at=expires_at,
                )
            )
        await self._db.flush()
        return device_id

    async def revoke_all(self, user_id: UUID) -> None:
        from src.domain.auth.mfa_models import TrustedDevice

        result = await self._db.execute(select(TrustedDevice).where(TrustedDevice.user_id == user_id))
        for row in result.scalars().all():
            await self._db.delete(row)
        await self._db.flush()
