# ================================================================
# services/suppliers/app/models/performance.py
# ================================================================
"""
Supplier Performance Tracking and Alert Models for Suppliers Service
Comprehensive supplier performance metrics, KPIs, and alert management
"""

from sqlalchemy import Column, String, DateTime, Float, Integer, Text, Index, Boolean, Numeric, ForeignKey, Enum as SQLEnum
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.orm import relationship
import uuid
import enum
from datetime import datetime, timezone
from typing import Dict, Any, Optional, List
from decimal import Decimal

from shared.database.base import Base


class AlertSeverity(enum.Enum):
    """Alert severity levels"""
    CRITICAL = "critical"
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"
    INFO = "info"


class AlertType(enum.Enum):
    """Types of supplier alerts"""
    POOR_QUALITY = "poor_quality"
    LATE_DELIVERY = "late_delivery"
    PRICE_INCREASE = "price_increase"
    LOW_PERFORMANCE = "low_performance"
    CONTRACT_EXPIRY = "contract_expiry"
    COMPLIANCE_ISSUE = "compliance_issue"
    FINANCIAL_RISK = "financial_risk"
    COMMUNICATION_ISSUE = "communication_issue"
    CAPACITY_CONSTRAINT = "capacity_constraint"
    CERTIFICATION_EXPIRY = "certification_expiry"


class AlertStatus(enum.Enum):
    """Alert processing status"""
    ACTIVE = "active"
    ACKNOWLEDGED = "acknowledged"
    IN_PROGRESS = "in_progress"
    RESOLVED = "resolved"
    DISMISSED = "dismissed"


class PerformanceMetricType(enum.Enum):
    """Types of performance metrics"""
    DELIVERY_PERFORMANCE = "delivery_performance"
    QUALITY_SCORE = "quality_score"
    PRICE_COMPETITIVENESS = "price_competitiveness"
    COMMUNICATION_RATING = "communication_rating"
    ORDER_ACCURACY = "order_accuracy"
    RESPONSE_TIME = "response_time"
    COMPLIANCE_SCORE = "compliance_score"
    FINANCIAL_STABILITY = "financial_stability"


class PerformancePeriod(enum.Enum):
    """Performance measurement periods"""
    DAILY = "daily"
    WEEKLY = "weekly"
    MONTHLY = "monthly"
    QUARTERLY = "quarterly"
    YEARLY = "yearly"


class SupplierPerformanceMetric(Base):
    """Supplier performance metrics tracking"""
    __tablename__ = "supplier_performance_metrics"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    supplier_id = Column(UUID(as_uuid=True), ForeignKey('suppliers.id'), nullable=False, index=True)
    
    # Metric details
    metric_type = Column(SQLEnum(PerformanceMetricType), nullable=False, index=True)
    period = Column(SQLEnum(PerformancePeriod), nullable=False, index=True)
    period_start = Column(DateTime(timezone=True), nullable=False, index=True)
    period_end = Column(DateTime(timezone=True), nullable=False, index=True)
    
    # Performance values
    metric_value = Column(Float, nullable=False)  # Main metric value (0-100 scale)
    target_value = Column(Float, nullable=True)   # Target/benchmark value
    previous_value = Column(Float, nullable=True) # Previous period value for comparison
    
    # Supporting data
    total_orders = Column(Integer, nullable=False, default=0)
    total_deliveries = Column(Integer, nullable=False, default=0)
    on_time_deliveries = Column(Integer, nullable=False, default=0)
    late_deliveries = Column(Integer, nullable=False, default=0)
    quality_issues = Column(Integer, nullable=False, default=0)
    total_amount = Column(Numeric(12, 2), nullable=False, default=0.0)
    
    # Detailed metrics breakdown
    metrics_data = Column(JSONB, nullable=True)  # Detailed breakdown of calculations
    
    # Performance trends
    trend_direction = Column(String(20), nullable=True)  # improving, declining, stable
    trend_percentage = Column(Float, nullable=True)      # % change from previous period
    
    # Contextual information
    notes = Column(Text, nullable=True)
    external_factors = Column(JSONB, nullable=True)  # External factors affecting performance
    
    # Audit fields
    calculated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    calculated_by = Column(UUID(as_uuid=True), nullable=True)  # System or user ID
    
    # Relationships
    supplier = relationship("Supplier")
    
    # Indexes
    __table_args__ = (
        Index('ix_performance_metrics_tenant_supplier', 'tenant_id', 'supplier_id'),
        Index('ix_performance_metrics_type_period', 'metric_type', 'period'),
        Index('ix_performance_metrics_period_dates', 'period_start', 'period_end'),
        Index('ix_performance_metrics_value', 'metric_value'),
    )


