"""
Persistent printer configuration stored in AppSetting.meta_data (production-safe).

Sections: invoice, pos, reports, sales, statements, quotations
"""
from __future__ import annotations

import copy
import json
from typing import Any, Dict, List, Optional

from sqlalchemy.orm import Session

from app.models.app_setting import AppSetting
from app.services.pos_print_service import normalize_paper_format

META_KEY = "printer_settings"

# Document sections configurable in Settings → Printer Settings
PRINTER_SECTIONS = (
    "invoice",
    "pos",
    "reports",
    "sales",
    "statements",
    "quotations",
)

DEFAULT_SECTIONS: Dict[str, Dict[str, Any]] = {
    "invoice": {
        "invoice_printer_type": "a4_pdf",
        "default_printer_name": "",
        "auto_print": False,
        "a4_paper_size": "A4",
        "a4_orientation": "portrait",
        "dot_matrix_paper_width": 80,
        "dot_matrix_form_length": 66,
        "dot_matrix_compressed": False,
        "dot_matrix_carbon_copies": 1,
        "dot_matrix_template": "standard_80",
    },
    "pos": {
        "receipt_format": "80mm",
        "pos_receipt_printer_type": "thermal_80mm",
        "pos_default_printer_name": "",
        "pos_auto_print": True,
        "pos_print_customer_copy": True,
        "pos_print_merchant_copy": False,
        "pos_receipt_width": 48,
        "pos_receipt_cut_type": "full",
        "pos_char_size": "normal",
        "pos_line_spacing": "normal",
        "pos_header_lines": 3,
        "pos_footer_lines": 2,
        "pos_logo_enabled": False,
        "pos_logo_height": 5,
        "pos_barcode_enabled": True,
        "pos_qr_code_enabled": False,
        "pos_template": "standard_thermal",
        "pos_paper_width_mm": 80,
        "header_text": "",
        "footer_text": "Thank you for your business!",
        "font_size": 12,
        "show_logo": True,
        "show_company_info": True,
        "show_vat_number": True,
        "copies": 1,
    },
    "reports": {
        "printer_type": "a4_pdf",
        "default_printer_name": "",
        "paper_size": "A4",
        "orientation": "portrait",
        "margins_mm": 12,
        "auto_print": False,
        "color_mode": "color",
    },
    "sales": {
        "printer_type": "a4_pdf",
        "default_printer_name": "",
        "paper_size": "A4",
        "orientation": "portrait",
        "margins_mm": 12,
        "auto_print": False,
        "color_mode": "color",
    },
    "statements": {
        "printer_type": "a4_pdf",
        "default_printer_name": "",
        "paper_size": "A4",
        "orientation": "portrait",
        "margins_mm": 12,
        "auto_print": False,
        "color_mode": "color",
    },
    "quotations": {
        "printer_type": "a4_pdf",
        "default_printer_name": "",
        "paper_size": "A4",
        "orientation": "portrait",
        "margins_mm": 12,
        "auto_print": False,
        "color_mode": "color",
    },
}

RECEIPT_FORMAT_TO_PRINTER_TYPE = {
    "50mm": "thermal_58mm",
    "80mm": "thermal_80mm",
    "a4": "custom",
    "continuous": "impact_76mm",
}

PRINTER_TYPE_TO_RECEIPT_FORMAT = {
    "thermal_58mm": "50mm",
    "thermal_50mm": "50mm",
    "thermal_80mm": "80mm",
    "impact_76mm": "continuous",
    "custom": "80mm",
}


def _deep_merge(base: Dict[str, Any], updates: Dict[str, Any]) -> Dict[str, Any]:
    out = copy.deepcopy(base)
    for key, value in (updates or {}).items():
        if isinstance(value, dict) and isinstance(out.get(key), dict):
            out[key] = _deep_merge(out[key], value)
        else:
            out[key] = value
    return out


