"""
Audit Logging Service for Time Tracking Module
===============================================

Fuld sporbarhed af alle handlinger i modulet.
Alle events logges til tmodule_sync_log for compliance.
"""

import logging
import json
from datetime import datetime
from typing import Optional, Dict, Any
from app.core.database import execute_insert
from app.timetracking.backend.models import TModuleSyncLogCreate

logger = logging.getLogger(__name__)


class AuditLogger:
    """
    Service til at logge alle module events.
    
    Event Types:
    - sync_started, sync_completed, sync_failed
    - approval, rejection, bulk_approval
    - order_created, order_updated, order_cancelled
    - export_started, export_completed, export_failed
    - module_installed, module_uninstalled
    """
    
    @staticmethod
    def log_event(
        event_type: str,
        entity_type: Optional[str] = None,
        entity_id: Optional[int] = None,
        user_id: Optional[int] = None,
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        user_agent: Optional[str] = None
    ) -> int:
        """
        Log en event til tmodule_sync_log.
        
        Args:
            event_type: Type af event (sync_started, approval, etc.)
            entity_type: Type af entitet (time_entry, order, customer, case)
            entity_id: ID på entiteten
            user_id: ID på brugeren der foretog handlingen
            details: Ekstra detaljer som JSON
            ip_address: IP-adresse
            user_agent: User agent string
            
        Returns:
            ID på den oprettede log-entry
        """
        try:
            # Konverter details til JSON-string hvis det er en dict
            details_json = json.dumps(details) if details else None
            
            query = """
                INSERT INTO tmodule_sync_log 
                (event_type, entity_type, entity_id, user_id, details, ip_address, user_agent)
                VALUES (%s, %s, %s, %s, %s::jsonb, %s, %s)
                RETURNING id
            """
            
            log_id = execute_insert(
                query,
                (event_type, entity_type, entity_id, user_id, details_json, ip_address, user_agent)
            )
            
            logger.debug(f"📝 Logged event: {event_type} (ID: {log_id})")
            return log_id
            
        except Exception as e:
            logger.error(f"❌ Failed to log event {event_type}: {e}")
            # Don't raise - audit logging failure shouldn't break main flow
            return 0
    
    @staticmethod
    def log_sync_started(user_id: Optional[int] = None) -> int:
        """Log start af vTiger sync"""
        return AuditLogger.log_event(
            event_type="sync_started",
            user_id=user_id,
            details={"timestamp": datetime.now().isoformat()}
        )
    
    @staticmethod
    def log_sync_completed(
        stats: Dict[str, Any],
        user_id: Optional[int] = None
    ) -> int:
        """Log succesfuld sync med statistik"""
        return AuditLogger.log_event(
            event_type="sync_completed",
            user_id=user_id,
            details=stats
        )
    
    @staticmethod
    def log_sync_failed(
        error: str,
        user_id: Optional[int] = None
    ) -> int:
        """Log fejlet sync"""
        return AuditLogger.log_event(
            event_type="sync_failed",
            user_id=user_id,
            details={"error": error, "timestamp": datetime.now().isoformat()}
        )
    
    @staticmethod
    def log_approval(
        time_id: int,
        original_hours: float,
        approved_hours: float,
        rounded_to: Optional[float],
        note: Optional[str],
        user_id: Optional[int] = None
    ) -> int:
        """Log godkendelse af tidsregistrering"""
        return AuditLogger.log_event(
            event_type="approval",
            entity_type="time_entry",
            entity_id=time_id,
            user_id=user_id,
            details={
                "original_hours": original_hours,
                "approved_hours": approved_hours,
                "rounded_to": rounded_to,
                "note": note,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_rejection(
        time_id: int,
        reason: Optional[str],
        user_id: Optional[int] = None
    ) -> int:
        """Log afvisning af tidsregistrering"""
        return AuditLogger.log_event(
            event_type="rejection",
            entity_type="time_entry",
            entity_id=time_id,
            user_id=user_id,
            details={
                "reason": reason,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_order_created(
        order_id: int,
        customer_id: int,
        total_hours: float,
        total_amount: float,
        line_count: int,
        user_id: Optional[int] = None
    ) -> int:
        """Log oprettelse af ordre"""
        return AuditLogger.log_event(
            event_type="order_created",
            entity_type="order",
            entity_id=order_id,
            user_id=user_id,
            details={
                "customer_id": customer_id,
                "total_hours": total_hours,
                "total_amount": total_amount,
                "line_count": line_count,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_order_updated(
        order_id: int,
        changes: Dict[str, Any],
        user_id: Optional[int] = None
    ) -> int:
        """Log opdatering af ordre"""
        return AuditLogger.log_event(
            event_type="order_updated",
            entity_type="order",
            entity_id=order_id,
            user_id=user_id,
            details={
                "changes": changes,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_order_cancelled(
        order_id: int,
        reason: Optional[str],
        user_id: Optional[int] = None
    ) -> int:
        """Log annullering af ordre"""
        return AuditLogger.log_event(
            event_type="order_cancelled",
            entity_type="order",
            entity_id=order_id,
            user_id=user_id,
            details={
                "reason": reason,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_export_started(
        order_id: int,
        user_id: Optional[int] = None
    ) -> int:
        """Log start af e-conomic export"""
        return AuditLogger.log_event(
            event_type="export_started",
            entity_type="order",
            entity_id=order_id,
            user_id=user_id,
            details={"timestamp": datetime.now().isoformat()}
        )
    
    @staticmethod
    def log_export_completed(
        order_id: int,
        economic_draft_id: Optional[int],
        economic_order_number: Optional[str],
        dry_run: bool,
        user_id: Optional[int] = None
    ) -> int:
        """Log succesfuld export til e-conomic"""
        return AuditLogger.log_event(
            event_type="export_completed",
            entity_type="order",
            entity_id=order_id,
            user_id=user_id,
            details={
                "economic_draft_id": economic_draft_id,
                "economic_order_number": economic_order_number,
                "dry_run": dry_run,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_export_failed(
        order_id: int,
        error: str,
        user_id: Optional[int] = None
    ) -> int:
        """Log fejlet export til e-conomic"""
        return AuditLogger.log_event(
            event_type="export_failed",
            entity_type="order",
            entity_id=order_id,
            user_id=user_id,
            details={
                "error": error,
                "timestamp": datetime.now().isoformat()
            }
        )
    
    @staticmethod
    def log_module_uninstalled(user_id: Optional[int] = None) -> int:
        """Log modul-uninstall"""
        return AuditLogger.log_event(
            event_type="module_uninstalled",
            user_id=user_id,
            details={"timestamp": datetime.now().isoformat()}
        )


# Singleton instance
audit = AuditLogger()
