# services/tenant/app/models/tenants.py - FIXED VERSION
"""
Tenant models for bakery management - FIXED
Removed cross-service User relationship to eliminate circular dependencies
"""

from sqlalchemy import Column, String, Boolean, DateTime, Float, ForeignKey, Text, Integer, JSON
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
import uuid

from shared.database.base import Base

class Tenant(Base):
    """Tenant/Bakery model"""
    __tablename__ = "tenants"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    name = Column(String(200), nullable=False)
    subdomain = Column(String(100), unique=True)
    business_type = Column(String(100), default="bakery")
    business_model = Column(String(100), default="individual_bakery")  # individual_bakery, central_baker_satellite, retail_bakery, hybrid_bakery
    
    # Location info
    address = Column(Text, nullable=False)
    city = Column(String(100), default="Madrid")
    postal_code = Column(String(10), nullable=False)
    latitude = Column(Float)
    longitude = Column(Float)

    # Regional/Localization configuration
    timezone = Column(String(50), default="Europe/Madrid", nullable=False)
    currency = Column(String(3), default="EUR", nullable=False)  # Currency code: EUR, USD, GBP
    language = Column(String(5), default="es", nullable=False)  # Language code: es, en, eu

    # Contact info
    phone = Column(String(20))
    email = Column(String(255))
    
    # Status
    is_active = Column(Boolean, default=True)

    # Demo account flags
    is_demo = Column(Boolean, default=False, index=True)
    is_demo_template = Column(Boolean, default=False, index=True)
    base_demo_tenant_id = Column(UUID(as_uuid=True), nullable=True, index=True)
    demo_session_id = Column(String(100), nullable=True, index=True)
    demo_expires_at = Column(DateTime(timezone=True), nullable=True)

    # ML status
    ml_model_trained = Column(Boolean, default=False)
    last_training_date = Column(DateTime(timezone=True))

    # Additional metadata (JSON field for flexible data storage)
    metadata_ = Column(JSON, nullable=True)

    # Ownership (user_id without FK - cross-service reference)
    owner_id = Column(UUID(as_uuid=True), nullable=False, index=True)

    # Enterprise tier hierarchy fields
    parent_tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="RESTRICT"), nullable=True, index=True)
    tenant_type = Column(String(50), default="standalone", nullable=False)  # standalone, parent, child
    hierarchy_path = Column(String(500), nullable=True)  # Materialized path for queries

    # Timestamps
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))

    # 3D Secure (3DS) tracking
    threeds_authentication_required = Column(Boolean, default=False)
    threeds_authentication_required_at = Column(DateTime(timezone=True), nullable=True)
    threeds_authentication_completed = Column(Boolean, default=False)
    threeds_authentication_completed_at = Column(DateTime(timezone=True), nullable=True)
    last_threeds_setup_intent_id = Column(String(255), nullable=True)
    threeds_action_type = Column(String(100), nullable=True)

    # Relationships - only within tenant service
    members = relationship("TenantMember", back_populates="tenant", cascade="all, delete-orphan")
    subscriptions = relationship("Subscription", back_populates="tenant", cascade="all, delete-orphan")
    locations = relationship("TenantLocation", back_populates="tenant", cascade="all, delete-orphan")
    child_tenants = relationship("Tenant", back_populates="parent_tenant", remote_side=[id])
    parent_tenant = relationship("Tenant", back_populates="child_tenants", remote_side=[parent_tenant_id])

    # REMOVED: users relationship - no cross-service SQLAlchemy relationships

    @property
    def subscription_tier(self):
        """
        Get current subscription tier from active subscription

        Note: This is a computed property that requires subscription relationship to be loaded.
        For performance-critical operations, use the subscription cache service directly.
        """
        # Find active subscription
        for subscription in self.subscriptions:
            if subscription.status == 'active':
                return subscription.plan
        return "starter"  # Default fallback

    def __repr__(self):
        return f"<Tenant(id={self.id}, name={self.name})>"