class SupplierAlert(Base):
    """Supplier-related alerts and notifications"""
    __tablename__ = "supplier_alerts"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    supplier_id = Column(UUID(as_uuid=True), ForeignKey('suppliers.id'), nullable=False, index=True)
    
    # Alert classification
    alert_type = Column(SQLEnum(AlertType), nullable=False, index=True)
    severity = Column(SQLEnum(AlertSeverity), nullable=False, index=True)
    status = Column(SQLEnum(AlertStatus), nullable=False, default=AlertStatus.ACTIVE, index=True)
    
    # Alert content
    title = Column(String(255), nullable=False)
    message = Column(Text, nullable=False)
    description = Column(Text, nullable=True)
    
    # Alert triggers and context
    trigger_value = Column(Float, nullable=True)     # The value that triggered the alert
    threshold_value = Column(Float, nullable=True)   # The threshold that was exceeded
    metric_type = Column(SQLEnum(PerformanceMetricType), nullable=True, index=True)
    
    # Related entities
    purchase_order_id = Column(UUID(as_uuid=True), nullable=True, index=True)
    delivery_id = Column(UUID(as_uuid=True), nullable=True, index=True)
    performance_metric_id = Column(UUID(as_uuid=True), ForeignKey('supplier_performance_metrics.id'), nullable=True)
    
    # Alert lifecycle
    triggered_at = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc))
    acknowledged_at = Column(DateTime(timezone=True), nullable=True)
    acknowledged_by = Column(UUID(as_uuid=True), nullable=True)
    resolved_at = Column(DateTime(timezone=True), nullable=True)
    resolved_by = Column(UUID(as_uuid=True), nullable=True)
    
    # Actions and resolution
    recommended_actions = Column(JSONB, nullable=True)  # Suggested actions
    actions_taken = Column(JSONB, nullable=True)        # Actions that were taken
    resolution_notes = Column(Text, nullable=True)
    
    # Auto-resolution
    auto_resolve = Column(Boolean, nullable=False, default=False)
    auto_resolve_condition = Column(JSONB, nullable=True)  # Conditions for auto-resolution
    
    # Escalation
    escalated = Column(Boolean, nullable=False, default=False)
    escalated_at = Column(DateTime(timezone=True), nullable=True)
    escalated_to = Column(UUID(as_uuid=True), nullable=True)  # User/role escalated to
    
    # Notification tracking
    notification_sent = Column(Boolean, nullable=False, default=False)
    notification_sent_at = Column(DateTime(timezone=True), nullable=True)
    notification_recipients = Column(JSONB, nullable=True)  # List of recipients
    
    # Additional metadata
    priority_score = Column(Integer, nullable=False, default=50)  # 1-100 priority scoring
    business_impact = Column(String(50), nullable=True)          # high, medium, low impact
    tags = Column(JSONB, nullable=True)                          # Categorization tags
    
    # Audit fields
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
    created_by = Column(UUID(as_uuid=True), nullable=True)
    
    # Relationships
    supplier = relationship("Supplier")
    performance_metric = relationship("SupplierPerformanceMetric")
    
    # Indexes
    __table_args__ = (
        Index('ix_supplier_alerts_tenant_supplier', 'tenant_id', 'supplier_id'),
        Index('ix_supplier_alerts_type_severity', 'alert_type', 'severity'),
        Index('ix_supplier_alerts_status_triggered', 'status', 'triggered_at'),
        Index('ix_supplier_alerts_metric_type', 'metric_type'),
        Index('ix_supplier_alerts_priority', 'priority_score'),
    )


