"""
User onboarding progress API routes
"""

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Dict, Any, List, Optional
import structlog
from datetime import datetime, timezone
from pydantic import BaseModel

from app.core.database import get_db
from app.services.user_service import EnhancedUserService
from app.repositories.onboarding_repository import OnboardingRepository
from shared.auth.decorators import get_current_user_dep

logger = structlog.get_logger()
router = APIRouter(tags=["onboarding"])

# Request/Response Models
class OnboardingStepStatus(BaseModel):
    step_name: str
    completed: bool
    completed_at: Optional[datetime] = None
    data: Optional[Dict[str, Any]] = None

class WizardContextState(BaseModel):
    """
    Wizard context state extracted from completed step data.
    This is used to restore the frontend WizardContext on session restore.
    """
    bakery_type: Optional[str] = None
    tenant_id: Optional[str] = None
    subscription_tier: Optional[str] = None
    ai_analysis_complete: bool = False
    inventory_review_completed: bool = False
    stock_entry_completed: bool = False
    categorization_completed: bool = False
    suppliers_completed: bool = False
    inventory_setup_completed: bool = False
    recipes_completed: bool = False
    quality_completed: bool = False
    team_completed: bool = False
    child_tenants_completed: bool = False
    ml_training_complete: bool = False

class UserProgress(BaseModel):
    user_id: str
    steps: List[OnboardingStepStatus]
    current_step: str
    next_step: Optional[str] = None
    completion_percentage: float
    fully_completed: bool
    last_updated: datetime
    context_state: Optional[WizardContextState] = None

class UpdateStepRequest(BaseModel):
    step_name: str
    completed: bool
    data: Optional[Dict[str, Any]] = None

class SaveStepDraftRequest(BaseModel):
    step_name: str
    draft_data: Dict[str, Any]

# Define the onboarding steps and their order - matching frontend UnifiedOnboardingWizard step IDs
ONBOARDING_STEPS = [
    # Phase 0: System Steps
    "user_registered",              # Auto-completed: User account created

    # Phase 1: Discovery
    "bakery-type-selection",        # Choose bakery type: production/retail/mixed (skipped for enterprise)

    # Phase 2: Core Setup
    "setup",                        # Basic bakery setup and tenant creation
                                    # NOTE: POI detection now happens automatically in background during tenant registration

    # Phase 2-Enterprise: Child Tenants Setup (enterprise tier only)
    "child-tenants-setup",          # Configure child tenants/branches for enterprise tier

    # Phase 2a: AI-Assisted Inventory Setup (REFACTORED - split into 3 focused steps)
    "upload-sales-data",            # File upload, validation, and AI classification
    "inventory-review",             # Review and confirm AI-detected products with type selection
    "initial-stock-entry",          # Capture initial stock levels

    # Phase 2b: Product Categorization (optional advanced categorization)
    "product-categorization",       # Advanced categorization (may be deprecated)

    # Phase 2c: Suppliers (shared by all paths)
    "suppliers-setup",              # Suppliers configuration

    # Phase 2d: Manual Inventory Setup (alternative to AI-assisted path)
    "inventory-setup",              # Manual ingredient/inventory management

    # Phase 3: Advanced Configuration (all optional)
    "recipes-setup",                # Production recipes (conditional: production/mixed bakery)
    "quality-setup",                # Quality standards and templates
    "team-setup",                   # Team members and permissions

    # Phase 4: ML & Finalization
    "ml-training",                  # AI model training
    # "setup-review" removed - not useful for user, completion step is final
    "completion"                    # Onboarding completed
]

# Step dependencies - defines which steps must be completed before others
# Steps not listed here have no dependencies (can be completed anytime after user_registered)
STEP_DEPENDENCIES = {
    # Discovery phase
    "bakery-type-selection": ["user_registered"],

    # Core setup - NOTE: bakery-type-selection dependency is conditionally required
    # Enterprise users skip bakery-type-selection, so setup only requires user_registered for them
    "setup": ["user_registered", "bakery-type-selection"],
    # NOTE: POI detection removed from steps - now happens automatically in background

    # Enterprise child tenants setup - requires setup (parent tenant) to be completed first
    "child-tenants-setup": ["user_registered", "setup"],

    # AI-Assisted Inventory Setup - REFACTORED into 3 sequential steps
    "upload-sales-data": ["user_registered", "setup"],
    "inventory-review": ["user_registered", "setup", "upload-sales-data"],
    "initial-stock-entry": ["user_registered", "setup", "upload-sales-data", "inventory-review"],

    # Advanced product categorization (optional, may be deprecated)
    "product-categorization": ["user_registered", "setup", "upload-sales-data"],

    # Suppliers (after inventory review)
    "suppliers-setup": ["user_registered", "setup", "inventory-review"],

    # Manual inventory setup (alternative to AI-assisted path)
    "inventory-setup": ["user_registered", "setup"],

    # Advanced configuration (optional, minimal dependencies)
    "recipes-setup": ["user_registered", "setup"],
    "quality-setup": ["user_registered", "setup"],
    "team-setup": ["user_registered", "setup"],

    # ML Training - requires AI path completion
    # NOTE: POI detection happens automatically in background, not required as dependency
    "ml-training": ["user_registered", "setup", "upload-sales-data", "inventory-review"],

    # Review and completion
    "setup-review": ["user_registered", "setup"],
    "completion": ["user_registered", "setup"]  # Minimal requirements for completion
}

