from pypos.core.base_model import BaseModel
from pypos.modules.printer.models.printer_settings_model import PrinterSettingsModel

class PrinterModel(BaseModel):
    def __init__(self, *args, settings_model=None, io_service=None, **kwargs):
        super().__init__()
        self.settings_model = settings_model or PrinterSettingsModel()
        self.io_service = io_service or self._build_default_io_service()

    def _build_default_io_service(self):
        module = __import__(
            "pypos.modules.printer.services.printer_io_service",
            fromlist=["PrinterIOService"],
        )
        return module.PrinterIOService()

    def get_all(self):
        """Ambil semua printer dari database"""
        printers = self.settings_model.load_printers()
        return [self._to_legacy_schema(p) for p in printers]

    def add_printer(self, data):
        """Tambah printer baru"""
        printers = self.settings_model.load_printers()
        new_rec = self._from_legacy_input(data)
        if new_rec.get("default"):
            for p in printers:
                p["default"] = False
                p["is_default"] = 0
        printers.append(new_rec)
        self.settings_model.save_printers(printers)

    def update_printer(self, printer_id, data):
        """Update data printer"""
        printers = self.settings_model.load_printers()
        updated = []
        set_default = bool(int(data.get("is_default") or data.get("default") or 0))
        for p in printers:
            if int(p.get("id") or 0) == int(printer_id):
                updated.append(self._merge_update(p, data))
            else:
                if set_default:
                    p["default"] = False
                    p["is_default"] = 0
                updated.append(p)
        self.settings_model.save_printers(updated)

    def delete_printer(self, printer_id):
        """Hapus printer"""
        printers = self.settings_model.load_printers()
        printers = [p for p in printers if int(p.get("id") or 0) != int(printer_id)]
        self.settings_model.save_printers(printers)

    def set_default(self, printer_id):
        """Set printer sebagai default"""
        printers = self.settings_model.load_printers()
        for p in printers:
            is_def = int(p.get("id") or 0) == int(printer_id)
            p["default"] = bool(is_def)
            p["is_default"] = 1 if is_def else 0
        self.settings_model.save_printers(printers)

    def get_default(self):
        """Ambil printer default"""
        printers = self.settings_model.load_printers()
        for p in printers:
            if p.get("default") or int(p.get("is_default") or 0) == 1:
                return self._to_legacy_schema(p)
        return None

    def test_connection(self, koneksi, address):
        """
        Test koneksi printer dan kirim cetak dummy.
        koneksi: usb | lan
        address: "VID:PID" (untuk USB) atau "IP:PORT" (untuk LAN)
        Return: (status: bool, error_code: str)
        """
        return self.io_service.test_connection(koneksi, address)

    def _to_legacy_schema(self, rec):
        return {
            "id": rec.get("id"),
            "nama": rec.get("nama") or rec.get("name"),
            "koneksi": rec.get("koneksi"),
            "address": rec.get("address"),
            "lebar_kertas": rec.get("lebar_kertas") or rec.get("paper_size"),
            "margin": rec.get("margin", 0),
            "driver": rec.get("driver", "escpos"),
            "auto_cut": rec.get("auto_cut", 1),
            "copies": rec.get("copies", 1),
            "is_default": int(rec.get("is_default") or (1 if rec.get("default") else 0)),
        }

    def _from_legacy_input(self, data):
        printers = self.settings_model.load_printers()
        max_id = 0
        for p in printers:
            try:
                max_id = max(max_id, int(p.get("id") or 0))
            except (TypeError, ValueError, KeyError, AttributeError, RuntimeError, OSError, LookupError, ArithmeticError, ImportError):
                pass
        new_id = max_id + 1
        name = data.get("nama") or data.get("name") or ""
        paper_size = data.get("lebar_kertas") or data.get("paper_size") or ""
        is_default = bool(int(data.get("is_default") or data.get("default") or 0))
        return {
            "id": new_id,
            "name": name,
            "paper_size": paper_size,
            "default": is_default,
            "nama": name,
            "lebar_kertas": paper_size,
            "is_default": 1 if is_default else 0,
            "koneksi": data.get("koneksi"),
            "address": data.get("address"),
            "margin": data.get("margin", 0),
            "driver": data.get("driver", "escpos"),
            "auto_cut": data.get("auto_cut", 1),
            "copies": data.get("copies", 1),
        }

    def _merge_update(self, rec, data):
        name = data.get("nama") or data.get("name") or rec.get("name") or rec.get("nama") or ""
        paper_size = data.get("lebar_kertas") or data.get("paper_size") or rec.get("paper_size") or rec.get("lebar_kertas") or ""
        is_default = bool(int(data.get("is_default") or data.get("default") or rec.get("is_default") or rec.get("default") or 0))
        rec.update({
            "name": name,
            "paper_size": paper_size,
            "default": is_default,
            "nama": name,
            "lebar_kertas": paper_size,
            "is_default": 1 if is_default else 0,
            "koneksi": data.get("koneksi", rec.get("koneksi")),
            "address": data.get("address", rec.get("address")),
            "margin": data.get("margin", rec.get("margin", 0)),
            "driver": data.get("driver", rec.get("driver", "escpos")),
            "auto_cut": data.get("auto_cut", rec.get("auto_cut", 1)),
            "copies": data.get("copies", rec.get("copies", 1)),
        })
        return rec
