from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session
from typing import Optional, List
from utils.utils import get_db
from . import handler
from .schema import (
    PromotionCreate,
    PromotionUpdate,
    PromotionResponse,
    PromotionusageCreate,
    PromotionusageUpdate,
    PromotionusageResponse
)

router = APIRouter(prefix="/promotions", tags=["Promotions"])


@router.post(
    "/",
    response_model=PromotionResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Promotion",
    description="Creates a new promotion with discount rules and validity period. Returns 409 if the promotion code already exists. Validates that expiration date is after start date and required discount fields are present based on promotion type."
)
def create_promotion_route(data: PromotionCreate, db: Session = Depends(get_db)):
    return handler.create_promotion(db, data)


@router.get(
    "/",
    response_model=List[PromotionResponse],
    summary="List Promotions",
    description="Returns a paginated list of promotions. Supports optional filters for active status, promotion type, and search by name or code."
)
def list_promotions_route(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    is_active: Optional[bool] = None,
    promotion_type: Optional[str] = None,
    search: Optional[str] = None,
    db: Session = Depends(get_db)
):
    return handler.list_promotions(db, limit, offset, is_active, promotion_type, search)


@router.get(
    "/{id}",
    response_model=PromotionResponse,
    summary="Get Promotion By ID",
    description="Returns a single promotion by ID. Returns 404 if the promotion does not exist."
)
def get_promotion_route(id: str, db: Session = Depends(get_db)):
    return handler.get_promotion(db, id)


@router.get(
    "/code/{code}",
    response_model=PromotionResponse,
    summary="Get Promotion By Code",
    description="Returns a single promotion by its unique code. Returns 404 if the promotion code does not exist."
)
def get_promotion_by_code_route(code: str, db: Session = Depends(get_db)):
    return handler.get_promotion_by_code(db, code)


@router.put(
    "/{id}",
    response_model=PromotionResponse,
    summary="Update Promotion",
    description="Updates an existing promotion. Returns 404 if the promotion does not exist. Returns 409 if the new code conflicts with an existing promotion. Validates date ranges if start or expiration dates are updated."
)
def update_promotion_route(id: str, data: PromotionUpdate, db: Session = Depends(get_db)):
    return handler.update_promotion(db, id, data)


@router.delete(
    "/{id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Promotion",
    description="Deletes a promotion by ID. Returns 404 if the promotion does not exist. Cascades to delete all associated promotion usages."
)
def delete_promotion_route(id: str, db: Session = Depends(get_db)):
    return handler.delete_promotion(db, id)


@router.post(
    "/validate",
    response_model=PromotionResponse,
    summary="Validate Promotion Code",
    description="Validates a promotion code for a specific user and order total. Checks if the promotion is active, within validity period, has not exceeded usage limits, and meets minimum purchase requirements. Returns 400 if validation fails, 404 if promotion not found."
)
def validate_promotion_route(
    code: str = Query(...),
    user_id: str = Query(...),
    order_total: float = Query(..., gt=0),
    db: Session = Depends(get_db)
):
    return handler.validate_promotion(db, code, user_id, order_total)


@router.post(
    "/usages",
    response_model=PromotionusageResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create Promotion Usage",
    description="Records a promotion usage for a specific order. Increments the promotion's current usage count. Returns 404 if promotion, user, or order does not exist."
)
def create_promotion_usage_route(data: PromotionusageCreate, db: Session = Depends(get_db)):
    return handler.create_promotion_usage(db, data)


@router.get(
    "/usages",
    response_model=List[PromotionusageResponse],
    summary="List Promotion Usages",
    description="Returns a paginated list of promotion usages. Supports optional filters for promotion ID, user ID, and order ID."
)
def list_promotion_usages_route(
    limit: int = Query(20, ge=1, le=100),
    offset: int = Query(0, ge=0),
    promotion_id: Optional[str] = None,
    user_id: Optional[str] = None,
    order_id: Optional[str] = None,
    db: Session = Depends(get_db)
):
    return handler.list_promotion_usages(db, limit, offset, promotion_id, user_id, order_id)


@router.get(
    "/usages/{id}",
    response_model=PromotionusageResponse,
    summary="Get Promotion Usage By ID",
    description="Returns a single promotion usage record by ID. Returns 404 if the usage record does not exist."
)
def get_promotion_usage_route(id: str, db: Session = Depends(get_db)):
    return handler.get_promotion_usage(db, id)


@router.put(
    "/usages/{id}",
    response_model=PromotionusageResponse,
    summary="Update Promotion Usage",
    description="Updates an existing promotion usage record. Returns 404 if the usage record, promotion, user, or order does not exist."
)
def update_promotion_usage_route(id: str, data: PromotionusageUpdate, db: Session = Depends(get_db)):
    return handler.update_promotion_usage(db, id, data)


@router.delete(
    "/usages/{id}",
    status_code=status.HTTP_200_OK,
    summary="Delete Promotion Usage",
    description="Deletes a promotion usage record by ID. Returns 404 if the usage record does not exist."
)
def delete_promotion_usage_route(id: str, db: Session = Depends(get_db)):
    return handler.delete_promotion_usage(db, id)