"""Data retention service: auto-purge expired presentations per client policy."""
import os
import uuid
from datetime import datetime, timedelta, timezone
from typing import Optional

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

from models.sql.client import ClientModel
from models.sql.presentation import PresentationModel
from services import audit_service
from services.database import async_session_maker
from utils.datetime_utils import get_current_utc_datetime


class RetentionService:

    async def run_cleanup(self) -> dict:
        """Soft-delete presentations older than each client's retention_days.

        Intended to be run daily via ARQ cron.
        Returns summary of actions taken.
        """
        deleted_count = 0
        errors = 0

        async with async_session_maker() as session:
            # Find all clients with a retention policy
            stmt = select(ClientModel).where(ClientModel.retention_days.isnot(None))
            result = await session.execute(stmt)
            clients = list(result.scalars().all())

            for client in clients:
                try:
                    cutoff = datetime.now(timezone.utc) - timedelta(
                        days=client.retention_days
                    )
                    # Find non-deleted presentations older than cutoff
                    pres_stmt = select(PresentationModel).where(
                        and_(
                            PresentationModel.client_id == client.id,
                            PresentationModel.created_at < cutoff,
                            PresentationModel.deleted_at.is_(None),
                        )
                    )
                    pres_result = await session.execute(pres_stmt)
                    expired = list(pres_result.scalars().all())

                    for presentation in expired:
                        presentation.deleted_at = get_current_utc_datetime()
                        deleted_count += 1

                        audit_service.log(
                            user_id=None,
                            action="retention_delete",
                            resource_type="presentation",
                            resource_id=presentation.id,
                            client_id=client.id,
                            details={
                                "retention_days": client.retention_days,
                                "created_at": presentation.created_at.isoformat()
                                if presentation.created_at
                                else None,
                            },
                        )

                    await session.commit()
                except Exception as e:
                    errors += 1
                    print(f"Retention cleanup error for client {client.id}: {e}")

        return {"deleted": deleted_count, "errors": errors}

    async def purge_soft_deleted(self, days_after_soft_delete: int = 30) -> dict:
        """Permanently delete records that were soft-deleted more than N days ago.

        Intended to be run weekly via ARQ cron.
        """
        purged_count = 0

        async with async_session_maker() as session:
            cutoff = datetime.now(timezone.utc) - timedelta(
                days=days_after_soft_delete
            )
            stmt = select(PresentationModel).where(
                and_(
                    PresentationModel.deleted_at.isnot(None),
                    PresentationModel.deleted_at < cutoff,
                )
            )
            result = await session.execute(stmt)
            expired = list(result.scalars().all())

            for presentation in expired:
                # Delete associated export files if they exist
                self._cleanup_files(presentation)
                await session.delete(presentation)
                purged_count += 1

            await session.commit()

        return {"purged": purged_count}

    def _cleanup_files(self, presentation: PresentationModel) -> None:
        """Remove associated files from filesystem."""
        try:
            if presentation.file_paths:
                for path in presentation.file_paths:
                    if path and os.path.exists(path):
                        os.remove(path)
        except Exception as e:
            print(f"File cleanup error for presentation {presentation.id}: {e}")