class OnboardingService:
    """Service for managing user onboarding progress"""
    
    def __init__(self, db: AsyncSession):
        self.db = db
        self.user_service = EnhancedUserService(db)
        self.onboarding_repo = OnboardingRepository(db)
    
    async def get_user_progress(self, user_id: str) -> UserProgress:
        """Get current onboarding progress for user"""

        # Get user's onboarding data from user preferences or separate table
        user_progress_data = await self._get_user_onboarding_data(user_id)

        # Calculate current status for each step
        steps = []
        completed_steps = []

        for step_name in ONBOARDING_STEPS:
            step_data = user_progress_data.get(step_name, {})
            is_completed = step_data.get("completed", False)

            if is_completed:
                completed_steps.append(step_name)

            steps.append(OnboardingStepStatus(
                step_name=step_name,
                completed=is_completed,
                completed_at=step_data.get("completed_at"),
                data=step_data.get("data", {})
            ))

        # Determine current and next step
        current_step = self._get_current_step(completed_steps)
        next_step = self._get_next_step(completed_steps)

        # Calculate completion percentage
        completion_percentage = (len(completed_steps) / len(ONBOARDING_STEPS)) * 100

        # Check if fully completed - based on REQUIRED steps only
        # Define required steps
        REQUIRED_STEPS = [
            "user_registered",
            "setup",
            "suppliers-setup",
            "ml-training",
            "completion"
        ]

        # Get user's subscription tier to determine if bakery-type-selection is required
        user_registered_data = user_progress_data.get("user_registered", {}).get("data", {})
        subscription_tier = user_registered_data.get("subscription_tier", "professional")

        # Add bakery-type-selection to required steps for non-enterprise users
        if subscription_tier != "enterprise":
            required_steps_for_user = REQUIRED_STEPS + ["bakery-type-selection"]
        else:
            required_steps_for_user = REQUIRED_STEPS

        # Check if all required steps are completed
        required_completed = all(
            user_progress_data.get(step, {}).get("completed", False)
            for step in required_steps_for_user
        )

        fully_completed = required_completed

        # Extract wizard context state for frontend restoration
        context_state = self._extract_context_state(user_progress_data)

        return UserProgress(
            user_id=user_id,
            steps=steps,
            current_step=current_step,
            next_step=next_step,
            completion_percentage=completion_percentage,
            fully_completed=fully_completed,
            last_updated=datetime.now(timezone.utc),
            context_state=context_state
        )
    
    async def update_step(self, user_id: str, update_request: UpdateStepRequest) -> UserProgress:
        """Update a specific onboarding step"""
        
        step_name = update_request.step_name
        
        # Validate step name
        if step_name not in ONBOARDING_STEPS:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid step name: {step_name}"
            )
        
        # Check dependencies if marking as completed
        if update_request.completed:
            can_complete = await self._can_complete_step(user_id, step_name)
            if not can_complete:
                raise HTTPException(
                    status_code=status.HTTP_400_BAD_REQUEST,
                    detail=f"Cannot complete step {step_name}: dependencies not met"
                )
        
        # Update the step
        await self._update_user_onboarding_data(
            user_id,
            step_name,
            {
                "completed": update_request.completed,
                "completed_at": datetime.now(timezone.utc).isoformat() if update_request.completed else None,
                "data": update_request.data or {}
            }
        )

        # Try to update summary and handle partial failures gracefully
        try:
            # Update the user's onboarding summary
            await self._update_user_summary(user_id)
        except HTTPException as he:
            # If it's a 207 Multi-Status (partial success), log warning but continue
            if he.status_code == status.HTTP_207_MULTI_STATUS:
                logger.warning(f"Summary update failed for user {user_id}, step {step_name}: {he.detail}")
                # Continue execution - the step update was successful
            else:
                # Re-raise other HTTP exceptions
                raise

        # Return updated progress
        return await self.get_user_progress(user_id)
    
    async def get_next_step(self, user_id: str) -> Dict[str, Any]:
        """Get the next required step for user"""
        progress = await self.get_user_progress(user_id)
        
        if progress.fully_completed:
            return {"step": "dashboard_accessible", "completed": True}
        
        return {"step": progress.next_step or progress.current_step}
    
    async def can_access_step(self, user_id: str, step_name: str) -> Dict[str, Any]:
        """Check if user can access a specific step"""
        
        if step_name not in ONBOARDING_STEPS:
            return {"can_access": False, "reason": "Invalid step name"}
        
        can_access = await self._can_complete_step(user_id, step_name)
        return {"can_access": can_access}
    
    async def complete_onboarding(self, user_id: str) -> Dict[str, Any]:
        """Mark entire onboarding as complete"""

        # Get user's progress
        progress = await self.get_user_progress(user_id)
        user_progress_data = await self._get_user_onboarding_data(user_id)

        # Define REQUIRED steps (excluding optional/conditional steps)
        # These are the minimum steps needed to complete onboarding
        REQUIRED_STEPS = [
            "user_registered",
            "setup",  # bakery-type-selection is conditional for enterprise
            "suppliers-setup",
            "ml-training",
            "completion"
        ]

        # Define CONDITIONAL steps that are only required for certain tiers/flows
        CONDITIONAL_STEPS = {
            "child-tenants-setup": "enterprise",  # Only for enterprise tier
            "product-categorization": None,  # Optional for all
            "bakery-type-selection": "non-enterprise",  # Only for non-enterprise
            "upload-sales-data": None,  # Optional (manual inventory setup is alternative)
            "inventory-review": None,  # Optional (manual inventory setup is alternative)
            "initial-stock-entry": None,  # Optional
            "recipes-setup": None,  # Optional
            "quality-setup": None,  # Optional
            "team-setup": None,  # Optional
        }

        # Get user's subscription tier
        user_registered_data = user_progress_data.get("user_registered", {}).get("data", {})
        subscription_tier = user_registered_data.get("subscription_tier", "professional")

        # Check if all REQUIRED steps are completed
        incomplete_required_steps = []
        for step_name in REQUIRED_STEPS:
            if not user_progress_data.get(step_name, {}).get("completed", False):
                # Special case: bakery-type-selection is not required for enterprise
                if step_name == "bakery-type-selection" and subscription_tier == "enterprise":
                    continue
                incomplete_required_steps.append(step_name)

        # If there are incomplete required steps, reject completion
        if incomplete_required_steps:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Cannot complete onboarding: incomplete required steps: {incomplete_required_steps}"
            )

        # Log conditional steps that are incomplete (warning only, not blocking)
        incomplete_conditional_steps = [
            step.step_name for step in progress.steps
            if not step.completed and step.step_name in CONDITIONAL_STEPS
        ]
        if incomplete_conditional_steps:
            logger.info(
                f"User {user_id} completing onboarding with incomplete optional steps: {incomplete_conditional_steps}",
                extra={"user_id": user_id, "subscription_tier": subscription_tier}
            )

        # Update user's isOnboardingComplete flag
        await self.user_service.update_user_field(
            user_id,
            "is_onboarding_complete",
            True
        )

        return {
            "success": True,
            "message": "Onboarding completed successfully",
            "optional_steps_skipped": incomplete_conditional_steps
        }
    
    def _get_current_step(self, completed_steps: List[str]) -> str:
        """Determine current step based on completed steps"""
        for step in ONBOARDING_STEPS:
            if step not in completed_steps:
                return step
        return ONBOARDING_STEPS[-1]  # All completed
    
    def _get_next_step(self, completed_steps: List[str]) -> Optional[str]:
        """Determine next step based on completed steps"""
        current_step = self._get_current_step(completed_steps)
        current_index = ONBOARDING_STEPS.index(current_step)

        if current_index < len(ONBOARDING_STEPS) - 1:
            return ONBOARDING_STEPS[current_index + 1]

        return None  # No next step

    def _extract_context_state(self, user_progress_data: Dict[str, Any]) -> WizardContextState:
        """
        Extract wizard context state from completed step data.
        This allows the frontend to restore WizardContext state on session restore,
        ensuring conditional steps remain visible based on previous progress.
        """
        # Extract bakeryType from bakery-type-selection step
        bakery_step = user_progress_data.get("bakery-type-selection", {})
        bakery_type = None
        if bakery_step.get("completed"):
            bakery_type = bakery_step.get("data", {}).get("bakeryType")

        # Extract tenantId from setup step
        setup_step = user_progress_data.get("setup", {})
        tenant_id = None
        if setup_step.get("completed"):
            setup_data = setup_step.get("data", {})
            tenant_id = setup_data.get("tenantId") or setup_data.get("tenant", {}).get("id")

        # Extract subscription tier from user_registered step
        user_registered_step = user_progress_data.get("user_registered", {})
        subscription_tier = user_registered_step.get("data", {}).get("subscription_tier")

        # Derive completion flags from step completion status
        upload_step = user_progress_data.get("upload-sales-data", {})
        inventory_review_step = user_progress_data.get("inventory-review", {})
        stock_entry_step = user_progress_data.get("initial-stock-entry", {})
        categorization_step = user_progress_data.get("product-categorization", {})
        suppliers_step = user_progress_data.get("suppliers-setup", {})
        inventory_setup_step = user_progress_data.get("inventory-setup", {})
        recipes_step = user_progress_data.get("recipes-setup", {})
        quality_step = user_progress_data.get("quality-setup", {})
        team_step = user_progress_data.get("team-setup", {})
        child_tenants_step = user_progress_data.get("child-tenants-setup", {})
        ml_training_step = user_progress_data.get("ml-training", {})

        return WizardContextState(
            bakery_type=bakery_type,
            tenant_id=tenant_id,
            subscription_tier=subscription_tier,
            ai_analysis_complete=upload_step.get("completed", False),
            inventory_review_completed=inventory_review_step.get("completed", False),
            stock_entry_completed=stock_entry_step.get("completed", False),
            categorization_completed=categorization_step.get("completed", False),
            suppliers_completed=suppliers_step.get("completed", False),
            inventory_setup_completed=inventory_setup_step.get("completed", False),
            recipes_completed=recipes_step.get("completed", False),
            quality_completed=quality_step.get("completed", False),
            team_completed=team_step.get("completed", False),
            child_tenants_completed=child_tenants_step.get("completed", False),
            ml_training_complete=ml_training_step.get("completed", False),
        )

    async def _can_complete_step(self, user_id: str, step_name: str) -> bool:
        """Check if user can complete a specific step"""

        # Get required dependencies for this step
        required_steps = STEP_DEPENDENCIES.get(step_name, []).copy()  # Copy to avoid modifying original

        if not required_steps:
            return True  # No dependencies

        # Check if all required steps are completed
        user_progress_data = await self._get_user_onboarding_data(user_id)

        # SPECIAL HANDLING FOR ENTERPRISE ONBOARDING
        # Enterprise users skip bakery-type-selection step, so don't require it for setup
        if step_name == "setup" and "bakery-type-selection" in required_steps:
            # Check if user's tenant has enterprise subscription tier
            # We do this by checking if the user has any data indicating enterprise tier
            # This could be stored in user_registered step data or we can infer from context
            user_registered_data = user_progress_data.get("user_registered", {}).get("data", {})
            subscription_tier = user_registered_data.get("subscription_tier")

            if subscription_tier == "enterprise":
                # Enterprise users don't need bakery-type-selection
                logger.info(f"Enterprise user {user_id}: Skipping bakery-type-selection requirement for setup step")
                required_steps.remove("bakery-type-selection")
            elif not user_progress_data.get("bakery-type-selection", {}).get("completed", False):
                # Non-enterprise user hasn't completed bakery-type-selection
                # But allow setup anyway if user_registered is complete (frontend will handle it)
                # This is a fallback for when subscription_tier is not stored in user_registered data
                logger.info(f"User {user_id}: Allowing setup without bakery-type-selection (will be auto-set for enterprise)")
                required_steps.remove("bakery-type-selection")

        for required_step in required_steps:
            is_completed = user_progress_data.get(required_step, {}).get("completed", False)
            if not is_completed:
                logger.warning(
                    f"Step {step_name} blocked for user {user_id}: missing dependency {required_step}",
                    extra={
                        "user_id": user_id,
                        "step_name": step_name,
                        "missing_dependency": required_step,
                        "all_required_steps": required_steps,
                        "user_progress_keys": list(user_progress_data.keys()),
                        "dependency_data": user_progress_data.get(required_step, {})
                    }
                )
                return False

        # SPECIAL VALIDATION FOR ML TRAINING STEP
        if step_name == "ml-training":
            # ML training requires AI-assisted path completion
            # Check if upload-sales-data and inventory-review are completed
            upload_complete = user_progress_data.get("upload-sales-data", {}).get("completed", False)
            inventory_complete = user_progress_data.get("inventory-review", {}).get("completed", False)

            if upload_complete and inventory_complete:
                # Validate sales data was imported
                upload_data = user_progress_data.get("upload-sales-data", {}).get("data", {})
                inventory_data = user_progress_data.get("inventory-review", {}).get("data", {})

                # Check if sales data was processed
                has_sales_data = (
                    upload_data.get("validationResult", {}).get("is_valid", False) or
                    upload_data.get("aiSuggestions", []) or
                    inventory_data.get("inventoryItemsCreated", 0) > 0
                )

                if has_sales_data:
                    logger.info(f"ML training allowed for user {user_id}: AI path with sales data")
                    return True

            # AI path not complete or no sales data
            logger.warning(f"ML training blocked for user {user_id}: No inventory data from AI path")
            return False
        
        return True
    
    async def _get_user_onboarding_data(self, user_id: str) -> Dict[str, Any]:
        """Get user's onboarding progress data from storage"""
        try:
            # Get all onboarding steps for the user from database
            steps = await self.onboarding_repo.get_user_progress_steps(user_id)
            
            # Convert to the expected dictionary format
            progress_data = {}
            for step in steps:
                progress_data[step.step_name] = {
                    "completed": step.completed,
                    "completed_at": step.completed_at,
                    "data": step.step_data or {}
                }
            
            return progress_data
            
        except Exception as e:
            logger.error(f"Error getting onboarding data for user {user_id}: {e}")
            return {}
    
    async def _update_user_onboarding_data(
        self, 
        user_id: str, 
        step_name: str, 
        step_data: Dict[str, Any]
    ):
        """Update user's onboarding step data"""
        try:
            # Extract the completion status and other data
            completed = step_data.get("completed", False)
            data_payload = step_data.get("data", {})
            
            # Update the step in database
            updated_step = await self.onboarding_repo.upsert_user_step(
                user_id=user_id,
                step_name=step_name,
                completed=completed,
                step_data=data_payload
            )

            logger.info(f"Successfully updated onboarding step for user {user_id}: {step_name} = {step_data}")
            return updated_step
            
        except Exception as e:
            logger.error(f"Error updating onboarding data for user {user_id}, step {step_name}: {e}")
            raise
    
    async def _update_user_summary(self, user_id: str):
        """Update user's onboarding summary after step changes"""
        try:
            # Get updated progress
            user_progress_data = await self._get_user_onboarding_data(user_id)

            # Calculate current status
            completed_steps = []
            for step_name in ONBOARDING_STEPS:
                if user_progress_data.get(step_name, {}).get("completed", False):
                    completed_steps.append(step_name)

            # Determine current and next step
            current_step = self._get_current_step(completed_steps)
            next_step = self._get_next_step(completed_steps)

            # Calculate completion percentage
            completion_percentage = (len(completed_steps) / len(ONBOARDING_STEPS)) * 100

            # Check if fully completed
            fully_completed = len(completed_steps) == len(ONBOARDING_STEPS)

            # Format steps count
            steps_completed_count = f"{len(completed_steps)}/{len(ONBOARDING_STEPS)}"

            # Update summary in database
            await self.onboarding_repo.upsert_user_summary(
                user_id=user_id,
                current_step=current_step,
                next_step=next_step,
                completion_percentage=completion_percentage,
                fully_completed=fully_completed,
                steps_completed_count=steps_completed_count
            )

            logger.debug(f"Successfully updated onboarding summary for user {user_id}")

        except Exception as e:
            logger.error(f"Error updating onboarding summary for user {user_id}: {e}",
                        extra={"user_id": user_id, "error_type": type(e).__name__})
            # Raise a warning-level HTTPException to inform frontend without breaking the flow
            # This allows the step update to succeed while alerting about summary issues
            raise HTTPException(
                status_code=status.HTTP_207_MULTI_STATUS,
                detail=f"Step updated successfully, but summary update failed: {str(e)}"
            )

