from fastapi import APIRouter, HTTPException, Depends, UploadFile, File
from typing import List
from enum import Enum
from app.schemas.tcgplayer import TCGPlayerAPIOrderSummary, TCGPlayerAPIOrder
from app.schemas.generate import GenerateAddressLabelsRequest, GeneratePackingSlipsRequest, GeneratePullSheetsRequest, GenerateResponse, GenerateReturnLabelsRequest
from app.services.service_manager import ServiceManager
from sqlalchemy.orm import Session
from app.db.database import get_db
import logging
from datetime import datetime

logger = logging.getLogger(__name__)


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", response_model=GenerateResponse)
async def generate_pull_sheets(
    request: GeneratePullSheetsRequest,
    db: Session = Depends(get_db)
) -> GenerateResponse:
    """
    Generate and print pull sheets for the specified orders.
    
    Args:
        request: Dictionary containing:
            - order_ids: List of TCGPlayer order numbers
        
    Returns:
        Success status of the operation
    """
    try:
        pull_sheet_service = service_manager.get_service('pull_sheet')
        order_ids = request.order_ids
            
        pull_sheet = await pull_sheet_service.get_or_create_rendered_pull_sheet(db, order_ids)
        
        regular_printer = service_manager.get_service('regular_printer')
        success = await regular_printer.print_file(pull_sheet.path)
        # TODO: change to accept file instead of path
        return {"success": success, "message": "Pull sheets generated and printed successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate pull sheet: {str(e)}")

@router.post("/generate-packing-slips", response_model=GenerateResponse)
async def generate_packing_slips(
    request: GeneratePackingSlipsRequest,
    db: Session = Depends(get_db)
) -> GenerateResponse:
    """
    Generate and print packing slips for the specified orders.
    
    Args:
        request: Dictionary containing:
            - order_ids: List of TCGPlayer order numbers
    """
    try:
        order_management = service_manager.get_service('order_management')
        # get or create packing slips
        packing_slips = await order_management.get_or_create_packing_slip(db, request.order_ids)
        if packing_slips:
            # print packing slips
            label_printer = service_manager.get_service('label_printer')
            success = await label_printer.print_file(packing_slips.path, label_size="dk1241", label_type="packing_slip")
            return {"success": success, "message": "Packing slips generated and printed successfully"}
        return {"success": False, "message": "Packing slips not found"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate packing slips: {str(e)}")

@router.post("/generate-address-labels")
async def generate_address_labels(
    request: GenerateAddressLabelsRequest,
    db: Session = Depends(get_db)
) -> GenerateResponse:
    """
    Generate and print address labels for the specified orders.
    
    Args:
        request: Dictionary containing:
            - order_ids: List of TCGPlayer order numbers
            - label_type: Type of label to generate (dk1201 or dk1241)
        
    Returns:
        Success status of the operation
    """
    try:
        address_label_service = service_manager.get_service('address_label')
        address_labels = await address_label_service.get_or_create_address_labels(db, request.order_ids, request.label_type)
        if address_labels:
            # print address labels
            label_printer = service_manager.get_service('label_printer')
            for address_label in address_labels:
                success = await label_printer.print_file(address_label.path, label_size=request.label_type, label_type="address_label")
                if not success:
                    return {"success": False, "message": "Address labels not found"}
            return {"success": True, "message": "Address labels generated and printed successfully"}
        return {"success": False, "message": "Address labels not found"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate address labels: {str(e)}")

@router.post("/generate-return-labels")
async def generate_return_labels(
    request: GenerateReturnLabelsRequest,
    db: Session = Depends(get_db)
) -> GenerateResponse:
    """
    Generate and print return labels for the specified number of labels.
    
    Args:
        request: Dictionary containing:
            - number_of_labels: Number of return labels to generate
    """
    try:
        label_printer = service_manager.get_service('label_printer')
        success = await label_printer.print_file("app/data/assets/images/ccrcardsaddress.png", label_size="dk1201", label_type="return_label", copies=request.number_of_labels)
        return {"success": success, "message": "Return labels generated and printed successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to generate return labels: {str(e)}")

@router.post("/print-pirate-ship-label")
async def print_pirate_ship_label(
    file: UploadFile = File(...),
    db: Session = Depends(get_db)
) -> GenerateResponse:
    """
    Print a PDF file uploaded via the API.
    
    Args:
        file: The PDF file to print
        
    Returns:
        Success status of the operation
    """
    try:
        # Read the file content
        content = await file.read()
        
        # Store the file using FileService
        file_service = service_manager.get_service('file')
        stored_file = await file_service.save_file(
            db=db,
            file_data=content,
            filename=file.filename,
            subdir="pirate_ship_labels",
            file_type="pdf",
            content_type=file.content_type,
            metadata={"filename": file.filename}
        )
        
        try:
            # Use the label printer service to print the file
            label_printer = service_manager.get_service('label_printer')
            success = await label_printer.print_file(stored_file, label_size="dk1241", label_type="pirate_ship_label")
            
            return {"success": success, "message": "Pirate Ship label printed successfully"}
        except Exception as e:
            # If printing fails, we'll keep the file in storage for potential retry
            logger.error(f"Failed to print file: {str(e)}")
            raise e
            
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to print Pirate Ship label: {str(e)}")

@router.post("/process-manabox-csv")
async def process_manabox_csv(
    file: UploadFile = File(...),
    db: Session = Depends(get_db)
) -> GenerateResponse:
    try:
        # ensure csv
        if file.content_type != "text/csv":
            raise HTTPException(status_code=400, detail="File must be a CSV")
        # read file
        content = await file.read()
        # save file
        file_service = service_manager.get_service('file')
        stored_file = await file_service.save_file(db, content, f'manabox_upload_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv', "manabox_csvs", "csv")
        # process csv
        manabox_service = service_manager.get_service('manabox')
        success = await manabox_service.process_manabox_csv(db, stored_file)
        return {"success": success, "message": "Manabox CSV processed successfully"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Failed to process Manabox CSV: {str(e)}")
