from sqlalchemy import Column, Integer, String, Boolean, Float, ForeignKey, Text
from sqlalchemy.orm import relationship
from database import Base


class Category(Base):
    __tablename__ = "categories"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, nullable=False)
    color = Column(String, nullable=True)
    sort_order = Column(Integer, default=0)
    # self-referential: null = top-level, non-null = sub-category of parent
    parent_id = Column(Integer, ForeignKey("categories.id"), nullable=True)
    # position of the "General" group (direct products) among sub-categories
    general_sort_order = Column(Integer, default=0, nullable=False)
    # sub-categories only: if True, the accordion section is expanded by default on the PWA
    auto_expanded = Column(Boolean, default=False, nullable=False)

    products = relationship("Product", back_populates="category")
    subcategories = relationship("Category", back_populates="parent", foreign_keys="Category.parent_id")
    parent = relationship("Category", back_populates="subcategories", remote_side="Category.id", foreign_keys="Category.parent_id")


class Product(Base):
    __tablename__ = "products"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, nullable=False)
    description = Column(Text, nullable=True)
    category_id = Column(Integer, ForeignKey("categories.id"), nullable=True)
    base_price = Column(Float, nullable=False)
    is_available = Column(Boolean, default=True, nullable=False)
    # "active" | "archived" — archived products are kept for order history but hidden from active use
    lifecycle_status = Column(String, default="active", nullable=False)
    printer_zone_id = Column(Integer, ForeignKey("printers.id"), nullable=True)
    image_url = Column(String, nullable=True)
    sort_order = Column(Integer, default=0, nullable=False)

    # Xenia Connect — digital menu overrides
    digital_visible = Column(Integer, default=1, nullable=False)
    digital_available = Column(Integer, default=1, nullable=False)
    digital_name = Column(String, nullable=True)
    digital_description = Column(String, nullable=True)
    digital_price = Column(Float, nullable=True)
    digital_discount = Column(Float, default=0.0, nullable=False)
    digital_image_url = Column(String, nullable=True)

    # Unit of measure: "piece" | "portion" | "kg" | "liter" | "gram" | "ml"
    unit_type = Column(String, default="piece", nullable=False)

    # Phase 2A — cost tracking
    cost_simple = Column(Float, nullable=True)
    cost_breakdown = Column(Text, nullable=True)  # JSON: [{"label": str, "amount": float}]

    # Quick Add: allow adding 1 unit directly from product list without opening config modal
    quick_add_enabled = Column(Boolean, default=True, nullable=False)

    # Service item: non-inventoried table-service items (cutlery, glasses, etc.)
    is_service_item = Column(Boolean, default=False, nullable=False)

    # Tags: JSON array of strings e.g. ["vegan", "gluten-free"]
    tags = Column(Text, nullable=True)

    # Fiscal printer (ΦΗΜ) fields
    fiscal_name = Column(String, nullable=True)          # short name for receipt (falls back to name)
    fiscal_vat_group_id = Column(Integer, nullable=True) # machine VAT group ID (1-based integer)

    category = relationship("Category", back_populates="products")
    printer_zone = relationship("Printer", back_populates="products")
    prep_zones = relationship("PrepZone", secondary="product_prep_zones", back_populates="products")
    quick_options = relationship("ProductQuickOption", back_populates="product", cascade="all, delete-orphan")
    options = relationship("ProductOption", back_populates="product", cascade="all, delete-orphan")
    ingredients = relationship("ProductIngredient", back_populates="product", cascade="all, delete-orphan")
    preference_sets = relationship("ProductPreferenceSet", back_populates="product", cascade="all, delete-orphan")
    modifier_groups = relationship("ProductModifierGroup", back_populates="product", cascade="all, delete-orphan")
    order_items = relationship("OrderItem", back_populates="product")


class ProductModifierGroup(Base):
    """A named folder/group that can contain options, ingredients, or preference sets."""
    __tablename__ = "product_modifier_groups"

    id = Column(Integer, primary_key=True, index=True)
    product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
    # "option" | "ingredient" | "preference"
    modifier_type = Column(String, nullable=False)
    name = Column(String, nullable=False)
    sort_order = Column(Integer, default=0, nullable=False)

    product = relationship("Product", back_populates="modifier_groups")


