"""
Data Breach Notification Service (Articles 33-34 GDPR).
"""
from sqlalchemy.orm import Session
from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta
from ..models.data_breach import DataBreach, BreachType, BreachStatus
from ...shared.config.logging_config import get_logger
from ...analytics.services.audit_service import audit_service

logger = get_logger(__name__)

class BreachService:
    """Service for managing data breach notifications (Articles 33-34 GDPR)."""
    
    NOTIFICATION_DEADLINE_HOURS = 72  # Article 33 - 72 hours to notify authority
    
    @staticmethod
    async def create_breach(
        db: Session,
        breach_type: BreachType,
        description: str,
        reported_by: int,
        affected_data_categories: Optional[List[str]] = None,
        affected_data_subjects: Optional[int] = None,
        occurred_at: Optional[datetime] = None,
        likely_consequences: Optional[str] = None,
        measures_proposed: Optional[str] = None,
        risk_level: Optional[str] = None,
        extra_metadata: Optional[Dict[str, Any]] = None
    ) -> DataBreach:
        """Create a data breach record."""
        breach = DataBreach(
            breach_type=breach_type,
            status=BreachStatus.detected,
            description=description,
            affected_data_categories=affected_data_categories or [],
            affected_data_subjects=affected_data_subjects,
            detected_at=datetime.utcnow(),
            occurred_at=occurred_at or datetime.utcnow(),
            likely_consequences=likely_consequences,
            measures_proposed=measures_proposed,
            risk_level=risk_level or 'medium',
            reported_by=reported_by,
            extra_metadata=extra_metadata
        )
        
        db.add(breach)
        db.commit()
        db.refresh(breach)
        
        # Log breach detection
        await audit_service.log_action(
            db=db,
            action='data_breach_detected',
            resource_type='data_breach',
            user_id=reported_by,
            resource_id=breach.id,
            details={
                'breach_type': breach_type.value,
                'risk_level': risk_level,
                'affected_subjects': affected_data_subjects
            },
            status='warning'
        )
        
        logger.warning(f'Data breach detected: {breach.id} - {breach_type.value}')
        return breach
    
    @staticmethod
    async def report_to_authority(
        db: Session,
        breach_id: int,
        authority_reference: str,
        reported_by: int
    ) -> DataBreach:
        """Report breach to supervisory authority (Article 33)."""
        breach = db.query(DataBreach).filter(DataBreach.id == breach_id).first()
        if not breach:
            raise ValueError('Breach not found')
        
        breach.status = BreachStatus.reported_to_authority
        breach.reported_to_authority_at = datetime.utcnow()
        breach.authority_reference = authority_reference
        
        db.commit()
        db.refresh(breach)
        
        # Check if within deadline
        time_since_detection = datetime.utcnow() - breach.detected_at
        if time_since_detection > timedelta(hours=BreachService.NOTIFICATION_DEADLINE_HOURS):
            logger.warning(f'Breach {breach_id} reported after {BreachService.NOTIFICATION_DEADLINE_HOURS} hour deadline')
        
        # Log report
        await audit_service.log_action(
            db=db,
            action='breach_reported_to_authority',
            resource_type='data_breach',
            user_id=reported_by,
            resource_id=breach_id,
            details={'authority_reference': authority_reference},
            status='success'
        )
        
        logger.info(f'Breach {breach_id} reported to authority: {authority_reference}')
        return breach
    
    @staticmethod
    async def notify_data_subjects(
        db: Session,
        breach_id: int,
        notification_method: str,
        notified_by: int
    ) -> DataBreach:
        """Notify affected data subjects (Article 34)."""
        breach = db.query(DataBreach).filter(DataBreach.id == breach_id).first()
        if not breach:
            raise ValueError('Breach not found')
        
        breach.status = BreachStatus.notified_data_subjects
        breach.notified_data_subjects_at = datetime.utcnow()
        breach.notification_method = notification_method
        
        db.commit()
        db.refresh(breach)
        
        # Log notification
        await audit_service.log_action(
            db=db,
            action='breach_subjects_notified',
            resource_type='data_breach',
            user_id=notified_by,
            resource_id=breach_id,
            details={'notification_method': notification_method},
            status='success'
        )
        
        logger.info(f'Data subjects notified for breach {breach_id}')
        return breach
    
    @staticmethod
    def get_breaches(
        db: Session,
        status: Optional[BreachStatus] = None,
        limit: int = 50,
        offset: int = 0
    ) -> List[DataBreach]:
        """Get data breaches with optional filters."""
        query = db.query(DataBreach)
        
        if status:
            query = query.filter(DataBreach.status == status)
        
        return query.order_by(DataBreach.detected_at.desc()).offset(offset).limit(limit).all()
    
    @staticmethod
    def get_breaches_requiring_notification(
        db: Session
    ) -> List[DataBreach]:
        """Get breaches that require notification (not yet reported)."""
        deadline = datetime.utcnow() - timedelta(hours=BreachService.NOTIFICATION_DEADLINE_HOURS)
        
        return db.query(DataBreach).filter(
            DataBreach.status.in_([BreachStatus.detected, BreachStatus.investigating]),
            DataBreach.detected_at < deadline
        ).all()

breach_service = BreachService()

