

"""
Product Routes Module

This module defines all API endpoints for product management including:
- Fetching products (all users)
- Creating/editing products (permissions >= 1)
- Deleting products (permissions == 2 only)

Permission levels:
- 0: Regular user (read-only access)
- 1: Manager (can create/edit products)
- 2: Admin (full access including delete)
"""

# Standard library imports
from math import prod
from logging import getLogger
import time
from typing import Optional

# Third-party imports
from fastapi import APIRouter, Depends, Query
from fastapi.responses import JSONResponse
from h11 import Data

# Local imports
from auth.security import get_current_user
from models.user import User
from models.items import Product, ProductCreateRequest, ProductEditRequest
from services.data_service import DataServiceFactory
from config.messages import ErrorResponse, SuccessResponse, UserResponse
from services.print_service import print_ticket
from utils.responses import error_response, success_response

# Initialize logger for this module
logger = getLogger(__name__)

# Initialize data services for products and users
product_data_service = DataServiceFactory.get_product_service()
user_data_service = DataServiceFactory.get_user_service()

# Create router instance for product-related endpoints
product_router = APIRouter()

def apply_promo_price(product: Product):
    """Apply promotional price to a product if applicable."""
    #dia de la semana 1-7
    day_of_week = time.localtime().tm_wday + 1  # Convert to 1-7 range
    product_dict = product.model_dump(exclude={"promo_id", "promo_price", "promo_day"})
    if product.promo_id and product.promo_price and product.promo_day == day_of_week:
        product_dict['promotion'] = {
            "id": product.promo_id,
            "price": product.promo_price,
        }

    return product_dict

@product_router.get("/")
async def get_products(status: Optional[int] = Query(None), current_user = Depends(get_current_user)):
    """
    Get all products - Available to all authenticated users
    
    Returns:
        JSONResponse: List of all products with success message
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info("Fetching all products")
    
    # Retrieve all products and convert to dictionary format
    all_products =  product_data_service.get_all()
    all_products = list(map(apply_promo_price, all_products))


    if status is not None:
        # Filter products by status if provided
        all_products = [product for product in all_products if product['status'] == status]

    return success_response({"products": all_products}, message= SuccessResponse.PRODUCTS_FETCH_SUCCESS)

@product_router.get("/{product_id}")
async def get_product(product_id: int, current_user = Depends(get_current_user)):
    """
    Get a specific product by ID - Available to all authenticated users
    
    Args:
        product_id (int): The ID of the product to retrieve
        current_user: Authenticated user (dependency injection)
        
    Returns:
        JSONResponse: Product data if found, error message if not found
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info(f"Fetching product with ID: {product_id}")
    
    # Attempt to find product by ID
    product = product_data_service.get_by_id(product_id)
    if product:
        return success_response({"product": product.model_dump(exclude={"promo_id", "promo_price", "promo_day"})}, message = SuccessResponse.PRODUCTS_FETCH_SUCCESS)

    # Return 404 if product not found
    return error_response(message = UserResponse.USER_NOT_FOUND.format(user_id=product_id), status_code=404)

@product_router.get("/free-beer/{table_id}")
async def get_free_beer(table_id: int, current_user:User = Depends(get_current_user)):
    """
    Get the free beer product - Available to all authenticated users
    
    Returns:
        JSONResponse: Free beer product data if found, error message if not found
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info("Fetching free beer ticket")
    
    if current_user.reward_progress >= 100:
        print_ticket(table_id)
        return success_response(message= SuccessResponse.REWARD_SUCCESS, status_code=200)

    # Return 404 if free beer product not found
    return error_response(message= UserResponse.USER_NOT_FOUND.format(user_id="free_beer"), status_code=404)
# MODERATE RISK OPERATIONS - Requires permissions >= 1 (Manager level or above)

@product_router.post("/create")
async def create_product(product: ProductCreateRequest, current_user = Depends(get_current_user)):
    """
    Create a new product - Requires manager permissions (level >= 1)
    
    Args:
        product (ProductCreateRequest): New product data
        current_user: Authenticated user (dependency injection)
        
    Returns:
        JSONResponse: Success message or permission denied message
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info("Creating a new product")
    
    # Check if user has sufficient permissions (manager level or above)
    if user_data_service.permissions(current_user.id) > 0:
        # Create new product with provided data
        product_data_service.create(**product.model_dump(exclude_unset=True))
        return success_response(product.model_dump(), message= SuccessResponse.PRODUCT_CREATE_SUCCESS, status_code=201)
    
    # Return 403 if user lacks permissions
    return error_response(message= UserResponse.NOT_PERMITTED, status_code=403)