class SupplierScorecard(Base):
    """Comprehensive supplier scorecards for performance evaluation"""
    __tablename__ = "supplier_scorecards"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    supplier_id = Column(UUID(as_uuid=True), ForeignKey('suppliers.id'), nullable=False, index=True)
    
    # Scorecard details
    scorecard_name = Column(String(255), nullable=False)
    period = Column(SQLEnum(PerformancePeriod), nullable=False, index=True)
    period_start = Column(DateTime(timezone=True), nullable=False, index=True)
    period_end = Column(DateTime(timezone=True), nullable=False, index=True)
    
    # Overall performance scores
    overall_score = Column(Float, nullable=False)           # Weighted overall score (0-100)
    quality_score = Column(Float, nullable=False)           # Quality performance (0-100)
    delivery_score = Column(Float, nullable=False)          # Delivery performance (0-100)
    cost_score = Column(Float, nullable=False)              # Cost competitiveness (0-100)
    service_score = Column(Float, nullable=False)           # Service quality (0-100)
    
    # Performance rankings
    overall_rank = Column(Integer, nullable=True)           # Rank among all suppliers
    category_rank = Column(Integer, nullable=True)          # Rank within supplier category
    total_suppliers_evaluated = Column(Integer, nullable=True)
    
    # Detailed performance breakdown
    on_time_delivery_rate = Column(Float, nullable=False)   # % of on-time deliveries
    quality_rejection_rate = Column(Float, nullable=False)  # % of quality rejections
    order_accuracy_rate = Column(Float, nullable=False)     # % of accurate orders
    response_time_hours = Column(Float, nullable=False)     # Average response time
    cost_variance_percentage = Column(Float, nullable=False) # Cost variance from budget
    
    # Business metrics
    total_orders_processed = Column(Integer, nullable=False, default=0)
    total_amount_processed = Column(Numeric(12, 2), nullable=False, default=0.0)
    average_order_value = Column(Numeric(10, 2), nullable=False, default=0.0)
    cost_savings_achieved = Column(Numeric(10, 2), nullable=False, default=0.0)
    
    # Performance trends
    score_trend = Column(String(20), nullable=True)         # improving, declining, stable
    score_change_percentage = Column(Float, nullable=True)   # % change from previous period
    
    # Recommendations and actions
    strengths = Column(JSONB, nullable=True)                # List of strengths
    improvement_areas = Column(JSONB, nullable=True)        # Areas for improvement
    recommended_actions = Column(JSONB, nullable=True)      # Recommended actions
    
    # Scorecard status
    is_final = Column(Boolean, nullable=False, default=False)
    approved_by = Column(UUID(as_uuid=True), nullable=True)
    approved_at = Column(DateTime(timezone=True), nullable=True)
    
    # Additional information
    notes = Column(Text, nullable=True)
    attachments = Column(JSONB, nullable=True)              # Supporting documents
    
    # Audit fields
    generated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    generated_by = Column(UUID(as_uuid=True), nullable=False)
    
    # Relationships
    supplier = relationship("Supplier")
    
    # Indexes
    __table_args__ = (
        Index('ix_scorecards_tenant_supplier', 'tenant_id', 'supplier_id'),
        Index('ix_scorecards_period_dates', 'period_start', 'period_end'),
        Index('ix_scorecards_overall_score', 'overall_score'),
        Index('ix_scorecards_period', 'period'),
        Index('ix_scorecards_final', 'is_final'),
    )


