"""
InventoryReservation model for tracking active inventory reservations.

This table is the durable source of truth for reservations. Redis is the
fast cache layer, but this table allows recovery and audit.

Key relationships:
- One order can have multiple reservations (multi-warehouse split)
- One SKU/warehouse can have multiple reservations (multiple orders)
"""

import uuid
from sqlalchemy import Column, String, Integer, DateTime, Index, Enum as SAEnum
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from enum import Enum

from ..base import Base


class ReservationStatus(str, Enum):
    """Status of an inventory reservation."""
    ACTIVE = "active"           # Reservation is holding inventory
    RELEASED = "released"       # Released back to available (fulfilled/cancelled)
    EXPIRED = "expired"         # Auto-expired after timeout (safety mechanism)


class ReservationSource(str, Enum):
    """Channel that created the reservation."""
    MEDUSA = "medusa"
    SHOPIFY = "shopify"


class ReleaseReason(str, Enum):
    """Why the reservation was released."""
    FULFILLED = "fulfilled"     # Order was shipped
    CANCELLED = "cancelled"     # Order was cancelled
    EXPIRED = "expired"         # Auto-expired (safety timeout)
    MANUAL = "manual"           # Manual release by admin
    RECONCILIATION = "reconciliation"  # Fixed during reconciliation


class InventoryReservation(Base):
    """
    Tracks inventory reservations for orders.
    
    This is the durable store - Redis is the fast cache.
    On Redis restart, reservations can be rebuilt from this table.
    
    Example flow:
    1. Order placed → Insert with status=ACTIVE
    2. Redis reserve() succeeds → Reservation persisted
    3. Order fulfilled → Update status=RELEASED, release_reason=FULFILLED
    """
    __tablename__ = "inventory_reservation"
    __table_args__ = (
        # Fast lookup by SKU + warehouse (for reconciliation)
        Index('idx_reservation_sku_warehouse', 'sku', 'warehouse_id'),
        # Fast lookup by order (for order-level queries)
        Index('idx_reservation_order', 'order_id'),
        # Fast lookup for active reservations (most common query)
        Index('idx_reservation_active', 'status', 'sku', 'warehouse_id'),
        # For finding reservations by source
        Index('idx_reservation_source', 'source', 'status'),
    )

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    
    # What is reserved
    sku = Column(String(100), nullable=False)
    warehouse_id = Column(String(100), nullable=False)
    quantity = Column(Integer, nullable=False)
    
    # Who reserved it
    source = Column(SAEnum(ReservationSource, values_callable=lambda x: [e.value for e in x]), nullable=False)
    order_id = Column(String(100), nullable=False)  # Internal order ID
    order_display_id = Column(String(100), nullable=True)  # Human-readable order ID (CLK12345)
    platform_order_id = Column(String(100), nullable=True)  # Platform-specific ID (Medusa/Shopify)
    line_item_id = Column(String(100), nullable=True)  # Line item ID for multi-SKU orders
    
    # Reservation state
    status = Column(SAEnum(ReservationStatus, values_callable=lambda x: [e.value for e in x]), default=ReservationStatus.ACTIVE, nullable=False)
    release_reason = Column(SAEnum(ReleaseReason, values_callable=lambda x: [e.value for e in x]), 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)
    released_at = Column(DateTime(timezone=True), nullable=True)
    expires_at = Column(DateTime(timezone=True), nullable=True)  # Optional expiry for safety
    
    # Snapshot of inventory state at reservation time (for debugging)
    available_before = Column(Integer, nullable=True)
    available_after = Column(Integer, nullable=True)

    def __repr__(self):
        return (
            f"<InventoryReservation("
            f"id={self.id}, "
            f"order={self.order_id}, "
            f"sku={self.sku}, "
            f"warehouse={self.warehouse_id}, "
            f"qty={self.quantity}, "
            f"status={self.status.value}"
            f")>"
        )
    
    @property
    def is_active(self) -> bool:
        """Check if reservation is still holding inventory."""
        return self.status == ReservationStatus.ACTIVE
