# ================================================================
# services/orders/app/models/order.py
# ================================================================
"""
Order-related database models for Orders Service
"""

import uuid
from datetime import datetime
from decimal import Decimal
from typing import Optional, List
from sqlalchemy import Column, String, Boolean, DateTime, Numeric, Text, ForeignKey, Integer
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func

from shared.database.base import Base


class CustomerOrder(Base):
    """Customer order model for tracking orders throughout their lifecycle"""
    __tablename__ = "customer_orders"
    
    # Primary identification
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
    order_number = Column(String(50), nullable=False, unique=True, index=True)
    
    # Customer information
    customer_id = Column(UUID(as_uuid=True), ForeignKey("customers.id"), nullable=False, index=True)
    
    # Order status and lifecycle
    status = Column(String(50), nullable=False, default="pending", index=True)
    # Status values: pending, confirmed, in_production, ready, out_for_delivery, delivered, cancelled, failed
    
    order_type = Column(String(50), nullable=False, default="standard")  # standard, rush, recurring, special
    priority = Column(String(20), nullable=False, default="normal")  # high, normal, low
    
    # Order timing
    order_date = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    requested_delivery_date = Column(DateTime(timezone=True), nullable=False)
    confirmed_delivery_date = Column(DateTime(timezone=True), nullable=True)
    actual_delivery_date = Column(DateTime(timezone=True), nullable=True)
    
    # Delivery information
    delivery_method = Column(String(50), nullable=False, default="delivery")  # delivery, pickup
    delivery_address = Column(JSONB, nullable=True)  # Complete delivery address
    delivery_instructions = Column(Text, nullable=True)
    delivery_window_start = Column(DateTime(timezone=True), nullable=True)
    delivery_window_end = Column(DateTime(timezone=True), nullable=True)
    
    # Financial information
    subtotal = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    discount_amount = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    discount_percentage = Column(Numeric(5, 2), nullable=False, default=Decimal("0.00"))
    tax_amount = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    delivery_fee = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    total_amount = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    
    # Payment information
    payment_status = Column(String(50), nullable=False, default="pending")  # pending, partial, paid, failed, refunded
    payment_method = Column(String(50), nullable=True)  # cash, card, bank_transfer, account
    payment_terms = Column(String(50), nullable=False, default="immediate")
    payment_due_date = Column(DateTime(timezone=True), nullable=True)
    
    # Special requirements and customizations
    special_instructions = Column(Text, nullable=True)
    custom_requirements = Column(JSONB, nullable=True)  # Special dietary requirements, decorations
    allergen_warnings = Column(JSONB, nullable=True)  # Allergen information
    
    # Business model detection
    business_model = Column(String(50), nullable=True)  # individual_bakery, central_bakery (auto-detected)
    estimated_business_model = Column(String(50), nullable=True)  # Based on order patterns
    
    # Order source and channel
    order_source = Column(String(50), nullable=False, default="manual")  # manual, online, phone, app, api
    sales_channel = Column(String(50), nullable=False, default="direct")  # direct, wholesale, retail
    order_origin = Column(String(100), nullable=True)  # Website, app, store location
    
    # Fulfillment tracking
    production_batch_id = Column(UUID(as_uuid=True), nullable=True)  # Link to production batch
    fulfillment_location = Column(String(100), nullable=True)  # Which location fulfills this order
    estimated_preparation_time = Column(Integer, nullable=True)  # Minutes
    actual_preparation_time = Column(Integer, nullable=True)  # Minutes
    
    # Customer communication
    customer_notified_confirmed = Column(Boolean, nullable=False, default=False)
    customer_notified_ready = Column(Boolean, nullable=False, default=False)
    customer_notified_delivered = Column(Boolean, nullable=False, default=False)
    communication_preferences = Column(JSONB, nullable=True)
    
    # Quality and feedback
    quality_score = Column(Numeric(3, 1), nullable=True)  # 1.0 to 10.0
    customer_rating = Column(Integer, nullable=True)  # 1-5 stars
    customer_feedback = Column(Text, nullable=True)
    
    # Cancellation and refunds
    cancellation_reason = Column(String(200), nullable=True)
    cancelled_at = Column(DateTime(timezone=True), nullable=True)
    cancelled_by = Column(UUID(as_uuid=True), nullable=True)
    refund_amount = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    refund_processed_at = Column(DateTime(timezone=True), nullable=True)
    
    # Audit fields
    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)
    created_by = Column(UUID(as_uuid=True), nullable=True)
    updated_by = Column(UUID(as_uuid=True), nullable=True)
    
    # Additional metadata
    order_metadata = Column(JSONB, nullable=True)  # Flexible field for additional data
    
    # Relationships
    customer = relationship("Customer", back_populates="orders")
    items = relationship("OrderItem", back_populates="order", cascade="all, delete-orphan")
    status_history = relationship("OrderStatusHistory", back_populates="order", cascade="all, delete-orphan")


