use serde::{Deserialize, Serialize};
use chrono::{DateTime, Utc};
use std::collections::HashMap;

/// Cedar policy structure
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CedarPolicy {
    pub id: String,
    pub name: String,
    pub description: Option<String>,
    pub content: String,
    pub version: u32,
    pub status: PolicyStatus,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub created_by: String,
    pub updated_by: String,
    pub tags: Vec<String>,
    pub category: PolicyCategory,
    pub effect: PolicyEffect,
    pub priority: i32,
    pub conditions: Vec<String>,
}

/// Policy status enumeration
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PolicyStatus {
    Draft,
    PendingReview,
    Approved,
    Active,
    Deprecated,
    Archived,
}

/// Policy categories for organization
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PolicyCategory {
    AccessControl,
    DataProtection,
    ResourceManagement,
    Compliance,
    Security,
    Audit,
    Custom(String),
}

/// Policy effect (permit/forbid)
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PolicyEffect {
    Permit,
    Forbid,
}

/// Policy template for common patterns
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyTemplate {
    pub id: String,
    pub name: String,
    pub description: String,
    pub category: PolicyCategory,
    pub template: String,
    pub variables: Vec<TemplateVariable>,
    pub example_values: HashMap<String, String>,
    pub use_count: u32,
    pub tags: Vec<String>,
}

/// Template variable definition
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemplateVariable {
    pub name: String,
    pub description: String,
    pub var_type: VariableType,
    pub required: bool,
    pub default_value: Option<String>,
    pub validation_pattern: Option<String>,
}

/// Variable types for templates
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VariableType {
    String,
    Number,
    Boolean,
    Array,
    Object,
    Principal,
    Resource,
    Action,
}

/// Test data for policy evaluation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyTestData {
    pub id: String,
    pub name: String,
    pub description: String,
    pub principal: TestPrincipal,
    pub resource: TestResource,
    pub action: TestAction,
    pub context: HashMap<String, serde_json::Value>,
    pub expected_result: Option<bool>,
}

/// Test principal (user/role/service)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestPrincipal {
    pub id: String,
    pub principal_type: String,
    pub attributes: HashMap<String, serde_json::Value>,
}

/// Test resource
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestResource {
    pub id: String,
    pub resource_type: String,
    pub attributes: HashMap<String, serde_json::Value>,
}

/// Test action
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TestAction {
    pub id: String,
    pub attributes: HashMap<String, serde_json::Value>,
}

/// Evaluation result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvaluationResult {
    pub policy_id: String,
    pub test_case_id: String,
    pub result: PolicyDecision,
    pub execution_time_ms: u64,
    pub reasoning: Option<String>,
    pub errors: Vec<String>,
    pub warnings: Vec<String>,
}

/// Policy decision
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PolicyDecision {
    Permit,
    Deny,
    Error(String),
}

/// Impact analysis result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ImpactAnalysis {
    pub policy_id: String,
    pub affected_users: Vec<String>,
    pub affected_resources: Vec<String>,
    pub affected_actions: Vec<String>,
    pub risk_level: RiskLevel,
    pub estimated_changes: u32,
    pub recommendations: Vec<String>,
}

/// Risk assessment levels
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RiskLevel {
    Low,
    Medium,
    High,
    Critical,
}

/// Policy version information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyVersion {
    pub id: String,
    pub policy_id: String,
    pub version: u32,
    pub content: String,
    pub changes: Vec<PolicyChange>,
    pub created_at: DateTime<Utc>,
    pub created_by: String,
    pub commit_message: Option<String>,
    pub diff_stats: DiffStats,
}

/// Policy change record
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyChange {
    pub change_type: ChangeType,
    pub line_number: Option<u32>,
    pub old_content: Option<String>,
    pub new_content: Option<String>,
    pub description: String,
}

/// Change types for versioning
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ChangeType {
    Add,
    Remove,
    Modify,
    Move,
}

/// Diff statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiffStats {
    pub lines_added: u32,
    pub lines_removed: u32,
    pub lines_modified: u32,
    pub total_changes: u32,
}

/// Approval workflow stage
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApprovalStage {
    pub id: String,
    pub name: String,
    pub approvers: Vec<String>,
    pub required_approvals: u32,
    pub current_approvals: Vec<Approval>,
    pub status: ApprovalStatus,
    pub deadline: Option<DateTime<Utc>>,
}

/// Individual approval
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Approval {
    pub approver_id: String,
    pub approved_at: DateTime<Utc>,
    pub comment: Option<String>,
    pub decision: ApprovalDecision,
}

/// Approval decisions
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ApprovalDecision {
    Approve,
    Reject,
    RequestChanges,
}

/// Approval status
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ApprovalStatus {
    Pending,
    Approved,
    Rejected,
    ChangesRequested,
}

/// Policy metrics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyMetrics {
    pub policy_id: String,
    pub total_evaluations: u64,
    pub permit_count: u64,
    pub deny_count: u64,
    pub error_count: u64,
    pub avg_execution_time_ms: f64,
    pub last_evaluation: Option<DateTime<Utc>>,
    pub effectiveness_score: f64,
    pub usage_trends: Vec<UsageTrend>,
}

/// Usage trend data point
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UsageTrend {
    pub date: DateTime<Utc>,
    pub evaluations: u64,
    pub permits: u64,
    pub denies: u64,
    pub errors: u64,
}

/// Violation information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PolicyViolation {
    pub id: String,
    pub policy_id: String,
    pub violation_type: ViolationType,
    pub description: String,
    pub severity: ViolationSeverity,
    pub detected_at: DateTime<Utc>,
    pub context: HashMap<String, serde_json::Value>,
    pub suggested_fix: Option<String>,
    pub related_policies: Vec<String>,
}

/// Violation types
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ViolationType {
    SyntaxError,
    LogicConflict,
    UnreachableRule,
    MissingCondition,
    SecurityGap,
    PerformanceIssue,
}

/// Violation severity levels
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ViolationSeverity {
    Info,
    Warning,
    Error,
    Critical,
}

/// Role mining suggestion
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RoleSuggestion {
    pub id: String,
    pub suggested_role: String,
    pub description: String,
    pub confidence_score: f64,
    pub supporting_patterns: Vec<AccessPattern>,
    pub affected_users: Vec<String>,
    pub potential_policies: Vec<String>,
}

/// Access pattern for role mining
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AccessPattern {
    pub pattern_type: PatternType,
    pub frequency: u64,
    pub resources: Vec<String>,
    pub actions: Vec<String>,
    pub time_pattern: Option<String>,
}

/// Pattern types for access analysis
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PatternType {
    Frequent,
    Scheduled,
    GroupBased,
    ResourceSpecific,
    Temporal,
}

/// What-if simulation scenario
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimulationScenario {
    pub id: String,
    pub name: String,
    pub description: String,
    pub policy_changes: Vec<PolicyChange>,
    pub test_data: Vec<PolicyTestData>,
    pub expected_impact: ImpactAnalysis,
    pub created_at: DateTime<Utc>,
    pub created_by: String,
}

/// Simulation result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimulationResult {
    pub scenario_id: String,
    pub results: Vec<EvaluationResult>,
    pub impact_analysis: ImpactAnalysis,
    pub performance_metrics: HashMap<String, f64>,
    pub recommendations: Vec<String>,
    pub risk_assessment: RiskLevel,
}
