"""Integration tests for printer and client CRUD endpoints."""
import json

import pytest
from fastapi.testclient import TestClient


# ---------------------------------------------------------------------------
# Task 1: RED state — routes do not exist yet, tests should fail
# ---------------------------------------------------------------------------


def test_create_printer_persisted(client: TestClient) -> None:
    """POST /printers with required fields returns 200; GET /printers contains printer name."""
    from imptune.db.models import Printer

    resp = client.post(
        "/printers",
        data={
            "name": "Test Printer",
            "ip_address": "192.168.1.100",
            "port_name": "IP_192_168_1_100",
        },
    )
    assert resp.status_code == 200

    # GET /printers page contains the printer name
    page = client.get("/printers")
    assert page.status_code == 200
    assert "Test Printer" in page.text

    # Verify DB persistence
    count = Printer.select().where(Printer.name == "Test Printer").count()
    assert count == 1


def test_create_printer_duplex(client: TestClient) -> None:
    """POST /printers with duplex_mode=LongEdge persists correctly."""
    from imptune.db.models import Printer

    resp = client.post(
        "/printers",
        data={
            "name": "Duplex Printer",
            "ip_address": "192.168.1.101",
            "port_name": "IP_192_168_1_101",
            "duplex_mode": "LongEdge",
        },
    )
    assert resp.status_code == 200

    printers = list(Printer.select().where(Printer.name == "Duplex Printer"))
    assert len(printers) == 1
    assert printers[0].duplex_mode == "LongEdge"


def test_create_printer_color_mode(client: TestClient) -> None:
    """POST /printers with color_mode not sent (unchecked) sets color_mode=False."""
    from imptune.db.models import Printer

    resp = client.post(
        "/printers",
        data={
            "name": "Mono Printer",
            "ip_address": "192.168.1.102",
            "port_name": "IP_192_168_1_102",
            # color_mode intentionally omitted (unchecked checkbox)
        },
    )
    assert resp.status_code == 200

    printers = list(Printer.select().where(Printer.name == "Mono Printer"))
    assert len(printers) == 1
    assert printers[0].color_mode is False


def test_create_printer_paper_size(client: TestClient) -> None:
    """POST /printers with paper_size=Letter persists correctly."""
    from imptune.db.models import Printer

    resp = client.post(
        "/printers",
        data={
            "name": "Letter Printer",
            "ip_address": "192.168.1.103",
            "port_name": "IP_192_168_1_103",
            "paper_size": "Letter",
        },
    )
    assert resp.status_code == 200

    printers = list(Printer.select().where(Printer.name == "Letter Printer"))
    assert len(printers) == 1
    assert printers[0].paper_size == "Letter"


def test_create_printer_collate(client: TestClient) -> None:
    """POST /printers with collate not sent (unchecked) sets collate=False."""
    from imptune.db.models import Printer

    resp = client.post(
        "/printers",
        data={
            "name": "No Collate Printer",
            "ip_address": "192.168.1.104",
            "port_name": "IP_192_168_1_104",
            # collate intentionally omitted (unchecked checkbox)
        },
    )
    assert resp.status_code == 200

    printers = list(Printer.select().where(Printer.name == "No Collate Printer"))
    assert len(printers) == 1
    assert printers[0].collate is False


def test_create_client(client: TestClient) -> None:
    """POST /clients with name=Contoso returns 200; GET /clients contains Contoso."""
    resp = client.post("/clients", data={"name": "Contoso"})
    assert resp.status_code == 200

    page = client.get("/clients")
    assert page.status_code == 200
    assert "Contoso" in page.text


def test_printer_grouped_by_client(client: TestClient) -> None:
    """Printer assigned to a client appears under that client group heading."""
    from imptune.db.models import Client, Printer

    # Create client
    resp = client.post("/clients", data={"name": "Contoso"})
    assert resp.status_code == 200

    contoso_list = list(Client.select().where(Client.name == "Contoso"))
    assert len(contoso_list) == 1
    contoso = contoso_list[0]

    # Create printer assigned to that client
    resp = client.post(
        "/printers",
        data={
            "name": "Contoso Printer",
            "ip_address": "10.0.0.1",
            "port_name": "IP_10_0_0_1",
            "client_id": str(contoso.id),
        },
    )
    assert resp.status_code == 200

    # GET /printers should show "Contoso" as a group header
    page = client.get("/printers")
    assert page.status_code == 200
    html = page.text
    assert "Contoso" in html
    # Client name should appear in a heading element
    assert "<h3" in html


def test_create_printer_missing_name(client: TestClient) -> None:
    """POST /printers with empty name returns 400."""
    resp = client.post(
        "/printers",
        data={
            "name": "",
            "ip_address": "192.168.1.100",
            "port_name": "IP_192_168_1_100",
        },
    )
    assert resp.status_code == 400


def test_create_printer_invalid_ip(client: TestClient) -> None:
    """POST /printers with empty ip_address returns 400."""
    resp = client.post(
        "/printers",
        data={
            "name": "Valid Name",
            "ip_address": "",
            "port_name": "SOME_PORT",
        },
    )
    assert resp.status_code == 400


def test_printer_detail_shows_driver(client: TestClient) -> None:
    """GET /printers/{id} returns 200 with all printer fields and driver name."""
    from imptune.db.models import Driver, Printer

    driver_obj = Driver.create(
        sha256="abc123",
        original_filename="hp_universal.zip",
        size_bytes=1000,
        driver_desc=json.dumps(["HP Universal"]),
    )
    printer = Printer.create(
        name="HP Office Printer",
        ip_address="10.0.1.1",
        port_name="IP_10_0_1_1",
        driver=driver_obj,
    )

    resp = client.get(f"/printers/{printer.id}")
    assert resp.status_code == 200
    html = resp.text
    assert "HP Office Printer" in html
    assert "10.0.1.1" in html
    assert "HP Universal" in html


def test_printer_detail_not_found(client: TestClient) -> None:
    """GET /printers/9999 returns 404."""
    resp = client.get("/printers/9999")
    assert resp.status_code == 404


def test_printer_detail_no_driver(client: TestClient) -> None:
    """GET /printers/{id} for printer with no driver returns 200 with 'No driver assigned'."""
    from imptune.db.models import Printer

    printer = Printer.create(
        name="Driverless Printer",
        ip_address="10.0.1.2",
        port_name="IP_10_0_1_2",
        driver=None,
    )

    resp = client.get(f"/printers/{printer.id}")
    assert resp.status_code == 200
    html = resp.text
    assert "No driver assigned" in html


def test_delete_printer(client: TestClient) -> None:
    """DELETE /printers/{id} removes the printer; GET /printers no longer shows it."""
    from imptune.db.models import Printer

    # Create a printer
    resp = client.post(
        "/printers",
        data={
            "name": "To Delete",
            "ip_address": "192.168.1.200",
            "port_name": "IP_192_168_1_200",
        },
    )
    assert resp.status_code == 200

    # Find its ID
    printers = list(Printer.select().where(Printer.name == "To Delete"))
    assert len(printers) == 1
    printer_id = printers[0].id

    # Delete it
    resp = client.delete(f"/printers/{printer_id}")
    assert resp.status_code == 200

    # Confirm it's gone from the DB
    count = Printer.select().where(Printer.id == printer_id).count()
    assert count == 0

    # GET /printers should no longer show it
    page = client.get("/printers")
    assert "To Delete" not in page.text