class OrderItem(Base):
    """Individual items within a customer order"""
    __tablename__ = "order_items"
    
    # Primary identification
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    order_id = Column(UUID(as_uuid=True), ForeignKey("customer_orders.id", ondelete="CASCADE"), nullable=False)
    
    # Product information
    product_id = Column(UUID(as_uuid=True), nullable=False, index=True)  # Reference to products service
    product_name = Column(String(200), nullable=False)
    product_sku = Column(String(100), nullable=True)
    product_category = Column(String(100), nullable=True)
    
    # Quantity and units
    quantity = Column(Numeric(10, 3), nullable=False)
    unit_of_measure = Column(String(50), nullable=False, default="each")
    weight = Column(Numeric(10, 3), nullable=True)  # For weight-based products
    
    # Pricing information
    unit_price = Column(Numeric(10, 2), nullable=False)
    line_discount = Column(Numeric(10, 2), nullable=False, default=Decimal("0.00"))
    line_total = Column(Numeric(10, 2), nullable=False)
    
    # Product specifications and customizations
    product_specifications = Column(JSONB, nullable=True)  # Size, flavor, decorations
    customization_details = Column(Text, nullable=True)
    special_instructions = Column(Text, nullable=True)
    
    # Production requirements
    recipe_id = Column(UUID(as_uuid=True), nullable=True)  # Reference to recipes service
    production_requirements = Column(JSONB, nullable=True)  # Ingredients, equipment needed
    estimated_production_time = Column(Integer, nullable=True)  # Minutes
    
    # Fulfillment tracking
    status = Column(String(50), nullable=False, default="pending")  # pending, in_production, ready, delivered
    production_started_at = Column(DateTime(timezone=True), nullable=True)
    production_completed_at = Column(DateTime(timezone=True), nullable=True)
    quality_checked = Column(Boolean, nullable=False, default=False)
    quality_score = Column(Numeric(3, 1), nullable=True)
    
    # Cost tracking
    ingredient_cost = Column(Numeric(10, 2), nullable=True)
    labor_cost = Column(Numeric(10, 2), nullable=True)
    overhead_cost = Column(Numeric(10, 2), nullable=True)
    total_cost = Column(Numeric(10, 2), nullable=True)
    margin = Column(Numeric(10, 2), nullable=True)
    
    # Inventory impact
    reserved_inventory = Column(Boolean, nullable=False, default=False)
    inventory_allocated_at = Column(DateTime(timezone=True), nullable=True)
    
    # Audit fields
    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)
    
    # Additional metadata
    customer_metadata = Column(JSONB, nullable=True)
    
    # Relationships
    order = relationship("CustomerOrder", back_populates="items")


class OrderStatusHistory(Base):
    """Track status changes and important events in order lifecycle"""
    __tablename__ = "order_status_history"
    
    # Primary identification
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    order_id = Column(UUID(as_uuid=True), ForeignKey("customer_orders.id", ondelete="CASCADE"), nullable=False)
    
    # Status change information
    from_status = Column(String(50), nullable=True)
    to_status = Column(String(50), nullable=False)
    change_reason = Column(String(200), nullable=True)
    
    # Event details
    event_type = Column(String(50), nullable=False, default="status_change")
    # Event types: status_change, payment_received, production_started, delivery_scheduled, etc.
    
    event_description = Column(Text, nullable=True)
    event_data = Column(JSONB, nullable=True)  # Additional event-specific data
    
    # Who made the change
    changed_by = Column(UUID(as_uuid=True), nullable=True)
    change_source = Column(String(50), nullable=False, default="manual")  # manual, automatic, system, api
    
    # Timing
    changed_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    
    # Customer communication
    customer_notified = Column(Boolean, nullable=False, default=False)
    notification_method = Column(String(50), nullable=True)  # email, sms, phone, app
    notification_sent_at = Column(DateTime(timezone=True), nullable=True)
    
    # Additional notes
    notes = Column(Text, nullable=True)
    
    # Relationships
    order = relationship("CustomerOrder", back_populates="status_history")