"""Migrate audit log schema from basic to comprehensive format."""

from datetime import datetime

from app.migrations.migrator import Migration


class Migration(Migration):
    """Update audit log schema to comprehensive format."""

    def __init__(self):
        super().__init__()
        self.version = "2025-08-17-120002"
        self.description = "Update audit log schema from basic to comprehensive format"

    async def up(self) -> None:
        """Migrate existing audit logs to new schema format."""

        # Find all existing audit logs with old schema
        old_logs_cursor = self.db.audit_logs.find({
            # Look for logs that have the old schema structure
            "$or": [
                {"when": {"$exists": True}},  # Old timestamp field
                {"job_id": {"$exists": True}},  # Old job-specific logs
                {"timestamp": {"$exists": False}}  # Missing new timestamp field
            ]
        })

        migration_count = 0

        async for old_log in old_logs_cursor:
            try:
                # Map old fields to new schema
                new_log = {
                    "_id": old_log["_id"],
                    "timestamp": old_log.get("when", old_log.get("timestamp", datetime.utcnow())),
                    "action": self._map_old_action(old_log.get("action", "unknown")),
                    "severity": "info",
                    "description": old_log.get("action", "Legacy action"),
                    "success": True,
                    "environment": "prod",
                    "service_name": "accessible-video-api",
                    "api_version": "v1"
                }

                # Map optional fields if they exist
                if "user_id" in old_log:
                    new_log["user_id"] = old_log["user_id"]

                if "job_id" in old_log:
                    new_log["resource_type"] = "job"
                    new_log["resource_id"] = old_log["job_id"]

                if "ip_address" in old_log:
                    new_log["ip_address"] = old_log["ip_address"]

                if "user_agent" in old_log:
                    new_log["user_agent"] = old_log["user_agent"]

                if "details" in old_log:
                    new_log["details"] = old_log["details"]

                # Replace the old document with the new schema
                await self.db.audit_logs.replace_one(
                    {"_id": old_log["_id"]},
                    new_log
                )

                migration_count += 1

            except Exception as e:
                print(f"Error migrating audit log {old_log.get('_id')}: {e}")
                continue

        print(f"✅ Applied migration {self.version}: Migrated {migration_count} audit log records")

    def _map_old_action(self, old_action: str) -> str:
        """Map old action strings to new AuditAction enum values."""
        action_mapping = {
            # Job actions
            "job_created": "job.create",
            "job_approved": "job.approve",
            "job_rejected": "job.reject",
            "job_updated": "job.update",
            "job_cancelled": "job.cancel",

            # Auth actions
            "login": "auth.login.success",
            "logout": "auth.logout",
            "login_failed": "auth.login.failure",

            # File actions
            "file_uploaded": "file.upload",
            "file_downloaded": "file.download",

            # VTT actions
            "vtt_edited": "vtt.edit",

            # Admin actions
            "user_created": "user.create",
            "user_updated": "user.update",
            "user_deleted": "user.delete",
        }

        return action_mapping.get(old_action, old_action)

    async def down(self) -> None:
        """Rollback to old audit log schema format (limited)."""

        # Find all audit logs with new schema
        new_logs_cursor = self.db.audit_logs.find({
            "timestamp": {"$exists": True},
            "action": {"$exists": True}
        })

        rollback_count = 0

        async for new_log in new_logs_cursor:
            try:
                # Map new fields back to old schema (lossy conversion)
                old_log = {
                    "_id": new_log["_id"],
                    "when": new_log["timestamp"],
                    "action": new_log["action"]
                }

                # Map back optional fields
                if "user_id" in new_log:
                    old_log["user_id"] = new_log["user_id"]

                if "resource_type" in new_log and new_log["resource_type"] == "job":
                    old_log["job_id"] = new_log.get("resource_id")

                if "ip_address" in new_log:
                    old_log["ip_address"] = new_log["ip_address"]

                if "user_agent" in new_log:
                    old_log["user_agent"] = new_log["user_agent"]

                if "details" in new_log:
                    old_log["details"] = new_log["details"]

                # Replace with old schema
                await self.db.audit_logs.replace_one(
                    {"_id": new_log["_id"]},
                    old_log
                )

                rollback_count += 1

            except Exception as e:
                print(f"Error rolling back audit log {new_log.get('_id')}: {e}")
                continue

        print(f"⚠️  Rolled back migration {self.version}: Reverted {rollback_count} audit log records")
        print("⚠️  WARNING: Some audit log data may have been lost due to schema differences")
