from typing import Optional
from fastapi import APIRouter, File, UploadFile, Depends, HTTPException, status, Form, Query
from sqlmodel import Session

from app.db.session import get_session
from app.api.deps import require_roles
from app.models.user import User, Role
from app.schemas.product_template import ProductTemplateRead, ProductTemplateListResponse
from app.schemas.common import PaginatedResponse
from app.services.product_template_service import ProductTemplateService
from app.core.logging import setup_logger
from app.core.constants import (
    ERR_PSD_PROCESSING_FAILED,
    ERR_RETRIEVE_PSD,
    ERR_UPDATE_TEMPLATE,
    ERR_DELETE_TEMPLATE
)

logger = setup_logger(__name__)
router = APIRouter(prefix="/api/product-templates", tags=["Product Templates"])

@router.post(
    "/upload",
    response_model=ProductTemplateRead,
    status_code=status.HTTP_201_CREATED,
    summary="Upload a new product template (PSD)",
    description="Upload a PSD file, create a DB record and generate an optional PNG preview.",
)
async def upload_product_template(
    name: str = Form(..., description="Human-friendly name of the template."),
    psd_file: UploadFile = File(..., description="PSD file to upload."),
    db: Session = Depends(get_session),
    current_user: User = Depends(require_roles(Role.SUPERADMIN, Role.ADMIN)),
):
    """
    Upload a PSD product template and persist metadata.
    """
    try:
        tpl = await ProductTemplateService.upload_template(
            name=name,
            psd_file=psd_file,
            user_id=current_user.id,
            session=db,
        )
        return tpl
    except HTTPException:
        raise
    except Exception:
        logger.exception("Unexpected error during PSD upload")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=ERR_PSD_PROCESSING_FAILED)

@router.get(
    "/list",
    response_model=PaginatedResponse[ProductTemplateRead],
    status_code=status.HTTP_200_OK,
    summary="List product templates",
    description="Retrieve non-deleted product templates.",
)
def list_product_templates(
    page: int = Query(1, ge=1),
    limit: int = Query(10, ge=1, le=200),
    search: Optional[str] = Query(None),
    sort_by: Optional[str] = Query("created_at"),
    order: Optional[str] = Query("desc"),
    db: Session = Depends(get_session),
    current_user: User = Depends(require_roles(Role.SUPERADMIN, Role.ADMIN)),
):
    """Return active product templates."""
    try:
        if sort_by not in ["id", "name", "created_at", "updated_at"]:
            raise HTTPException(400, "Invalid sort_by field")
        if order not in ["asc", "desc"]:
            raise HTTPException(400, "Invalid order")
        result = ProductTemplateService.list_templates(
            session=db,
            page=page,
            limit=limit,
            search=search,
            sort_by=sort_by,
            order=order,
        )
        return result
    except HTTPException:
        raise
    except Exception:
        logger.exception("Database error while listing templates")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve templates",
        )

@router.get(
    "/detail/{template_id}",
    response_model=ProductTemplateRead,
    status_code=status.HTTP_200_OK,
    summary="Get product template detail",
    description="Retrieve a single product template by ID.",
)
def get_product_template(
    template_id: int,
    db: Session = Depends(get_session),
    current_user: User = Depends(require_roles(Role.SUPERADMIN, Role.ADMIN)),
):
    """
    Retrieve a template by ID, ensuring it is not deleted.
    """
    try:
        tpl = ProductTemplateService.get_template_by_id(template_id, db)
        return tpl
    except HTTPException:
        raise
    except Exception:
        logger.exception("Unexpected error while retrieving template detail")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=ERR_RETRIEVE_PSD,
        )

@router.patch(
    "/update/{template_id}",
    response_model=ProductTemplateRead,
    status_code=status.HTTP_200_OK,
    summary="Update a product template",
    description="Update name and/or replace PSD file (regenerates preview).",
)
async def update_product_template(
    template_id: int,
    name: Optional[str] = Form(None, description="New name for template."),
    new_psd: Optional[UploadFile] = File(None, description="Optional replacement PSD file."),
    db: Session = Depends(get_session),
    current_user: User = Depends(require_roles(Role.SUPERADMIN, Role.ADMIN)),
):
    """Update the product template's metadata and/or file."""
    try:
        tpl = await ProductTemplateService.update_template(
            template_id=template_id,
            name=name,
            new_psd=new_psd,
            session=db,
        )
        return tpl
    except HTTPException:
        raise
    except Exception:
        logger.exception("Unexpected error while updating template")
        raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=ERR_UPDATE_TEMPLATE)

# @router.delete(
#     "/delete/{template_id}",
#     status_code=status.HTTP_200_OK,
#     summary="Delete a product template",
#     description="Soft-delete template and attempt to remove associated files.",
# )
# def delete_product_template(
#     template_id: int,
#     db: Session = Depends(get_session),
#     current_user: User = Depends(require_roles(Role.SUPERADMIN, Role.ADMIN)),
# ):
#     """Soft-delete a template and attempt file cleanup."""
#     try:
#         ProductTemplateService.delete_template(template_id, db)
#         return {"success": True}
#     except HTTPException:
#         raise
#     except Exception:
#         logger.exception("Unexpected error while deleting template")
#         raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=ERR_DELETE_TEMPLATE)
