"""
Enterprise Upgrade API
Endpoints for upgrading tenants to enterprise tier and managing child outlets
"""

from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel, Field
from typing import Dict, Any, Optional
import uuid
from datetime import datetime, date
from sqlalchemy.ext.asyncio import AsyncSession

from app.models.tenants import Tenant
from app.models.tenant_location import TenantLocation
from app.services.tenant_service import EnhancedTenantService
from app.core.config import settings
from shared.auth.tenant_access import verify_tenant_permission_dep
from shared.auth.decorators import get_current_user_dep
from shared.clients.subscription_client import SubscriptionServiceClient, get_subscription_service_client
from shared.subscription.plans import SubscriptionTier, QuotaLimits
from shared.database.base import create_database_manager
import structlog

logger = structlog.get_logger()
router = APIRouter()


# Dependency injection for enhanced tenant service
def get_enhanced_tenant_service():
    try:
        from app.core.config import settings
        database_manager = create_database_manager(settings.DATABASE_URL, "tenant-service")
        return EnhancedTenantService(database_manager)
    except Exception as e:
        logger.error("Failed to create enhanced tenant service", error=str(e))
        raise HTTPException(status_code=500, detail="Service initialization failed")


# Pydantic models for request bodies
class EnterpriseUpgradeRequest(BaseModel):
    location_name: Optional[str] = Field(default="Central Production Facility")
    address: Optional[str] = None
    city: Optional[str] = None
    postal_code: Optional[str] = None
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    production_capacity_kg: Optional[int] = Field(default=1000)


class ChildOutletRequest(BaseModel):
    name: str
    subdomain: str
    address: str
    city: Optional[str] = None
    postal_code: str
    latitude: Optional[float] = None
    longitude: Optional[float] = None
    phone: Optional[str] = None
    email: Optional[str] = None
    delivery_days: Optional[list] = None


