// Maintenance Window Access Control Policy
// Restricts certain operations to designated maintenance windows
// Compliance: ITIL Service Management, Change Control

// Allow maintenance operations during designated windows
permit(
    principal,
    action in [Action::"maintenance", Action::"patch", Action::"upgrade", Action::"backup"],
    resource
) when {
    // Check if we're in a scheduled maintenance window
    (
        context has maintenance_window &&
        context.maintenance_window.active == true &&
        context.time.hour >= context.maintenance_window.start_hour &&
        context.time.hour < context.maintenance_window.end_hour &&
        context.time.day_of_week in context.maintenance_window.allowed_days
    ) ||
    // Or if it's an emergency maintenance with proper authorization
    (
        principal has emergency_maintenance &&
        principal.emergency_maintenance.authorized == true &&
        principal.emergency_maintenance.expires_at > context.time.timestamp &&
        principal.emergency_maintenance.incident_severity in ["critical", "high"]
    )
};

// Allow critical system operations during maintenance windows
permit(
    principal,
    action in [Action::"restart", Action::"scale", Action::"deploy"],
    resource
) when {
    resource has maintenance_category &&
    resource.maintenance_category in ["critical", "system"] &&
    context has maintenance_window &&
    context.maintenance_window.active == true &&
    context.time.hour >= context.maintenance_window.start_hour &&
    context.time.hour < context.maintenance_window.end_hour &&
    principal has role &&
    principal.role in ["MaintenanceAdmin", "SystemOperator", "SRE"] &&
    principal has maintenance_ticket &&
    principal.maintenance_ticket != ""
};

// Standard business hours - restrict disruptive operations
forbid(
    principal,
    action in [Action::"restart", Action::"maintenance", Action::"patch", Action::"upgrade"],
    resource
) when {
    resource has criticality &&
    resource.criticality in ["high", "critical"] &&
    context.time.hour >= 8 && // Business hours: 8 AM to 6 PM
    context.time.hour < 18 &&
    context.time.day_of_week >= 1 && // Monday to Friday
    context.time.day_of_week <= 5 &&
    !(
        principal has emergency_maintenance &&
        principal.emergency_maintenance.authorized == true
    ) &&
    !(
        context has maintenance_window &&
        context.maintenance_window.active == true
    )
};

// Weekend maintenance windows - more permissive
permit(
    principal,
    action in [Action::"maintenance", Action::"patch", Action::"upgrade", Action::"backup"],
    resource
) when {
    (context.time.day_of_week == 0 || context.time.day_of_week == 6) && // Saturday or Sunday
    context.time.hour >= 2 && // 2 AM to 8 AM weekend window
    context.time.hour < 8 &&
    principal has role &&
    principal.role in ["MaintenanceTeam", "SRE", "SystemAdmin"] &&
    principal has weekend_maintenance_approval &&
    principal.weekend_maintenance_approval.valid == true
};

// Database maintenance - special restrictions
permit(
    principal,
    action in [Action::"backup", Action::"maintenance", Action::"patch"],
    resource
) when {
    resource has resource_type &&
    resource.resource_type == "Database" &&
    (
        // During designated DB maintenance window
        (
            context has db_maintenance_window &&
            context.db_maintenance_window.active == true &&
            context.time.hour >= context.db_maintenance_window.start_hour &&
            context.time.hour < context.db_maintenance_window.end_hour
        ) ||
        // Or with DBA approval for urgent maintenance
        (
            principal has dba_approval &&
            principal.dba_approval.granted == true &&
            principal.dba_approval.expires_at > context.time.timestamp &&
            principal.dba_approval.maintenance_type in ["critical_patch", "emergency_backup"]
        )
    ) &&
    principal has role &&
    principal.role in ["DBA", "DatabaseAdmin", "BackupOperator"]
};

// Monitoring and alerting - always allowed
permit(
    principal,
    action in [Action::"read", Action::"monitor", Action::"alert"],
    resource
) when {
    principal has role &&
    principal.role in ["MonitoringService", "AlertManager", "Observer"]
};