"""
Financial approval model for tracking high-risk financial operations that require approval.
Implements segregation of duties - users cannot approve their own actions.
"""
from sqlalchemy import Column, Integer, String, DateTime, Numeric, Text, Enum, ForeignKey, JSON, Index
from sqlalchemy.orm import relationship
from datetime import datetime
import enum
from ...shared.config.database import Base


class ApprovalStatus(str, enum.Enum):
    """Status of an approval request."""
    pending = 'pending'
    approved = 'approved'
    rejected = 'rejected'
    cancelled = 'cancelled'


class ApprovalActionType(str, enum.Enum):
    """Types of actions that require approval."""
    large_refund = 'large_refund'
    payment_status_override = 'payment_status_override'
    invoice_write_off = 'invoice_write_off'
    large_discount = 'large_discount'
    tax_rate_change = 'tax_rate_change'
    manual_payment_adjustment = 'manual_payment_adjustment'


class FinancialApproval(Base):
    """Approval request for high-risk financial operations."""
    __tablename__ = 'financial_approvals'
    
    id = Column(Integer, primary_key=True, index=True, autoincrement=True)
    
    # Action details
    action_type = Column(Enum(ApprovalActionType), nullable=False, index=True)
    action_description = Column(Text, nullable=False)
    status = Column(Enum(ApprovalStatus), default=ApprovalStatus.pending, nullable=False, index=True)
    
    # Related entities
    payment_id = Column(Integer, ForeignKey('payments.id'), nullable=True, index=True)
    invoice_id = Column(Integer, ForeignKey('invoices.id'), nullable=True, index=True)
    booking_id = Column(Integer, ForeignKey('bookings.id'), nullable=True, index=True)
    
    # Financial details
    amount = Column(Numeric(10, 2), nullable=True)
    previous_value = Column(JSON, nullable=True)  # Store previous state (e.g., old status, old amount)
    new_value = Column(JSON, nullable=True)  # Store new state
    
    # Request details
    requested_by = Column(Integer, ForeignKey('users.id'), nullable=False, index=True)
    requested_by_email = Column(String(255), nullable=True)  # Store email for audit even if user deleted
    request_reason = Column(Text, nullable=True)
    
    # Approval details
    approved_by = Column(Integer, ForeignKey('users.id'), nullable=True, index=True)
    approved_by_email = Column(String(255), nullable=True)
    approval_notes = Column(Text, nullable=True)
    approved_at = Column(DateTime, nullable=True)
    
    # Rejection details
    rejected_by = Column(Integer, ForeignKey('users.id'), nullable=True)
    rejection_reason = Column(Text, nullable=True)
    rejected_at = Column(DateTime, nullable=True)
    
    # Additional context
    approval_metadata = Column(JSON, nullable=True)  # Store additional context (IP, user agent, thresholds, etc.)
    
    # Timestamps
    created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
    updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
    
    # Relationships
    payment = relationship('Payment', foreign_keys=[payment_id])
    invoice = relationship('Invoice', foreign_keys=[invoice_id])
    booking = relationship('Booking', foreign_keys=[booking_id])
    requester = relationship('User', foreign_keys=[requested_by])
    approver = relationship('User', foreign_keys=[approved_by])
    rejector = relationship('User', foreign_keys=[rejected_by])
    
    # Indexes for common queries
    __table_args__ = (
        Index('idx_financial_approval_status', 'status', 'created_at'),
        Index('idx_financial_approval_action', 'action_type', 'status'),
        Index('idx_financial_approval_requester', 'requested_by', 'status'),
        Index('idx_financial_approval_approver', 'approved_by', 'created_at'),
    )

