"""Label Templates & Thermal Printing backend regression suite.

Covers:
- /api/labels/meta (preset sizes, fields, printers, barcode types)
- /api/labels/templates CRUD + duplicate
- /api/labels/print-log POST + GET
- Permission check on DELETE
"""
import os
import pytest

BASE_URL = os.environ.get(
    "REACT_APP_BACKEND_URL", "https://offline-billing-pro-2.preview.emergentagent.com"
).rstrip("/")


# ---------- Meta ----------
class TestLabelMeta:
    def test_meta_endpoint(self, admin_session):
        r = admin_session.get(f"{BASE_URL}/api/labels/meta", timeout=30)
        assert r.status_code == 200
        data = r.json()
        # Required keys
        assert set(["preset_sizes", "fields", "printers", "barcode_types", "kinds"]).issubset(data.keys())
        # Counts per spec
        assert len(data["preset_sizes"]) == 11, f"Expected 11 preset sizes, got {len(data['preset_sizes'])}"
        assert len(data["fields"]) == 25, f"Expected 25 fields, got {len(data['fields'])}"
        assert len(data["printers"]) == 10, f"Expected 10 printers, got {len(data['printers'])}"
        assert len(data["barcode_types"]) == 7, f"Expected 7 barcode types, got {len(data['barcode_types'])}"
        # Validate specific barcode types
        for t in ["CODE128", "CODE39", "EAN13", "EAN8", "UPC", "ITF", "GS1"]:
            assert t in data["barcode_types"]
        # Preset includes 4x3 with 101.6/76.2
        p4x3 = next((p for p in data["preset_sizes"] if p["key"] == "4x3"), None)
        assert p4x3 is not None
        assert p4x3["width_mm"] == 101.6
        assert p4x3["height_mm"] == 76.2


# ---------- CRUD ----------
@pytest.fixture(scope="module")
def created_template_id(admin_session, default_company_id):
    """Create one template for downstream tests; cleanup at end."""
    payload = {
        "name": "TEST_LabelTemplate_Module",
        "kind": "product",
        "size": {
            "preset": "2x1",
            "width_mm": 50.8,
            "height_mm": 25.4,
            "margin_mm": 1.0,
            "gap_mm": 2.0,
            "dpi": 203,
        },
        "elements": [
            {"id": "e1", "type": "text", "x": 2, "y": 2, "w": 30, "h": 5, "text": "Hello"},
            {
                "id": "e2",
                "type": "barcode",
                "x": 2,
                "y": 10,
                "w": 40,
                "h": 8,
                "barcode_type": "CODE128",
                "barcode_value": "1234567890",
            },
            {"id": "e3", "type": "qr", "x": 38, "y": 1, "w": 10, "h": 10, "qr_value": "QR-DEMO"},
        ],
        "is_default": False,
    }
    r = admin_session.post(
        f"{BASE_URL}/api/labels/templates?company_id={default_company_id}", json=payload, timeout=30
    )
    assert r.status_code == 200, r.text
    tid = r.json()["id"]
    yield tid
    # Cleanup
    admin_session.delete(f"{BASE_URL}/api/labels/templates/{tid}", timeout=30)


