"""
Printer Settings API — persisted in AppSetting.meta_data for production durability.
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import Any, Dict, Optional

from pydantic import BaseModel, ConfigDict

from app.core.database import get_db
from app.models.app_setting import AppSetting
from app.services.printer_settings_service import (
    PRINTER_SECTIONS,
    PrinterSettingsService,
)
from app.utils.logger import get_logger

logger = get_logger(__name__)

router = APIRouter()


class FlexibleSettings(BaseModel):
    """Accept any printer fields the UI sends."""

    model_config = ConfigDict(extra="allow")


def _svc(db: Session) -> PrinterSettingsService:
    return PrinterSettingsService(db)


@router.get("/printers")
async def get_all_printer_settings(db: Session = Depends(get_db)):
    """All printer sections (invoice, pos, reports, sales, statements, quotations)."""
    try:
        return {"success": True, "data": _svc(db).get_all()}
    except Exception as e:
        logger.exception("get_all_printer_settings failed: %s", e)
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/invoice-printer/types")
async def get_invoice_printer_types():
    return {
        "success": True,
        "data": {"printer_types": PrinterSettingsService.invoice_printer_types()},
    }


@router.get("/invoice-printer")
async def get_invoice_printer_settings(db: Session = Depends(get_db)):
    try:
        return {"success": True, "data": _svc(db).get_section("invoice")}
    except Exception as e:
        logger.exception("get_invoice_printer_settings: %s", e)
        return {"success": False, "error": str(e), "data": _svc(db).get_section("invoice")}


@router.put("/invoice-printer")
async def update_invoice_printer_settings(
    settings_data: FlexibleSettings,
    db: Session = Depends(get_db),
):
    try:
        payload = settings_data.model_dump(exclude_unset=True)
        merged = _svc(db).update_section("invoice", payload)
        return {"success": True, "message": "Invoice printer settings saved", "data": merged}
    except Exception as e:
        logger.exception("update_invoice_printer_settings: %s", e)
        db.rollback()
        return {"success": False, "error": str(e)}


@router.get("/pos-receipt")
async def get_pos_receipt_settings(db: Session = Depends(get_db)):
    try:
        return {"success": True, "data": _svc(db).get_section("pos")}
    except Exception as e:
        logger.exception("get_pos_receipt_settings: %s", e)
        return {"success": False, "error": str(e), "data": _svc(db).get_section("pos")}


@router.put("/pos-receipt")
async def update_pos_receipt_settings(
    settings_data: FlexibleSettings,
    db: Session = Depends(get_db),
):
    try:
        payload = settings_data.model_dump(exclude_unset=True)
        if "printer_name" in payload and "pos_default_printer_name" not in payload:
            payload["pos_default_printer_name"] = payload["printer_name"]
        if "receipt_format" in payload and "pos_receipt_printer_type" not in payload:
            from app.services.printer_settings_service import RECEIPT_FORMAT_TO_PRINTER_TYPE

            payload["pos_receipt_printer_type"] = RECEIPT_FORMAT_TO_PRINTER_TYPE.get(
                payload["receipt_format"], "thermal_80mm"
            )
        merged = _svc(db).update_section("pos", payload)
        return {"success": True, "message": "POS receipt settings saved", "data": merged}
    except Exception as e:
        logger.exception("update_pos_receipt_settings: %s", e)
        db.rollback()
        return {"success": False, "error": str(e)}


@router.get("/document-printer/{section}")
async def get_document_printer_settings(section: str, db: Session = Depends(get_db)):
    if section not in ("reports", "sales", "statements", "quotations"):
        raise HTTPException(
            status_code=404,
            detail=f"Unknown section. Use one of: reports, sales, statements, quotations",
        )
    try:
        return {"success": True, "data": _svc(db).get_section(section)}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.put("/document-printer/{section}")
async def update_document_printer_settings(
    section: str,
    settings_data: FlexibleSettings,
    db: Session = Depends(get_db),
):
    if section not in ("reports", "sales", "statements", "quotations"):
        raise HTTPException(status_code=404, detail="Unknown document printer section")
    try:
        merged = _svc(db).update_section(section, settings_data.model_dump(exclude_unset=True))
        return {
            "success": True,
            "message": f"{section.title()} printer settings saved",
            "data": merged,
        }
    except Exception as e:
        db.rollback()
        return {"success": False, "error": str(e)}


@router.get("/document-printer/types")
async def get_document_printer_types():
    return {
        "success": True,
        "data": {"printer_types": PrinterSettingsService.document_printer_types()},
    }


@router.get("/available-printers")
async def get_available_printers():
    """List OS printers when available (Windows); browser print otherwise."""
    try:
        import win32print

        default_printer = win32print.GetDefaultPrinter()
        printer_list = win32print.EnumPrinters(
            win32print.PRINTER_ENUM_LOCAL | win32print.PRINTER_ENUM_CONNECTIONS
        )
        printers = [
            {
                "name": printer[2],
                "is_default": printer[2] == default_printer,
                "status": "Ready",
            }
            for printer in printer_list
        ]
        return {
            "success": True,
            "printers": printers,
            "default_printer": default_printer,
        }
    except ImportError:
        return {
            "success": True,
            "printers": [
                {"name": "Microsoft Print to PDF", "is_default": True, "status": "Ready"},
                {"name": "(Use browser print dialog)", "is_default": False, "status": "Ready"},
            ],
            "default_printer": "Microsoft Print to PDF",
            "note": "Server-side printer enumeration unavailable; use browser print.",
        }
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "printers": [],
            "default_printer": "",
        }
