from fastapi import APIRouter, Depends, HTTPException, status, Query
from sqlalchemy.orm import Session
from typing import List, Optional
from datetime import datetime

from app.api import deps
from app.schemas.order import OrderCreate, OrderResponse, OrderSummary
from app.services import order_service

router = APIRouter()


@router.post("/checkout", response_model=OrderResponse, status_code=status.HTTP_201_CREATED)
def create_order_from_cart(
    order_data: OrderCreate,
    db: Session = Depends(deps.get_db),
    current_user = Depends(deps.get_current_user)
):
    """
    Creates a new order from the user's shopping cart.
    
    This endpoint:
    1. Validates product availability
    2. Checks if user has enough points
    3. Creates an order record
    4. Creates order item records
    5. Updates product stock
    6. Deducts points from user's balance
    7. Clears the user's shopping cart
    
    You can provide shipping details directly OR use an address_id to reference a saved address.
    If an address_id is provided, it will be used instead of shipping_details.
    
    Additionally, you can save the shipping details as a new address by setting save_address to True
    and providing an address_title. This is only applicable when providing shipping_details directly.
    
    If any validation fails (e.g., insufficient stock, insufficient points),
    the entire operation fails.
    """
    
    # Convert Pydantic model to dict for shipping details
    shipping_details = None
    if order_data.shipping_details:
        shipping_details = order_data.shipping_details.dict()
    
    # Create order from cart
    new_order = order_service.create_order_from_cart(
        db=db, 
        user_id=current_user.id,
        shipping_details=shipping_details,
        address_id=order_data.address_id,
        save_address=order_data.save_address,
        address_title=order_data.address_title
    )
    
    return new_order


@router.get("/{order_id}", response_model=OrderResponse)
def get_order(
    order_id: int,
    db: Session = Depends(deps.get_db),
    current_user = Depends(deps.get_current_user)
):
    """
    Retrieves a specific order by ID.
    Only returns the order if it belongs to the authenticated user.
    """
    order = order_service.get_order_by_id(db, order_id, current_user.id)
    if not order:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Order not found"
        )
    return order


@router.get("/", response_model=List[OrderResponse])
def get_user_orders(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(deps.get_db),
    current_user = Depends(deps.get_current_user)
):
    """
    Retrieves all orders for the authenticated user.
    Results are paginated and sorted by creation date (newest first).
    """
    orders = order_service.get_user_orders(db, current_user.id, skip, limit)
    return orders


@router.post("/{order_id}/cancel", response_model=OrderResponse)
def cancel_order(
    order_id: int,
    db: Session = Depends(deps.get_db),
    current_user = Depends(deps.get_current_user)
):
    """
    Cancels an existing order.
    
    This endpoint:
    1. Validates that the order exists and belongs to the user
    2. Checks if the order is in a cancellable state
    3. Changes the order status to "CANCELLED"
    4. Restores product stock
    5. Refunds the points used for the order
    
    Only orders in PENDING or PROCESSING status can be cancelled.
    """
    cancelled_order = order_service.cancel_order(
        db=db,
        order_id=order_id,
        user_id=current_user.id
    )
    
    return cancelled_order


@router.get("/summary/weekly", response_model=OrderSummary)
def get_weekly_order_summary(
    date: Optional[str] = Query(None, description="기준 날짜 (YYYY-MM-DD 형식). 제공되지 않으면 오늘 날짜 기준"),
    db: Session = Depends(deps.get_db)
):
    """
    주간 주문 요약 정보를 제공합니다.
    - 주간 고유 사용자 수
    - 주간 총 주문 건수
    - 주간 총 포인트 사용량
    
    로그인 없이 접근 가능합니다.
    """
    target_date = None
    if date:
        try:
            target_date = datetime.strptime(date, "%Y-%m-%d")
        except ValueError:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Invalid date format. Please use YYYY-MM-DD format."
            )
    
    return order_service.get_weekly_order_summary(db, target_date) 