class TestLabelTemplateCRUD:
    def test_create_returns_saved(self, admin_session, default_company_id):
        payload = {
            "name": "TEST_CreatedTemplate",
            "kind": "retail",
            "size": {"preset": "2x1", "width_mm": 50.8, "height_mm": 25.4,
                     "margin_mm": 1.0, "gap_mm": 2.0, "dpi": 203},
            "elements": [
                {"id": "x", "type": "text", "x": 1, "y": 1, "w": 20, "h": 5, "text": "Hi"},
            ],
        }
        r = admin_session.post(
            f"{BASE_URL}/api/labels/templates?company_id={default_company_id}", json=payload, timeout=30
        )
        assert r.status_code == 200, r.text
        d = r.json()
        assert d["name"] == "TEST_CreatedTemplate"
        assert d["kind"] == "retail"
        assert len(d["elements"]) == 1
        assert "id" in d
        assert "_id" not in d
        # cleanup
        admin_session.delete(f"{BASE_URL}/api/labels/templates/{d['id']}", timeout=30)

    def test_list_templates_includes_created(self, admin_session, default_company_id, created_template_id):
        r = admin_session.get(
            f"{BASE_URL}/api/labels/templates?company_id={default_company_id}", timeout=30
        )
        assert r.status_code == 200
        items = r.json()
        assert isinstance(items, list)
        ids = [it["id"] for it in items]
        assert created_template_id in ids

    def test_get_template_returns_full(self, admin_session, created_template_id):
        r = admin_session.get(f"{BASE_URL}/api/labels/templates/{created_template_id}", timeout=30)
        assert r.status_code == 200
        d = r.json()
        assert d["id"] == created_template_id
        assert len(d["elements"]) == 3
        # Verify element types are intact
        types = sorted(e["type"] for e in d["elements"])
        assert types == ["barcode", "qr", "text"]
        bc = next(e for e in d["elements"] if e["type"] == "barcode")
        assert bc["barcode_type"] == "CODE128"
        assert bc["barcode_value"] == "1234567890"

    def test_update_template_mutates(self, admin_session, created_template_id):
        update_payload = {
            "name": "TEST_LabelTemplate_Module_UPDATED",
            "kind": "product",
            "size": {
                "preset": "4x3",
                "width_mm": 101.6,
                "height_mm": 76.2,
                "margin_mm": 2.0,
                "gap_mm": 3.0,
                "dpi": 300,
            },
            "elements": [
                {"id": "only", "type": "text", "x": 5, "y": 5, "w": 50, "h": 10, "text": "Updated"},
            ],
            "is_default": False,
        }
        r = admin_session.put(
            f"{BASE_URL}/api/labels/templates/{created_template_id}", json=update_payload, timeout=30
        )
        assert r.status_code == 200, r.text
        d = r.json()
        assert d["name"].endswith("UPDATED")
        assert d["size"]["preset"] == "4x3"
        assert d["size"]["width_mm"] == 101.6
        assert len(d["elements"]) == 1
        # Verify persistence via GET
        rg = admin_session.get(f"{BASE_URL}/api/labels/templates/{created_template_id}", timeout=30)
        assert rg.status_code == 200
        dg = rg.json()
        assert dg["size"]["preset"] == "4x3"
        assert len(dg["elements"]) == 1
        assert dg["elements"][0]["text"] == "Updated"

    def test_duplicate_creates_copy(self, admin_session, created_template_id):
        r = admin_session.post(
            f"{BASE_URL}/api/labels/templates/{created_template_id}/duplicate", timeout=30
        )
        assert r.status_code == 200, r.text
        d = r.json()
        assert "(copy)" in d["name"]
        assert d["id"] != created_template_id
        # Confirm duplicate has the same number of elements
        # cleanup duplicate
        admin_session.delete(f"{BASE_URL}/api/labels/templates/{d['id']}", timeout=30)

    def test_delete_then_404(self, admin_session, default_company_id):
        # Create a disposable template
        payload = {
            "name": "TEST_DeleteMe",
            "kind": "product",
            "size": {"preset": "1x1", "width_mm": 25.4, "height_mm": 25.4,
                     "margin_mm": 1, "gap_mm": 2, "dpi": 203},
            "elements": [],
        }
        rc = admin_session.post(
            f"{BASE_URL}/api/labels/templates?company_id={default_company_id}", json=payload, timeout=30
        )
        assert rc.status_code == 200
        tid = rc.json()["id"]
        rd = admin_session.delete(f"{BASE_URL}/api/labels/templates/{tid}", timeout=30)
        assert rd.status_code == 200
        # Now GET should 404
        rg = admin_session.get(f"{BASE_URL}/api/labels/templates/{tid}", timeout=30)
        assert rg.status_code == 404


# ---------- Print Log ----------
class TestPrintLog:
    def test_create_and_list_print_log(self, admin_session, default_company_id, created_template_id):
        payload = {
            "template_id": created_template_id,
            "template_name": "TEST_LabelTemplate_Module",
            "item_count": 2,
            "label_count": 4,
            "copies": 2,
            "output": "print",
        }
        r = admin_session.post(
            f"{BASE_URL}/api/labels/print-log?company_id={default_company_id}", json=payload, timeout=30
        )
        assert r.status_code == 200, r.text
        d = r.json()
        assert d.get("ok") is True
        assert "id" in d
        # List
        rl = admin_session.get(
            f"{BASE_URL}/api/labels/print-log?company_id={default_company_id}", timeout=30
        )
        assert rl.status_code == 200
        items = rl.json()
        assert isinstance(items, list)
        assert any(it.get("template_id") == created_template_id and it.get("label_count") == 4 for it in items)