# API Routes

@router.get("/api/v1/auth/me/onboarding/progress", response_model=UserProgress)
async def get_user_progress(
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Get current user's onboarding progress"""

    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # DEMO FIX: Demo users don't need onboarding - return fully completed progress
        # Demo tenants are pre-configured through cloning, so onboarding is not required
        if is_demo or user_id.startswith("demo-user-"):
            logger.info(f"Demo user {user_id} accessing onboarding progress - returning completed state")

            # Create all steps as completed for demo users
            demo_steps = []
            for step_name in ONBOARDING_STEPS:
                demo_steps.append(OnboardingStepStatus(
                    step_name=step_name,
                    completed=True,
                    completed_at=datetime.now(timezone.utc),
                    data={"auto_completed": True, "demo_mode": True}
                ))

            # Create a fully completed context state for demo users
            demo_context_state = WizardContextState(
                bakery_type="mixed",
                tenant_id="demo-tenant",
                subscription_tier="professional",
                ai_analysis_complete=True,
                inventory_review_completed=True,
                stock_entry_completed=True,
                categorization_completed=True,
                suppliers_completed=True,
                recipes_completed=True,
                quality_completed=True,
                team_completed=True,
                child_tenants_completed=False,
                ml_training_complete=True,
            )

            return UserProgress(
                user_id=user_id,
                steps=demo_steps,
                current_step="completion",
                next_step=None,
                completion_percentage=100.0,
                fully_completed=True,
                last_updated=datetime.now(timezone.utc),
                context_state=demo_context_state
            )

        # Regular user flow
        onboarding_service = OnboardingService(db)
        progress = await onboarding_service.get_user_progress(user_id)
        return progress

    except Exception as e:
        logger.error(f"Get onboarding progress error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get onboarding progress"
        )

@router.get("/api/v1/auth/users/{user_id}/onboarding/progress", response_model=UserProgress)
async def get_user_progress_by_id(
    user_id: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Get onboarding progress for a specific user
    Available for service-to-service calls and admin users
    """

    # Allow service tokens or admin users
    user_type = current_user.get("type", "user")
    user_role = current_user.get("role", "user")

    if user_type != "service" and user_role not in ["admin", "super_admin"]:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Insufficient permissions to access other users' onboarding progress"
        )

    try:
        # DEMO FIX: Handle demo users - return fully completed progress
        if user_id.startswith("demo-user-"):
            logger.info(f"Service requesting demo user {user_id} onboarding progress - returning completed state")

            # Create all steps as completed for demo users
            demo_steps = []
            for step_name in ONBOARDING_STEPS:
                demo_steps.append(OnboardingStepStatus(
                    step_name=step_name,
                    completed=True,
                    completed_at=datetime.now(timezone.utc),
                    data={"auto_completed": True, "demo_mode": True}
                ))

            # Create a fully completed context state for demo users
            demo_context_state = WizardContextState(
                bakery_type="mixed",
                tenant_id="demo-tenant",
                subscription_tier="professional",
                ai_analysis_complete=True,
                inventory_review_completed=True,
                stock_entry_completed=True,
                categorization_completed=True,
                suppliers_completed=True,
                recipes_completed=True,
                quality_completed=True,
                team_completed=True,
                child_tenants_completed=False,
                ml_training_complete=True,
            )

            return UserProgress(
                user_id=user_id,
                steps=demo_steps,
                current_step="completion",
                next_step=None,
                completion_percentage=100.0,
                fully_completed=True,
                last_updated=datetime.now(timezone.utc),
                context_state=demo_context_state
            )

        # Regular user flow
        onboarding_service = OnboardingService(db)
        progress = await onboarding_service.get_user_progress(user_id)
        return progress

    except Exception as e:
        logger.error(f"Get onboarding progress error for user {user_id}: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get onboarding progress"
        )

@router.put("/api/v1/auth/me/onboarding/step", response_model=UserProgress)
async def update_onboarding_step(
    update_request: UpdateStepRequest,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Update a specific onboarding step"""

    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # DEMO FIX: Demo users don't update onboarding - return completed progress
        if is_demo or user_id.startswith("demo-user-"):
            logger.info(f"Demo user {user_id} attempting to update onboarding step - returning completed state (no-op)")

            # Create all steps as completed for demo users
            demo_steps = []
            for step_name in ONBOARDING_STEPS:
                demo_steps.append(OnboardingStepStatus(
                    step_name=step_name,
                    completed=True,
                    completed_at=datetime.now(timezone.utc),
                    data={"auto_completed": True, "demo_mode": True}
                ))

            # Create a fully completed context state for demo users
            demo_context_state = WizardContextState(
                bakery_type="mixed",
                tenant_id="demo-tenant",
                subscription_tier="professional",
                ai_analysis_complete=True,
                inventory_review_completed=True,
                stock_entry_completed=True,
                categorization_completed=True,
                suppliers_completed=True,
                recipes_completed=True,
                quality_completed=True,
                team_completed=True,
                child_tenants_completed=False,
                ml_training_complete=True,
            )

            return UserProgress(
                user_id=user_id,
                steps=demo_steps,
                current_step="completion",
                next_step=None,
                completion_percentage=100.0,
                fully_completed=True,
                last_updated=datetime.now(timezone.utc),
                context_state=demo_context_state
            )

        # Regular user flow
        onboarding_service = OnboardingService(db)
        progress = await onboarding_service.update_step(
            user_id,
            update_request
        )
        return progress

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Update onboarding step error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to update onboarding step"
        )

@router.get("/api/v1/auth/me/onboarding/next-step")
async def get_next_step(
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Get next required step for user"""
    
    try:
        onboarding_service = OnboardingService(db)
        result = await onboarding_service.get_next_step(current_user["user_id"])
        return result
        
    except Exception as e:
        logger.error(f"Get next step error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get next step"
        )

@router.get("/api/v1/auth/me/onboarding/can-access/{step_name}")
async def can_access_step(
    step_name: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Check if user can access a specific step"""
    
    try:
        onboarding_service = OnboardingService(db)
        result = await onboarding_service.can_access_step(
            current_user["user_id"], 
            step_name
        )
        return result
        
    except Exception as e:
        logger.error(f"Can access step error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to check step access"
        )

@router.post("/api/v1/auth/me/onboarding/complete")
async def complete_onboarding(
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """Complete entire onboarding process"""

    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # DEMO FIX: Demo users don't need to complete onboarding - return success
        if is_demo or user_id.startswith("demo-user-"):
            logger.info(f"Demo user {user_id} attempting to complete onboarding - returning success (no-op)")
            return {
                "success": True,
                "message": "Onboarding already completed for demo account",
                "optional_steps_skipped": [],
                "demo_mode": True
            }

        # Regular user flow
        onboarding_service = OnboardingService(db)
        result = await onboarding_service.complete_onboarding(user_id)
        return result

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Complete onboarding error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to complete onboarding"
        )

@router.put("/api/v1/auth/me/onboarding/step-draft")
async def save_step_draft(
    request: SaveStepDraftRequest,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Save in-progress step data without marking the step as complete.
    This allows users to save their work and resume later.
    """
    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # Demo users don't save drafts
        if is_demo or user_id.startswith("demo-user-"):
            logger.info(f"Demo user {user_id} attempting to save draft - returning success (no-op)")
            return {"success": True, "demo_mode": True}

        # Validate step name
        if request.step_name not in ONBOARDING_STEPS:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid step name: {request.step_name}"
            )

        # Save the draft data
        onboarding_repo = OnboardingRepository(db)
        await onboarding_repo.upsert_user_step(
            user_id=user_id,
            step_name=request.step_name,
            completed=False,
            step_data={**request.draft_data, "is_draft": True, "draft_saved_at": datetime.now(timezone.utc).isoformat()}
        )

        logger.info(f"Saved draft for step {request.step_name} for user {user_id}")
        return {"success": True, "step_name": request.step_name}

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Save step draft error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to save step draft"
        )

@router.get("/api/v1/auth/me/onboarding/step-draft/{step_name}")
async def get_step_draft(
    step_name: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Get saved draft data for a specific step.
    Returns null if no draft exists or the step is already completed.
    """
    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # Demo users don't have drafts
        if is_demo or user_id.startswith("demo-user-"):
            return {"step_name": step_name, "draft_data": None, "demo_mode": True}

        # Validate step name
        if step_name not in ONBOARDING_STEPS:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid step name: {step_name}"
            )

        # Get the step data
        onboarding_repo = OnboardingRepository(db)
        step = await onboarding_repo.get_user_step(user_id, step_name)

        # Return draft data only if step exists, is not completed, and has draft flag
        if step and not step.completed and step.step_data and step.step_data.get("is_draft"):
            return {
                "step_name": step_name,
                "draft_data": step.step_data,
                "draft_saved_at": step.step_data.get("draft_saved_at")
            }

        return {"step_name": step_name, "draft_data": None}

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Get step draft error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to get step draft"
        )

@router.delete("/api/v1/auth/me/onboarding/step-draft/{step_name}")
async def delete_step_draft(
    step_name: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Delete saved draft data for a specific step.
    Called after step is completed to clean up draft data.
    """
    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # Demo users don't have drafts
        if is_demo or user_id.startswith("demo-user-"):
            return {"success": True, "demo_mode": True}

        # Validate step name
        if step_name not in ONBOARDING_STEPS:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid step name: {step_name}"
            )

        # Get the step data and remove draft flag
        onboarding_repo = OnboardingRepository(db)
        step = await onboarding_repo.get_user_step(user_id, step_name)

        if step and step.step_data and step.step_data.get("is_draft"):
            # Remove draft-related fields but keep other data
            updated_data = {k: v for k, v in step.step_data.items() if k not in ["is_draft", "draft_saved_at"]}
            await onboarding_repo.upsert_user_step(
                user_id=user_id,
                step_name=step_name,
                completed=step.completed,
                step_data=updated_data
            )

        logger.info(f"Deleted draft for step {step_name} for user {user_id}")
        return {"success": True, "step_name": step_name}

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Delete step draft error: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete step draft"
        )

@router.get("/api/v1/auth/me/onboarding/subscription-parameters", response_model=Dict[str, Any])
async def get_subscription_parameters(
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Get subscription parameters saved during onboarding for tenant creation
    Returns all parameters needed for subscription processing: plan, billing cycle, coupon, etc.
    """
    try:
        user_id = current_user["user_id"]
        is_demo = current_user.get("is_demo", False)

        # DEMO FIX: Demo users get default subscription parameters
        if is_demo or user_id.startswith("demo-user-"):
            logger.info(f"Demo user {user_id} requesting subscription parameters - returning demo defaults")
            return {
                "subscription_plan": "professional",
                "billing_cycle": "monthly",
                "coupon_code": "DEMO2025",
                "payment_method_id": "pm_demo_test_123",
                "payment_customer_id": "cus_demo_test_123",  # Demo payment customer ID
                "saved_at": datetime.now(timezone.utc).isoformat(),
                "demo_mode": True
            }

        # Get subscription parameters from onboarding progress
        from app.repositories.onboarding_repository import OnboardingRepository
        onboarding_repo = OnboardingRepository(db)
        subscription_params = await onboarding_repo.get_subscription_parameters(user_id)

        if not subscription_params:
            logger.warning(f"No subscription parameters found for user {user_id} - returning defaults")
            return {
                "subscription_plan": "starter",
                "billing_cycle": "monthly",
                "coupon_code": None,
                "payment_method_id": None,
                "payment_customer_id": None,
                "saved_at": datetime.now(timezone.utc).isoformat()
            }

        logger.info(f"Retrieved subscription parameters for user {user_id}",
                   subscription_plan=subscription_params["subscription_plan"],
                   billing_cycle=subscription_params["billing_cycle"],
                   coupon_code=subscription_params["coupon_code"])

        return subscription_params

    except Exception as e:
        logger.error(f"Error getting subscription parameters for user {current_user.get('user_id')}: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve subscription parameters"
        )

@router.get("/api/v1/auth/users/{user_id}/onboarding/subscription-parameters", response_model=Dict[str, Any])
async def get_user_subscription_parameters(
    user_id: str,
    current_user: Dict[str, Any] = Depends(get_current_user_dep),
    db: AsyncSession = Depends(get_db)
):
    """
    Get subscription parameters for a specific user (admin/service access)
    """
    try:
        # Check permissions - only admins and services can access other users' data
        requester_id = current_user["user_id"]
        requester_roles = current_user.get("roles", [])
        is_service = current_user.get("is_service", False)

        if not is_service and "super_admin" not in requester_roles and requester_id != user_id:
            logger.warning(f"Unauthorized access attempt to user {user_id} subscription parameters by {requester_id}")
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Insufficient permissions to access other users' subscription parameters"
            )

        # Get subscription parameters from onboarding progress
        from app.repositories.onboarding_repository import OnboardingRepository
        onboarding_repo = OnboardingRepository(db)
        subscription_params = await onboarding_repo.get_subscription_parameters(user_id)

        if not subscription_params:
            logger.warning(f"No subscription parameters found for user {user_id} - returning defaults")
            return {
                "subscription_plan": "starter",
                "billing_cycle": "monthly",
                "coupon_code": None,
                "payment_method_id": None,
                "payment_customer_id": None,
                "saved_at": datetime.now(timezone.utc).isoformat()
            }

        logger.info(f"Retrieved subscription parameters for user {user_id} by {requester_id}",
                   subscription_plan=subscription_params["subscription_plan"])

        return subscription_params

    except Exception as e:
        logger.error(f"Error getting subscription parameters for user {user_id}: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve subscription parameters"
        )