class PrinterSettingsService:
    def __init__(self, db: Session):
        self.db = db
        self.instance = AppSetting.get_instance(db)

    def _load_meta(self) -> Dict[str, Any]:
        try:
            return json.loads(self.instance.meta_data) if self.instance.meta_data else {}
        except json.JSONDecodeError:
            return {}

    def _save_meta(self, meta: Dict[str, Any]) -> None:
        self.instance.meta_data = json.dumps(meta)

    def get_all(self) -> Dict[str, Dict[str, Any]]:
        stored = self._load_meta().get(META_KEY) or {}
        result: Dict[str, Dict[str, Any]] = {}
        for section in PRINTER_SECTIONS:
            result[section] = self.get_section(section, stored=stored)
        return result

    def get_section(
        self,
        section: str,
        *,
        stored: Optional[Dict[str, Any]] = None,
    ) -> Dict[str, Any]:
        if section not in DEFAULT_SECTIONS:
            raise ValueError(f"Unknown printer section: {section}")

        if stored is None:
            stored = self._load_meta().get(META_KEY) or {}

        merged = _deep_merge(
            DEFAULT_SECTIONS[section],
            stored.get(section, {}) if isinstance(stored.get(section), dict) else {},
        )

        if section == "pos":
            col_fmt = getattr(self.instance, "default_receipt_format", None)
            if col_fmt:
                merged["receipt_format"] = normalize_paper_format(col_fmt)
            merged["receipt_format"] = normalize_paper_format(
                merged.get("receipt_format") or "80mm"
            )
            if not merged.get("pos_receipt_printer_type"):
                merged["pos_receipt_printer_type"] = RECEIPT_FORMAT_TO_PRINTER_TYPE.get(
                    merged["receipt_format"], "thermal_80mm"
                )

        return merged

    def update_section(self, section: str, updates: Dict[str, Any]) -> Dict[str, Any]:
        if section not in DEFAULT_SECTIONS:
            raise ValueError(f"Unknown printer section: {section}")

        meta = self._load_meta()
        stored = meta.get(META_KEY) or {}
        if not isinstance(stored, dict):
            stored = {}

        current = self.get_section(section, stored=stored)
        merged = _deep_merge(current, updates or {})

        if section == "pos":
            if updates.get("receipt_format"):
                merged["receipt_format"] = normalize_paper_format(updates["receipt_format"])
            elif updates.get("pos_receipt_printer_type"):
                merged["receipt_format"] = PRINTER_TYPE_TO_RECEIPT_FORMAT.get(
                    updates["pos_receipt_printer_type"],
                    merged.get("receipt_format", "80mm"),
                )
            merged["receipt_format"] = normalize_paper_format(merged.get("receipt_format", "80mm"))
            merged["pos_receipt_printer_type"] = (
                updates.get("pos_receipt_printer_type")
                or RECEIPT_FORMAT_TO_PRINTER_TYPE.get(merged["receipt_format"], "thermal_80mm")
            )
            if hasattr(self.instance, "default_receipt_format"):
                self.instance.default_receipt_format = merged["receipt_format"]

        stored[section] = merged
        meta[META_KEY] = stored
        self._save_meta(meta)
        self.db.commit()
        self.db.refresh(self.instance)
        return merged

    @staticmethod
    def invoice_printer_types() -> List[Dict[str, Any]]:
        return [
            {
                "value": "a4_pdf",
                "name": "A4 PDF (Laser / Inkjet)",
                "description": "Professional full-page invoices (PDF)",
                "supports": ["high_quality", "graphics", "colors", "logos"],
            },
            {
                "value": "dot_matrix",
                "name": "Dot Matrix / Continuous",
                "description": "Impact printer on tractor-feed continuous paper",
                "supports": ["continuous_paper", "carbon_copies", "fast_printing", "low_cost"],
            },
        ]

    @staticmethod
    def document_printer_types() -> List[Dict[str, Any]]:
        return [
            {
                "value": "a4_pdf",
                "name": "A4 PDF",
                "description": "Standard office printer (PDF in browser)",
                "supports": ["high_quality", "graphics"],
            },
            {
                "value": "dot_matrix",
                "name": "Dot Matrix / Continuous",
                "description": "Plain-text layout for continuous forms",
                "supports": ["continuous_paper", "fast_printing"],
            },
        ]