class ProductOption(Base):
    __tablename__ = "product_options"

    id = Column(Integer, primary_key=True, index=True)
    product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
    name = Column(String, nullable=False)
    extra_cost = Column(Float, default=0.0)
    allow_multiple = Column(Boolean, default=False, nullable=False)
    # When True, waiter can select more than one sub-choice simultaneously
    multi_select = Column(Boolean, default=False, nullable=False)
    # JSON array [{name, extra_cost, is_default, allow_multiple}] — sub-options shown when this option is checked
    sub_choices = Column(Text, nullable=True)
    is_favorite = Column(Boolean, default=False, nullable=False)
    favorite_sort_order = Column(Integer, default=0, nullable=False)
    # When True renders as half-width card on the PWA
    is_compact = Column(Boolean, default=False, nullable=False)
    # Optional group/folder this option belongs to
    group_id = Column(Integer, ForeignKey("product_modifier_groups.id"), nullable=True)

    product = relationship("Product", back_populates="options")


class ProductQuickOption(Base):
    __tablename__ = "product_quick_options"

    id = Column(Integer, primary_key=True, index=True)
    product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
    name = Column(String, nullable=False)
    price = Column(Float, default=0.0, nullable=False)
    allow_multiple = Column(Boolean, default=False, nullable=False)
    sort_order = Column(Integer, default=0, nullable=False)
    is_favorite = Column(Boolean, default=False, nullable=False)
    favorite_sort_order = Column(Integer, default=0, nullable=False)
    is_compact = Column(Boolean, default=False, nullable=False)

    product = relationship("Product", back_populates="quick_options")


class ProductIngredient(Base):
    __tablename__ = "product_ingredients"

    id = Column(Integer, primary_key=True, index=True)
    product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
    name = Column(String, nullable=False)
    extra_cost = Column(Float, default=0.0)
    is_favorite = Column(Boolean, default=False, nullable=False)
    favorite_sort_order = Column(Integer, default=0, nullable=False)
    # When True renders as half-width card on the PWA
    is_compact = Column(Boolean, default=False, nullable=False)
    # Optional group/folder this ingredient belongs to
    group_id = Column(Integer, ForeignKey("product_modifier_groups.id"), nullable=True)

    product = relationship("Product", back_populates="ingredients")


class ProductPreferenceSet(Base):
    __tablename__ = "product_preference_sets"

    id = Column(Integer, primary_key=True, index=True)
    product_id = Column(Integer, ForeignKey("products.id"), nullable=False)
    name = Column(String, nullable=False)
    default_choice_id = Column(Integer, nullable=True)
    # JSON: {name, default_choice_index, choices:[{name,extra_cost,is_default}]}
    # Shared sub-set shown for all choices that don't have disables_subset=True
    shared_subset = Column(Text, nullable=True)
    is_favorite = Column(Boolean, default=False, nullable=False)
    favorite_sort_order = Column(Integer, default=0, nullable=False)
    # Optional group/folder this preference set belongs to
    group_id = Column(Integer, ForeignKey("product_modifier_groups.id"), nullable=True)
    # When True, waiter can select multiple choices instead of just one
    allow_multi_select = Column(Boolean, default=False, nullable=False)
    # When True, each selected choice can have a quantity (x2, x3, …)
    allow_choice_quantity = Column(Boolean, default=False, nullable=False)

    product = relationship("Product", back_populates="preference_sets")
    choices = relationship("ProductPreferenceChoice", back_populates="set", cascade="all, delete-orphan")


class ProductPreferenceChoice(Base):
    __tablename__ = "product_preference_choices"

    id = Column(Integer, primary_key=True, index=True)
    set_id = Column(Integer, ForeignKey("product_preference_sets.id"), nullable=False)
    name = Column(String, nullable=False)
    extra_cost = Column(Float, default=0.0)
    # JSON array of sub-choice objects: [{name, extra_cost, is_default, is_compact}]
    # Per-choice inline sub-preference shown only when this choice is selected.
    sub_choices = Column(Text, nullable=True)
    # When True this choice hides the set-level shared_subset on the PWA.
    disables_subset = Column(Boolean, default=False, nullable=False)
    # When True renders as half-width card on the PWA
    is_compact = Column(Boolean, default=False, nullable=False)

    set = relationship("ProductPreferenceSet", back_populates="choices")
