//! Types for the PII detection module.

use serde::{Deserialize, Serialize};

/// Report from scanning an entire schema for PII columns.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PiiReport {
    /// Per-column PII classification results.
    pub columns: Vec<PiiColumnResult>,
    /// Number of columns classified as PII.
    pub pii_count: usize,
    /// Total number of columns scanned.
    pub total_columns: usize,
    /// Overall risk level for the schema.
    pub risk_level: PiiRiskLevel,
}

/// PII classification result for a single column.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PiiColumnResult {
    /// Table name.
    pub table: String,
    /// Column name.
    pub column: String,
    /// PII classification.
    pub classification: PiiClassification,
    /// Confidence score (0.0 to 1.0).
    pub confidence: f64,
    /// How PII was detected (e.g., "name_pattern", "tag", "type_pattern").
    pub detection_method: String,
    /// Suggested masking expression for this column.
    pub suggested_masking: Option<String>,
}

/// PII classification categories.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum PiiClassification {
    /// Email address.
    Email,
    /// Phone number.
    Phone,
    /// Social Security Number.
    SSN,
    /// Person name (first, last, full).
    Name,
    /// Physical address.
    Address,
    /// Financial data (credit card, salary, etc.).
    Financial,
    /// Health-related data.
    Health,
    /// Date of birth.
    DateOfBirth,
    /// IP address.
    IPAddress,
    /// Custom PII category.
    Custom(String),
    /// Not PII.
    None,
}

/// Risk level for PII exposure.
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum PiiRiskLevel {
    /// No PII detected.
    None,
    /// Low risk (e.g., only names).
    Low,
    /// Medium risk (e.g., emails, phone numbers).
    Medium,
    /// High risk (e.g., SSNs, financial data).
    High,
}

/// Result of checking a query for PII column access.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PiiQueryResult {
    /// Whether the query accesses any PII columns.
    pub accesses_pii: bool,
    /// PII columns accessed by the query.
    pub pii_columns: Vec<PiiColumnAccess>,
    /// Suggested rewritten SQL with masking applied.
    pub suggested_alternatives: Vec<String>,
    /// Overall risk level for this query.
    pub risk_level: PiiRiskLevel,
}

/// A PII column accessed by a query.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PiiColumnAccess {
    /// Table name.
    pub table: String,
    /// Column name.
    pub column: String,
    /// PII classification of this column.
    pub classification: PiiClassification,
    /// Suggested masking expression.
    pub suggested_masking: Option<String>,
}

impl std::fmt::Display for PiiClassification {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PiiClassification::Email => write!(f, "email"),
            PiiClassification::Phone => write!(f, "phone"),
            PiiClassification::SSN => write!(f, "ssn"),
            PiiClassification::Name => write!(f, "name"),
            PiiClassification::Address => write!(f, "address"),
            PiiClassification::Financial => write!(f, "financial"),
            PiiClassification::Health => write!(f, "health"),
            PiiClassification::DateOfBirth => write!(f, "date_of_birth"),
            PiiClassification::IPAddress => write!(f, "ip_address"),
            PiiClassification::Custom(s) => write!(f, "custom:{s}"),
            PiiClassification::None => write!(f, "none"),
        }
    }
}

impl std::fmt::Display for PiiRiskLevel {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            PiiRiskLevel::None => write!(f, "none"),
            PiiRiskLevel::Low => write!(f, "low"),
            PiiRiskLevel::Medium => write!(f, "medium"),
            PiiRiskLevel::High => write!(f, "high"),
        }
    }
}

impl PiiClassification {
    /// Returns the inherent risk level for this classification.
    pub fn risk_level(&self) -> PiiRiskLevel {
        match self {
            PiiClassification::SSN | PiiClassification::Financial => PiiRiskLevel::High,
            PiiClassification::Email
            | PiiClassification::Phone
            | PiiClassification::DateOfBirth
            | PiiClassification::IPAddress
            | PiiClassification::Health => PiiRiskLevel::Medium,
            PiiClassification::Name | PiiClassification::Address => PiiRiskLevel::Low,
            PiiClassification::Custom(_) => PiiRiskLevel::Medium,
            PiiClassification::None => PiiRiskLevel::None,
        }
    }
}
