"""Nexus — AuditLog Repository (Async SQLAlchemy)"""

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

from server.domain.models import AuditLog


def _build_filters(
    action: Optional[str] = None,
    admin_username: Optional[str] = None,
    date_from: Optional[str] = None,   # ISO date or datetime string
    date_to: Optional[str] = None,
) -> list:
    """Build SQLAlchemy WHERE clauses from optional filter params."""
    filters = []
    if action:
        filters.append(AuditLog.action == action)
    if admin_username:
        filters.append(AuditLog.admin_username == admin_username)
    if date_from:
        try:
            dt = datetime.fromisoformat(date_from)
            # Treat bare date (YYYY-MM-DD) as start of day UTC
            if dt.tzinfo is None:
                dt = dt.replace(tzinfo=timezone.utc)
            filters.append(AuditLog.created_at >= dt.replace(tzinfo=None))
        except ValueError:
            pass
    if date_to:
        try:
            dt = datetime.fromisoformat(date_to)
            if dt.tzinfo is None:
                dt = dt.replace(tzinfo=timezone.utc)
            filters.append(AuditLog.created_at <= dt.replace(tzinfo=None))
        except ValueError:
            pass
    return filters


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

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

    async def query(
        self,
        action: Optional[str] = None,
        admin_username: Optional[str] = None,
        date_from: Optional[str] = None,
        date_to: Optional[str] = None,
        limit: int = 50,
        offset: int = 0,
    ) -> Tuple[List[AuditLog], int]:
        """Unified query with all filters + total count."""
        filters = _build_filters(action, admin_username, date_from, date_to)
        count_q = select(func.count(AuditLog.id))
        data_q = select(AuditLog).order_by(AuditLog.created_at.desc()).offset(offset).limit(limit)
        if filters:
            count_q = count_q.where(*filters)
            data_q = data_q.where(*filters)
        total = int((await self.session.execute(count_q)).scalar() or 0)
        rows = list((await self.session.execute(data_q)).scalars().all())
        return rows, total

    # ── Kept for backward compat ──
    async def count(self, action: Optional[str] = None) -> int:
        filters = _build_filters(action)
        q = select(func.count(AuditLog.id))
        if filters:
            q = q.where(*filters)
        return int((await self.session.execute(q)).scalar() or 0)

    async def get_recent(self, limit: int = 200, offset: int = 0) -> List[AuditLog]:
        rows, _ = await self.query(limit=limit, offset=offset)
        return rows

    async def get_by_action(self, action: str, limit: int = 50, offset: int = 0) -> List[AuditLog]:
        rows, _ = await self.query(action=action, limit=limit, offset=offset)
        return rows