class TenantMember(Base):
    """
    Tenant membership model for team access.

    This model represents TENANT-SPECIFIC roles, which are distinct from global user roles.

    TENANT ROLES (stored here):
    - owner: Full control of the tenant, can transfer ownership, manage all aspects
    - admin: Tenant administrator, can manage team members and most operations
    - member: Standard team member, regular operational access
    - viewer: Read-only observer, view-only access to tenant data

    ROLE MAPPING TO GLOBAL ROLES:
    When users are created through tenant management (pilot phase), their tenant role
    is mapped to a global user role in the Auth service:
    - tenant 'admin'  → global 'admin'   (system-wide admin access)
    - tenant 'member' → global 'manager' (management-level access)
    - tenant 'viewer' → global 'user'    (basic user access)
    - tenant 'owner'  → No automatic global role (owner is tenant-specific)

    This mapping is implemented in app/api/tenant_members.py lines 68-76.

    Note: user_id is a cross-service reference (no FK) to avoid circular dependencies.
    User enrichment is handled at the service layer via Auth service calls.
    """
    __tablename__ = "tenant_members"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False)
    user_id = Column(UUID(as_uuid=True), nullable=False, index=True)  # No FK - cross-service reference

    # Role and permissions specific to this tenant
    # Valid values: 'owner', 'admin', 'member', 'viewer', 'network_admin'
    role = Column(String(50), default="member")
    permissions = Column(Text)  # JSON string of permissions
    
    # Status
    is_active = Column(Boolean, default=True)
    invited_by = Column(UUID(as_uuid=True))  # No FK - cross-service reference
    invited_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    joined_at = Column(DateTime(timezone=True))
    
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))

    # Relationships - only within tenant service
    tenant = relationship("Tenant", back_populates="members")
    
    # REMOVED: user relationship - no cross-service SQLAlchemy relationships
    
    def __repr__(self):
        return f"<TenantMember(tenant_id={self.tenant_id}, user_id={self.user_id}, role={self.role})>"

# Additional models for subscriptions, plans, etc.
class Subscription(Base):
    """Subscription model for tenant billing with tenant linking support"""
    __tablename__ = "subscriptions"
    
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=True)
    
    # User reference for tenant-independent subscriptions
    user_id = Column(UUID(as_uuid=True), nullable=True, index=True)
    
    # Tenant linking status
    is_tenant_linked = Column(Boolean, default=False, nullable=False)
    tenant_linking_status = Column(String(50), nullable=True)  # pending, completed, failed
    linked_at = Column(DateTime(timezone=True), nullable=True)
    
    plan = Column(String(50), default="starter")  # starter, professional, enterprise
    status = Column(String(50), default="active")  # active, pending_cancellation, inactive, suspended, pending_tenant_linking

    # Billing
    monthly_price = Column(Float, default=0.0)
    billing_cycle = Column(String(20), default="monthly")  # monthly, yearly
    next_billing_date = Column(DateTime(timezone=True))
    trial_ends_at = Column(DateTime(timezone=True))
    cancelled_at = Column(DateTime(timezone=True), nullable=True)
    cancellation_effective_date = Column(DateTime(timezone=True), nullable=True)

    # Payment provider references (generic names for provider-agnostic design)
    subscription_id = Column(String(255), nullable=True)  # Payment provider subscription ID
    customer_id = Column(String(255), nullable=True)  # Payment provider customer ID
    
    # Limits
    max_users = Column(Integer, default=5)
    max_locations = Column(Integer, default=1)
    max_products = Column(Integer, default=50)
    
    # Features - Store plan features as JSON
    features = Column(JSON)
    
    # Timestamps
    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
    updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))

    # 3D Secure (3DS) tracking
    threeds_authentication_required = Column(Boolean, default=False)
    threeds_authentication_required_at = Column(DateTime(timezone=True), nullable=True)
    threeds_authentication_completed = Column(Boolean, default=False)
    threeds_authentication_completed_at = Column(DateTime(timezone=True), nullable=True)
    last_threeds_setup_intent_id = Column(String(255), nullable=True)
    threeds_action_type = Column(String(100), nullable=True)
    
    # Relationships
    tenant = relationship("Tenant")
    
    def __repr__(self):
        return f"<Subscription(id={self.id}, tenant_id={self.tenant_id}, user_id={self.user_id}, plan={self.plan}, status={self.status})>"
    
    def is_pending_tenant_linking(self) -> bool:
        """Check if subscription is waiting to be linked to a tenant"""
        return self.tenant_linking_status == "pending" and not self.is_tenant_linked
    
    def can_be_linked_to_tenant(self, user_id: str) -> bool:
        """Check if subscription can be linked to a tenant by the given user"""
        return (self.is_pending_tenant_linking() and 
                str(self.user_id) == user_id and
                self.tenant_id is None)
