"""E2E: Color strip source CRUD lifecycle.

Tests creating, listing, updating, cloning, and deleting color strip sources.
"""



class TestColorStripSourceLifecycle:
    """A user manages color strip sources for LED effects."""

    def test_static_and_gradient_crud(self, client):
        # 1. Create a static color strip source
        resp = client.post("/api/v1/color-strip-sources", json={
            "name": "Red Static",
            "source_type": "static",
            "color": [255, 0, 0],
            "led_count": 60,
            "tags": ["e2e", "static"],
        })
        assert resp.status_code == 201, f"Create static failed: {resp.text}"
        static = resp.json()
        static_id = static["id"]
        assert static["name"] == "Red Static"
        assert static["source_type"] == "static"
        assert static["color"] == [255, 0, 0]

        # 2. Create a gradient color strip source
        resp = client.post("/api/v1/color-strip-sources", json={
            "name": "Blue-Green Gradient",
            "source_type": "gradient",
            "stops": [
                {"position": 0.0, "color": [0, 0, 255]},
                {"position": 1.0, "color": [0, 255, 0]},
            ],
            "led_count": 60,
        })
        assert resp.status_code == 201, f"Create gradient failed: {resp.text}"
        gradient = resp.json()
        gradient_id = gradient["id"]
        assert gradient["name"] == "Blue-Green Gradient"
        assert gradient["source_type"] == "gradient"
        assert len(gradient["stops"]) == 2

        # 3. List all -- should have both
        resp = client.get("/api/v1/color-strip-sources")
        assert resp.status_code == 200
        data = resp.json()
        assert data["count"] == 2
        ids = {s["id"] for s in data["sources"]}
        assert static_id in ids
        assert gradient_id in ids

        # 4. Update the static source -- change color
        resp = client.put(
            f"/api/v1/color-strip-sources/{static_id}",
            json={"color": [0, 255, 0]},
        )
        assert resp.status_code == 200
        assert resp.json()["color"] == [0, 255, 0]

        # 5. Verify update via GET
        resp = client.get(f"/api/v1/color-strip-sources/{static_id}")
        assert resp.status_code == 200
        assert resp.json()["color"] == [0, 255, 0]

        # 6. Clone by creating another source with same data, different name
        resp = client.post("/api/v1/color-strip-sources", json={
            "name": "Cloned Static",
            "source_type": "static",
            "color": [0, 255, 0],
            "led_count": 60,
        })
        assert resp.status_code == 201
        clone_id = resp.json()["id"]
        assert clone_id != static_id
        assert resp.json()["name"] == "Cloned Static"

        # 7. Delete all three
        for sid in [static_id, gradient_id, clone_id]:
            resp = client.delete(f"/api/v1/color-strip-sources/{sid}")
            assert resp.status_code == 204

        # 8. List should be empty
        resp = client.get("/api/v1/color-strip-sources")
        assert resp.status_code == 200
        assert resp.json()["count"] == 0

    def test_update_name(self, client):
        """Renaming a color strip source persists."""
        resp = client.post("/api/v1/color-strip-sources", json={
            "name": "Original Name",
            "source_type": "static",
            "color": [100, 100, 100],
            "led_count": 10,
        })
        source_id = resp.json()["id"]

        resp = client.put(
            f"/api/v1/color-strip-sources/{source_id}",
            json={"name": "New Name"},
        )
        assert resp.status_code == 200
        assert resp.json()["name"] == "New Name"

    def test_get_nonexistent_returns_404(self, client):
        resp = client.get("/api/v1/color-strip-sources/nonexistent")
        assert resp.status_code == 404

    def test_delete_nonexistent_returns_404(self, client):
        resp = client.delete("/api/v1/color-strip-sources/nonexistent")
        assert resp.status_code == 404

    def test_duplicate_name_rejected(self, client):
        """Cannot create two sources with the same name."""
        payload = {
            "name": "Unique Name",
            "source_type": "static",
            "color": [0, 0, 0],
            "led_count": 10,
        }
        resp = client.post("/api/v1/color-strip-sources", json=payload)
        assert resp.status_code == 201

        resp = client.post("/api/v1/color-strip-sources", json=payload)
        assert resp.status_code == 400  # duplicate name

    def test_color_cycle_source(self, client):
        """Color cycle sources store and return their color list."""
        resp = client.post("/api/v1/color-strip-sources", json={
            "name": "Rainbow Cycle",
            "source_type": "color_cycle",
            "colors": [[255, 0, 0], [0, 255, 0], [0, 0, 255]],
            "led_count": 30,
        })
        assert resp.status_code == 201
        data = resp.json()
        assert data["source_type"] == "color_cycle"
        assert data["colors"] == [[255, 0, 0], [0, 255, 0], [0, 0, 255]]

    def test_effect_source(self, client):
        """Effect sources store their effect parameters."""
        resp = client.post("/api/v1/color-strip-sources", json={
            "name": "Fire Effect",
            "source_type": "effect",
            "effect_type": "fire",
            "palette": "fire",
            "intensity": 1.5,
            "led_count": 60,
        })
        assert resp.status_code == 201
        data = resp.json()
        assert data["source_type"] == "effect"
        assert data["effect_type"] == "fire"
