# services/pos/app/models/pos_transaction.py
"""
POS Transaction Models
Stores transaction data from POS systems
"""

from sqlalchemy import Column, String, DateTime, Boolean, Numeric, Integer, Text, JSON, Index, ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
import uuid

from shared.database.base import Base


class POSTransaction(Base):
    """
    Main transaction record from POS systems
    """
    __tablename__ = "pos_transactions"
    
    # Primary identifiers
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    pos_config_id = Column(UUID(as_uuid=True), ForeignKey("pos_configurations.id"), nullable=False, index=True)
    
    # POS Provider Information
    pos_system = Column(String(50), nullable=False, index=True)  # square, toast, lightspeed
    external_transaction_id = Column(String(255), nullable=False, index=True)  # POS system's transaction ID
    external_order_id = Column(String(255), nullable=True, index=True)  # POS system's order ID
    
    # Transaction Details
    transaction_type = Column(String(50), nullable=False)  # sale, refund, void, exchange
    status = Column(String(50), nullable=False)  # completed, pending, failed, refunded, voided
    
    # Financial Information
    subtotal = Column(Numeric(10, 2), nullable=False)
    tax_amount = Column(Numeric(10, 2), default=0, nullable=False)
    tip_amount = Column(Numeric(10, 2), default=0, nullable=False)
    discount_amount = Column(Numeric(10, 2), default=0, nullable=False)
    total_amount = Column(Numeric(10, 2), nullable=False)
    currency = Column(String(3), default="EUR", nullable=False)
    
    # Payment Information
    payment_method = Column(String(50), nullable=True)  # card, cash, digital_wallet, etc.
    payment_status = Column(String(50), nullable=True)  # paid, pending, failed
    
    # Transaction Timing
    transaction_date = Column(DateTime(timezone=True), nullable=False, index=True)
    pos_created_at = Column(DateTime(timezone=True), nullable=False)  # Original POS timestamp
    pos_updated_at = Column(DateTime(timezone=True), nullable=True)   # Last update in POS
    
    # Location & Staff
    location_id = Column(String(100), nullable=True)
    location_name = Column(String(255), nullable=True)
    staff_id = Column(String(100), nullable=True)
    staff_name = Column(String(255), nullable=True)
    
    # Customer Information
    customer_id = Column(String(100), nullable=True)
    customer_email = Column(String(255), nullable=True)
    customer_phone = Column(String(50), nullable=True)
    
    # Order Context
    order_type = Column(String(50), nullable=True)  # dine_in, takeout, delivery, pickup
    table_number = Column(String(20), nullable=True)
    receipt_number = Column(String(100), nullable=True)
    
    # Sync Status
    is_synced_to_sales = Column(Boolean, default=False, nullable=False, index=True)
    sales_record_id = Column(UUID(as_uuid=True), nullable=True, index=True)  # Reference to sales service
    sync_attempted_at = Column(DateTime(timezone=True), nullable=True)
    sync_completed_at = Column(DateTime(timezone=True), nullable=True)
    sync_error = Column(Text, nullable=True)
    sync_retry_count = Column(Integer, default=0, nullable=False)
    
    # Raw Data
    raw_data = Column(JSON, nullable=True)  # Complete raw response from POS
    
    # Processing Status
    is_processed = Column(Boolean, default=False, nullable=False)
    processing_error = Column(Text, nullable=True)
    
    # Duplicate Detection
    is_duplicate = Column(Boolean, default=False, nullable=False)
    duplicate_of = Column(UUID(as_uuid=True), nullable=True)
    
    # Timestamps
    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
    
    # Relationships
    items = relationship("POSTransactionItem", back_populates="transaction", cascade="all, delete-orphan")
    
    # Indexes for performance
    __table_args__ = (
        Index('idx_pos_transaction_tenant_date', 'tenant_id', 'transaction_date'),
        Index('idx_pos_transaction_external_id', 'pos_system', 'external_transaction_id'),
        Index('idx_pos_transaction_sync_status', 'is_synced_to_sales'),
        Index('idx_pos_transaction_status', 'status'),
        Index('idx_pos_transaction_type', 'transaction_type'),
        Index('idx_pos_transaction_processed', 'is_processed'),
        Index('idx_pos_transaction_duplicate', 'is_duplicate'),
        Index('idx_pos_transaction_location', 'location_id'),
        Index('idx_pos_transaction_customer', 'customer_id'),
    )
    
    def __repr__(self):
        return f"<POSTransaction(id={self.id}, external_id='{self.external_transaction_id}', pos_system='{self.pos_system}', total={self.total_amount})>"


class POSTransactionItem(Base):
    """
    Individual items within a POS transaction
    """
    __tablename__ = "pos_transaction_items"
    
    # Primary identifiers
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    transaction_id = Column(UUID(as_uuid=True), ForeignKey("pos_transactions.id"), nullable=False, index=True)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    
    # POS Item Information
    external_item_id = Column(String(255), nullable=True)  # POS system's item ID
    sku = Column(String(100), nullable=True, index=True)
    
    # Product Details
    product_name = Column(String(255), nullable=False)
    product_category = Column(String(100), nullable=True, index=True)
    product_subcategory = Column(String(100), nullable=True)
    
    # Quantity & Pricing
    quantity = Column(Numeric(10, 3), nullable=False)
    unit_price = Column(Numeric(10, 2), nullable=False)
    total_price = Column(Numeric(10, 2), nullable=False)
    
    # Discounts & Modifiers
    discount_amount = Column(Numeric(10, 2), default=0, nullable=False)
    tax_amount = Column(Numeric(10, 2), default=0, nullable=False)
    
    # Modifiers (e.g., extra shot, no foam for coffee)
    modifiers = Column(JSON, nullable=True)
    
    # Inventory Mapping
    inventory_product_id = Column(UUID(as_uuid=True), nullable=True, index=True)  # Mapped to inventory service
    is_mapped_to_inventory = Column(Boolean, default=False, nullable=False)
    
    # Sync Status
    is_synced_to_sales = Column(Boolean, default=False, nullable=False)
    sync_error = Column(Text, nullable=True)
    
    # Raw Data
    raw_data = Column(JSON, nullable=True)
    
    # Timestamps
    created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False)
    
    # Relationships
    transaction = relationship("POSTransaction", back_populates="items")
    
    # Indexes for performance
    __table_args__ = (
        Index('idx_pos_item_transaction', 'transaction_id'),
        Index('idx_pos_item_product', 'product_name'),
        Index('idx_pos_item_category', 'product_category'),
        Index('idx_pos_item_sku', 'sku'),
        Index('idx_pos_item_inventory', 'inventory_product_id'),
        Index('idx_pos_item_sync', 'is_synced_to_sales'),
        Index('idx_pos_item_mapped', 'is_mapped_to_inventory'),
    )
    
    def __repr__(self):
        return f"<POSTransactionItem(id={self.id}, product='{self.product_name}', quantity={self.quantity}, price={self.total_price})>"