@product_router.patch("/{product_id}/swap-status")
async def switch_product_status(product_id: int, current_user = Depends(get_current_user)): 
    """
    Toggle product status between active/inactive - Requires manager permissions (level >= 1)
    
    Args:
        product_id (int): ID of the product to update
        status (int): New status value (0=inactive, 1=active)
        current_user: Authenticated user (dependency injection)
        
    Returns:
        JSONResponse: Success message or permission denied message
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info(f"Switching status for product with ID: {product_id}")
    
    # Check if user has sufficient permissions (manager level or above)
    if user_data_service.permissions(current_user.id) > 0:
        # Update only the status field of the specified product
        product = product_data_service.get_by_id(product_id)
        if not product:
            return error_response(message= ErrorResponse.PRODDUCT_NOT_FOUND.format(product_id=product_id), status_code=404)
        status = 0 if product.status == 1 else 1
        product_data_service.update(product_id, status=status)
        return success_response(message=SuccessResponse.PRODUCT_EDIT_SUCCESS)
    
    # Return 403 if user lacks permissions
    return error_response(message=UserResponse.NOT_PERMITTED, status_code=403)

# HIGH RISK OPERATIONS - Requires permissions == 2 (Admin level only)

@product_router.delete("/{product_id}")
async def delete_product(product_id: int, current_user = Depends(get_current_user)):
    """
    Delete a product permanently - Requires admin permissions (level == 2)
    
    This is a high-risk operation that permanently removes product data.
    Only users with admin-level permissions can perform this action.
    
    Args:
        product_id (int): ID of the product to delete
        current_user: Authenticated user (dependency injection)
        
    Returns:
        JSONResponse: Success message or permission denied message
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info(f"Deleting product with ID: {product_id}")
    
    # Check if user has admin permissions (exactly level 2)
    if user_data_service.permissions(current_user.id) == 2:
        # Permanently delete the product
        product_data_service.delete(product_id)
        return success_response(message=SuccessResponse.PRODUCT_DELETE_SUCCESS)
    
    # Return 403 if user lacks admin permissions    
    return error_response(message=UserResponse.NOT_PERMITTED, status_code=403)

@product_router.patch("/{product_id}/edit")
async def edit_product(product_id: int, product: ProductEditRequest, current_user = Depends(get_current_user)):
    """
    Edit an existing product - Requires manager permissions (level >= 1)
    
    Args:
        product (ProductEditRequest): Product data to update
        current_user: Authenticated user (dependency injection)
        
    Returns:
        JSONResponse: Updated product data or permission denied message
    """
    logger.debug(f"Current user: {current_user.email if current_user else 'Anonymous'}")
    logger.info(f"Editing product: {product_id}")
    
    # Check if user has sufficient permissions (manager level or above)
    if user_data_service.permissions(current_user.id) > 1:

        # Update product with provided data (excluding unset fields)
        product_data_service.update(product_id, **product.model_dump(exclude_unset=True))
        
        # Retrieve updated product to return in response
        edited_product = product_data_service.get_by_id(product_id)
        if not edited_product:
            return error_response(message=UserResponse.USER_NOT_FOUND.format(user_id=product_id), status_code=404)
        
        logger.info(f"Product {product_id} edited successfully")
        return success_response(data=edited_product.model_dump(), message=SuccessResponse.PRODUCT_EDIT_SUCCESS)
    
    # Return 403 if user lacks permissions    
    return error_response(message=UserResponse.NOT_PERMITTED, status_code=403)