@router.post("/tenants/{tenant_id}/upgrade-to-enterprise")
async def upgrade_to_enterprise(
    tenant_id: str,
    upgrade_data: EnterpriseUpgradeRequest,
    subscription_client: SubscriptionServiceClient = Depends(get_subscription_service_client),
    current_user: Dict[str, Any] = Depends(get_current_user_dep)
):
    """
    Upgrade a tenant to enterprise tier with central production facility
    """
    try:
        from app.core.database import database_manager
        from app.repositories.tenant_repository import TenantRepository

        # Get the current tenant
        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            tenant = await tenant_repo.get_by_id(tenant_id)
            if not tenant:
                raise HTTPException(status_code=404, detail="Tenant not found")

        # Verify current subscription allows upgrade to enterprise
        current_subscription = await subscription_client.get_subscription(tenant_id)
        if current_subscription['plan'] not in [SubscriptionTier.STARTER.value, SubscriptionTier.PROFESSIONAL.value]:
            raise HTTPException(status_code=400, detail="Only starter and professional tier tenants can be upgraded to enterprise")

        # Verify user has admin/owner role
        # This is handled by current_user check

        # Update tenant to parent type
        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            updated_tenant = await tenant_repo.update(
                tenant_id,
                {
                    'tenant_type': 'parent',
                    'hierarchy_path': f"{tenant_id}"  # Root path
                }
            )
            await session.commit()
        
        # Create central production location
        location_data = {
            'tenant_id': tenant_id,
            'name': upgrade_data.location_name,
            'location_type': 'central_production',
            'address': upgrade_data.address or tenant.address,
            'city': upgrade_data.city or tenant.city,
            'postal_code': upgrade_data.postal_code or tenant.postal_code,
            'latitude': upgrade_data.latitude or tenant.latitude,
            'longitude': upgrade_data.longitude or tenant.longitude,
            'capacity': upgrade_data.production_capacity_kg,
            'is_active': True
        }

        from app.repositories.tenant_location_repository import TenantLocationRepository
        from app.core.database import database_manager

        # Create async session
        async with database_manager.get_session() as session:
            location_repo = TenantLocationRepository(session)
            created_location = await location_repo.create_location(location_data)
            await session.commit()
        
        # Update subscription to enterprise tier
        await subscription_client.update_subscription_plan(
            tenant_id=tenant_id,
            new_plan=SubscriptionTier.ENTERPRISE.value
        )
        
        return {
            'success': True,
            'tenant': updated_tenant,
            'production_location': created_location,
            'message': 'Tenant successfully upgraded to enterprise tier'
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to upgrade tenant: {str(e)}")


@router.post("/tenants/{parent_id}/add-child-outlet")
async def add_child_outlet(
    parent_id: str,
    child_data: ChildOutletRequest,
    subscription_client: SubscriptionServiceClient = Depends(get_subscription_service_client),
    current_user: Dict[str, Any] = Depends(get_current_user_dep)
):
    """
    Add a new child outlet to a parent tenant
    """
    try:
        from app.core.database import database_manager
        from app.repositories.tenant_repository import TenantRepository

        # Get parent tenant and verify it's a parent
        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            parent_tenant = await tenant_repo.get_by_id(parent_id)
            if not parent_tenant:
                raise HTTPException(status_code=400, detail="Parent tenant not found")

            parent_dict = {
                'id': str(parent_tenant.id),
                'name': parent_tenant.name,
                'tenant_type': parent_tenant.tenant_type,
                'subscription_tier': parent_tenant.subscription_tier,
                'business_type': parent_tenant.business_type,
                'business_model': parent_tenant.business_model,
                'city': parent_tenant.city,
                'phone': parent_tenant.phone,
                'email': parent_tenant.email,
                'owner_id': parent_tenant.owner_id
            }

            if parent_dict.get('tenant_type') != 'parent':
                raise HTTPException(status_code=400, detail="Tenant is not a parent type")

        # Validate subscription tier
        from shared.clients import get_tenant_client
        from shared.subscription.plans import PlanFeatures

        tenant_client = get_tenant_client(config=settings, service_name="tenant-service")
        subscription = await tenant_client.get_tenant_subscription(parent_id)

        if not subscription:
            raise HTTPException(
                status_code=403,
                detail="No active subscription found for parent tenant"
            )

        tier = subscription.get("plan", "starter")
        if not PlanFeatures.validate_tenant_access(tier, "child"):
            raise HTTPException(
                status_code=403,
                detail=f"Creating child outlets requires Enterprise subscription. Current plan: {tier}"
            )

        # Check if parent has reached child quota
        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            current_child_count = await tenant_repo.get_child_tenant_count(parent_id)

        # Get max children from subscription plan
        max_children = QuotaLimits.get_limit("MAX_CHILD_TENANTS", tier)

        if max_children is not None and current_child_count >= max_children:
            raise HTTPException(
                status_code=403,
                detail=f"Child tenant limit reached. Current: {current_child_count}, Maximum: {max_children}"
            )

        # Create new child tenant
        child_id = str(uuid.uuid4())
        child_tenant_data = {
            'id': child_id,
            'name': child_data.name,
            'subdomain': child_data.subdomain,
            'business_type': parent_dict.get('business_type', 'bakery'),
            'business_model': parent_dict.get('business_model', 'retail_bakery'),
            'address': child_data.address,
            'city': child_data.city or parent_dict.get('city'),
            'postal_code': child_data.postal_code,
            'latitude': child_data.latitude,
            'longitude': child_data.longitude,
            'phone': child_data.phone or parent_dict.get('phone'),
            'email': child_data.email or parent_dict.get('email'),
            'parent_tenant_id': parent_id,
            'tenant_type': 'child',
            'hierarchy_path': f"{parent_id}.{child_id}",
            'owner_id': parent_dict.get('owner_id'),  # Same owner as parent
            'is_active': True
        }

        # Use database managed session
        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            created_child = await tenant_repo.create(child_tenant_data)
            await session.commit()

        created_child_dict = {
            'id': str(created_child.id),
            'name': created_child.name,
            'subdomain': created_child.subdomain
        }

        # Create retail outlet location for the child
        location_data = {
            'tenant_id': uuid.UUID(child_id),
            'name': f"Outlet - {child_data.name}",
            'location_type': 'retail_outlet',
            'address': child_data.address,
            'city': child_data.city or parent_dict.get('city'),
            'postal_code': child_data.postal_code,
            'latitude': child_data.latitude,
            'longitude': child_data.longitude,
            'delivery_windows': child_data.delivery_days,
            'is_active': True
        }

        from app.repositories.tenant_location_repository import TenantLocationRepository

        # Create async session
        async with database_manager.get_session() as session:
            location_repo = TenantLocationRepository(session)
            created_location = await location_repo.create_location(location_data)
            await session.commit()

        location_dict = {
            'id': str(created_location.id) if created_location else None,
            'name': created_location.name if created_location else None
        }

        # Copy relevant settings from parent (with child-specific overrides)
        # This would typically involve copying settings via tenant settings service

        # Create child subscription inheriting from parent
        await subscription_client.create_child_subscription(
            child_tenant_id=child_id,
            parent_tenant_id=parent_id
        )

        return {
            'success': True,
            'child_tenant': created_child_dict,
            'location': location_dict,
            'message': 'Child outlet successfully added'
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to add child outlet: {str(e)}")


@router.get("/tenants/{tenant_id}/hierarchy")
async def get_tenant_hierarchy(
    tenant_id: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep)
):
    """
    Get tenant hierarchy information
    """
    try:
        from app.core.database import database_manager
        from app.repositories.tenant_repository import TenantRepository

        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            tenant = await tenant_repo.get_by_id(tenant_id)
            if not tenant:
                raise HTTPException(status_code=404, detail="Tenant not found")

            result = {
                'tenant_id': tenant_id,
                'name': tenant.name,
                'tenant_type': tenant.tenant_type,
                'parent_tenant_id': tenant.parent_tenant_id,
                'hierarchy_path': tenant.hierarchy_path,
                'is_parent': tenant.tenant_type == 'parent',
                'is_child': tenant.tenant_type == 'child'
            }

            # If this is a parent, include child count
            if tenant.tenant_type == 'parent':
                child_count = await tenant_repo.get_child_tenant_count(tenant_id)
                result['child_tenant_count'] = child_count

        return result

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get hierarchy: {str(e)}")


@router.get("/users/{user_id}/tenant-hierarchy")
async def get_user_accessible_tenant_hierarchy(
    user_id: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep)
):
    """
    Get all tenants a user has access to, organized in hierarchy
    """
    try:
        from app.core.database import database_manager
        from app.repositories.tenant_repository import TenantRepository

        # Fetch all tenants where user has access, organized hierarchically
        async with database_manager.get_session() as session:
            tenant_repo = TenantRepository(Tenant, session)
            user_tenants = await tenant_repo.get_user_tenants_with_hierarchy(user_id)

        return {
            'user_id': user_id,
            'tenants': user_tenants,
            'total_count': len(user_tenants)
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to get user hierarchy: {str(e)}")