"""
Batch Upload Repository

Handles batch upload operations following Single Responsibility Principle.
"""

import logging
from typing import Any
from uuid import UUID

from sqlalchemy import func
from sqlmodel import select

from backend.data.database import get_session_context
from backend.data.admin_models import BatchUpload, BatchUploadFile
from backend.data.repositories.base import BaseRepository

logger = logging.getLogger(__name__)


class BatchUploadRepository(BaseRepository[BatchUpload]):
    """Repository for batch upload management.

    Handles:
    - Batch upload CRUD operations
    - Batch file tracking
    - Progress monitoring
    """

    def create(
        self,
        admin_token: str,
        filename: str,
        file_size: int,
        upload_source: str = "ui",
    ) -> BatchUpload:
        """Create a new batch upload record."""
        with get_session_context() as session:
            batch = BatchUpload(
                admin_token=admin_token,
                filename=filename,
                file_size=file_size,
                upload_source=upload_source,
            )
            session.add(batch)
            session.commit()
            session.refresh(batch)
            session.expunge(batch)
            return batch

    def get(self, batch_id: UUID) -> BatchUpload | None:
        """Get batch upload by ID."""
        with get_session_context() as session:
            result = session.get(BatchUpload, batch_id)
            if result:
                session.expunge(result)
            return result

    def update(
        self,
        batch_id: UUID,
        **kwargs: Any,
    ) -> None:
        """Update batch upload fields."""
        with get_session_context() as session:
            batch = session.get(BatchUpload, batch_id)
            if batch:
                for key, value in kwargs.items():
                    if hasattr(batch, key):
                        setattr(batch, key, value)
                session.add(batch)

    def create_file(
        self,
        batch_id: UUID,
        filename: str,
        **kwargs: Any,
    ) -> BatchUploadFile:
        """Create a batch upload file record."""
        with get_session_context() as session:
            file_record = BatchUploadFile(
                batch_id=batch_id,
                filename=filename,
                **kwargs,
            )
            session.add(file_record)
            session.commit()
            session.refresh(file_record)
            session.expunge(file_record)
            return file_record

    def update_file(
        self,
        file_id: UUID,
        **kwargs: Any,
    ) -> None:
        """Update batch upload file fields."""
        with get_session_context() as session:
            file_record = session.get(BatchUploadFile, file_id)
            if file_record:
                for key, value in kwargs.items():
                    if hasattr(file_record, key):
                        setattr(file_record, key, value)
                session.add(file_record)

    def get_files(self, batch_id: UUID) -> list[BatchUploadFile]:
        """Get all files for a batch upload."""
        with get_session_context() as session:
            statement = select(BatchUploadFile).where(
                BatchUploadFile.batch_id == batch_id
            ).order_by(BatchUploadFile.created_at)

            results = session.exec(statement).all()
            for r in results:
                session.expunge(r)
            return list(results)

    def get_paginated(
        self,
        admin_token: str | None = None,
        limit: int = 50,
        offset: int = 0,
    ) -> tuple[list[BatchUpload], int]:
        """Get paginated batch uploads."""
        with get_session_context() as session:
            count_stmt = select(func.count()).select_from(BatchUpload)
            total = session.exec(count_stmt).one()

            statement = select(BatchUpload).order_by(
                BatchUpload.created_at.desc()
            ).offset(offset).limit(limit)

            results = session.exec(statement).all()
            for r in results:
                session.expunge(r)
            return list(results), total