class SupplierBenchmark(Base):
    """Supplier performance benchmarks and industry standards"""
    __tablename__ = "supplier_benchmarks"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    
    # Benchmark details
    benchmark_name = Column(String(255), nullable=False)
    benchmark_type = Column(String(50), nullable=False, index=True)  # industry, internal, custom
    supplier_category = Column(String(100), nullable=True, index=True)  # Target supplier category
    
    # Metric thresholds
    metric_type = Column(SQLEnum(PerformanceMetricType), nullable=False, index=True)
    excellent_threshold = Column(Float, nullable=False)     # Excellent performance threshold
    good_threshold = Column(Float, nullable=False)          # Good performance threshold
    acceptable_threshold = Column(Float, nullable=False)    # Acceptable performance threshold
    poor_threshold = Column(Float, nullable=False)          # Poor performance threshold
    
    # Benchmark context
    data_source = Column(String(255), nullable=True)        # Source of benchmark data
    sample_size = Column(Integer, nullable=True)            # Sample size for benchmark
    confidence_level = Column(Float, nullable=True)         # Statistical confidence level
    
    # Validity and updates
    effective_date = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc))
    expiry_date = Column(DateTime(timezone=True), nullable=True)
    is_active = Column(Boolean, nullable=False, default=True)
    
    # Additional information
    description = Column(Text, nullable=True)
    methodology = Column(Text, nullable=True)
    notes = Column(Text, nullable=True)
    
    # Audit fields
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
    created_by = Column(UUID(as_uuid=True), nullable=False)
    
    # Indexes
    __table_args__ = (
        Index('ix_benchmarks_tenant_type', 'tenant_id', 'benchmark_type'),
        Index('ix_benchmarks_metric_type', 'metric_type'),
        Index('ix_benchmarks_category', 'supplier_category'),
        Index('ix_benchmarks_active', 'is_active'),
    )


class AlertRule(Base):
    """Configurable alert rules for supplier performance monitoring"""
    __tablename__ = "alert_rules"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    
    # Rule identification
    rule_name = Column(String(255), nullable=False)
    rule_description = Column(Text, nullable=True)
    is_active = Column(Boolean, nullable=False, default=True)
    
    # Alert configuration
    alert_type = Column(SQLEnum(AlertType), nullable=False, index=True)
    severity = Column(SQLEnum(AlertSeverity), nullable=False)
    metric_type = Column(SQLEnum(PerformanceMetricType), nullable=True, index=True)
    
    # Trigger conditions
    trigger_condition = Column(String(50), nullable=False)  # greater_than, less_than, equals, etc.
    threshold_value = Column(Float, nullable=False)
    consecutive_violations = Column(Integer, nullable=False, default=1)  # How many consecutive violations before alert
    
    # Scope and filters
    supplier_categories = Column(JSONB, nullable=True)      # Which supplier categories this applies to
    supplier_ids = Column(JSONB, nullable=True)            # Specific suppliers (if applicable)
    exclude_suppliers = Column(JSONB, nullable=True)       # Suppliers to exclude
    
    # Time constraints
    evaluation_period = Column(SQLEnum(PerformancePeriod), nullable=False)
    time_window_hours = Column(Integer, nullable=True)     # Time window for evaluation
    business_hours_only = Column(Boolean, nullable=False, default=False)
    
    # Auto-resolution
    auto_resolve = Column(Boolean, nullable=False, default=False)
    auto_resolve_threshold = Column(Float, nullable=True)   # Value at which alert auto-resolves
    auto_resolve_duration_hours = Column(Integer, nullable=True)  # How long condition must be met
    
    # Notification settings
    notification_enabled = Column(Boolean, nullable=False, default=True)
    notification_recipients = Column(JSONB, nullable=True)  # List of recipients
    escalation_minutes = Column(Integer, nullable=True)     # Minutes before escalation
    escalation_recipients = Column(JSONB, nullable=True)    # Escalation recipients
    
    # Action triggers
    recommended_actions = Column(JSONB, nullable=True)      # Actions to recommend
    auto_actions = Column(JSONB, nullable=True)            # Actions to automatically trigger
    
    # Rule metadata
    priority = Column(Integer, nullable=False, default=50)  # Rule priority (1-100)
    tags = Column(JSONB, nullable=True)                     # Classification tags
    
    # Audit fields
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
    created_by = Column(UUID(as_uuid=True), nullable=False)
    last_triggered = Column(DateTime(timezone=True), nullable=True)
    trigger_count = Column(Integer, nullable=False, default=0)
    
    # Indexes
    __table_args__ = (
        Index('ix_alert_rules_tenant_active', 'tenant_id', 'is_active'),
        Index('ix_alert_rules_type_severity', 'alert_type', 'severity'),
        Index('ix_alert_rules_metric_type', 'metric_type'),
        Index('ix_alert_rules_priority', 'priority'),
    )