from fastapi import APIRouter, HTTPException, Depends, Query
from app.services.external_api.tcgplayer.order_management_service import OrderManagementService
from app.services.label_printer_service import LabelPrinterService
from app.services.regular_printer_service import RegularPrinterService
from app.services.address_label_service import AddressLabelService
from typing import List, Optional, Literal
from datetime import datetime
from pydantic import BaseModel, Field
from enum import Enum
from app.schemas.tcgplayer import TCGPlayerAPIOrderSummary, TCGPlayerAPIOrder
from app.services.service_manager import ServiceManager



class SearchRange(str, Enum):
    LAST_WEEK = "LastWeek"
    LAST_MONTH = "LastMonth"
    LAST_THREE_MONTHS = "LastThreeMonths"
    LAST_FOUR_MONTHS = "LastFourMonths"
    LAST_TWO_YEARS = "LastTwoYears"

class LabelType(str, Enum):
    DK1201 = "dk1201"
    DK1241 = "dk1241"

# Initialize service manager
service_manager = ServiceManager()

# Initialize router
router = APIRouter(prefix="/orders")

@router.get("/", response_model=List[TCGPlayerAPIOrderSummary])
async def get_orders(
    search_range: SearchRange = SearchRange.LAST_THREE_MONTHS,
    open_only: bool = False
) -> List[TCGPlayerAPIOrderSummary]:
    """
    Retrieve orders from TCGPlayer based on search criteria.
    
    Args:
        search_range: Time range to search for orders
        open_only: Whether to only return open orders
        
    Returns:
        List of orders matching the search criteria
    """
    try:
        order_management = service_manager.get_service('order_management')
        orders = await order_management.get_orders(search_range, open_only)
        return orders
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to fetch orders: {str(e)}")

@router.get("/{order_id}", response_model=TCGPlayerAPIOrder)
async def get_order(order_id: str) -> TCGPlayerAPIOrder:
    """
    Retrieve a specific order by ID.
    
    Args:
        order_id: The TCGPlayer order number
        
    Returns:
        The requested order details
    """
    try:
        order_management = service_manager.get_service('order_management')
        order = await order_management.get_order(order_id)
        if not order:
            raise HTTPException(status_code=404, detail=f"Order {order_id} not found")
        return order
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to fetch order: {str(e)}")

@router.post("/generate-pull-sheets")
async def generate_pull_sheets(
    order_ids: Optional[List[str]] = None,
    all_open_orders: bool = False
) -> dict:
    """
    Generate and print pull sheets for the specified orders.
    
    Args:
        order_ids: List of TCGPlayer order numbers (optional if all_open_orders is True)
        all_open_orders: If True, generate pull sheets for all orders (ignores order_ids)
        
    Returns:
        Success status of the operation
    """
    try:
        order_management = service_manager.get_service('order_management')
        if not all_open_orders and not order_ids:
            raise HTTPException(
                status_code=400, 
                detail="Either order_ids must be provided or all_open_orders must be True"
            )
            
        if all_open_orders:
            order_ids = await order_management.get_order_ids(search_range="LastWeek", open_only=True)
            
        pull_sheet = await order_management.get_pull_sheet(order_ids)
        pull_sheet_file = await order_management.save_file(
            pull_sheet, 
            f"pull_sheet_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.csv"
        )
        pull_sheet_service = service_manager.get_service('pull_sheet')
        pull_sheet_pdf = await pull_sheet_service.generate_pull_sheet_pdf(pull_sheet_file)
        regular_printer = service_manager.get_service('regular_printer')
        success = await regular_printer.print_file(pull_sheet_pdf)
        return {"success": success}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate pull sheet: {str(e)}")

@router.post("/generate-packing-slips")
async def generate_packing_slips(
    order_ids: Optional[List[str]] = None,
    all_open_orders: bool = False
) -> dict:
    """
    Generate and print packing slips for the specified orders.
    
    Args:
        order_ids: List of TCGPlayer order numbers (optional if all_open_orders is True)
        all_open_orders: If True, generate packing slips for all orders (ignores order_ids)
        
    Returns:
        Success status of the operation
    """
    try:
        if not all_open_orders and not order_ids:
            raise HTTPException(
                status_code=400, 
                detail="Either order_ids must be provided or all_open_orders must be True"
            )
            
        # TODO: Add logic to fetch all orders when all_open_orders is True
        if all_open_orders:
            order_management = service_manager.get_service('order_management')
            order_ids = await order_management.get_order_ids(search_range="LastWeek", open_only=True)
            
        packing_slip = await order_management.get_packing_slip(order_ids)
        packing_slip_file = await order_management.save_file(
            packing_slip, 
            f"packing_slip_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.pdf"
        )
        label_printer = service_manager.get_service('label_printer')
        success = await label_printer.print_file(
            packing_slip_file, 
            label_size="dk1241", 
            label_type="packing_slip"
        )
        return {"success": success}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate packing slip: {str(e)}")

@router.post("/generate-address-labels")
async def generate_address_labels(
    order_ids: Optional[List[str]] = None,
    all_open_orders: bool = False,
    label_type: LabelType = LabelType.DK1201
) -> dict:
    """
    Generate and print address labels for the specified orders.
    
    Args:
        order_ids: List of TCGPlayer order numbers (optional if all_open_orders is True)
        all_open_orders: If True, generate address labels for all orders (ignores order_ids)
        label_type: Type of label to generate (dk1201 or dk1241)
        
    Returns:
        Success status of the operation
    """
    try:
        order_management = service_manager.get_service('order_management')
        if not all_open_orders and not order_ids:
            raise HTTPException(
                status_code=400, 
                detail="Either order_ids must be provided or all_open_orders must be True"
            )
            
        if all_open_orders:
            order_ids = await order_management.get_order_ids(search_range="LastWeek", open_only=True)
            
        shipping_csv = await order_management.get_shipping_csv(order_ids)
        shipping_csv_file = await order_management.save_file(
            shipping_csv, 
            f"shipping_csv_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.csv"
        )
        
        # Generate PDFs
        address_label = service_manager.get_service('address_label')
        pdf_files = await address_label.generate_labels_from_csv(
            shipping_csv_file, 
            label_type=label_type
        )
        
        # Print each PDF
        label_printer = service_manager.get_service('label_printer')
        for pdf_file in pdf_files:
            success = await label_printer.print_file(
                pdf_file, 
                label_size=label_type, 
                label_type="address_label"
            )
            if not success:
                raise HTTPException(
                    status_code=500, 
                    detail=f"Failed to print address label for file {pdf_file}"
                )
                
        return {"success": True, "message": "Address labels generated and printed successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate address labels: {str(e)}")