"""Backend tests for M3U upload feature.

Covers:
- POST /api/auth/login (admin)
- PUT /api/admin/settings persists shared_profiles[].m3u_content
- GET /api/admin/settings returns m3u_content
- GET /api/shared-profiles (auth required) returns m3u_content
- /api/shared-profiles requires auth (401 for guests)
"""
import os
import uuid
import pytest
import requests

from conftest import BASE_URL as BASE, ADMIN_USER, ADMIN_PASS

SAMPLE_M3U = (
    "#EXTM3U\n"
    "#EXTINF:-1 tvg-id=\"ch1\" tvg-name=\"Channel One\" group-title=\"News\",Channel One\n"
    "http://example.com/stream/ch1.ts\n"
    "#EXTINF:-1 tvg-id=\"ch2\" tvg-name=\"Channel Two\" group-title=\"Sports\",Channel Two\n"
    "http://example.com/stream/ch2.ts\n"
)


@pytest.fixture(scope="module")
def admin_token():
    r = requests.post(
        f"{BASE}/api/auth/login",
        json={"username": ADMIN_USER, "password": ADMIN_PASS},
        timeout=10,
    )
    assert r.status_code == 200, f"admin login failed: {r.status_code} {r.text}"
    data = r.json()
    assert "access_token" in data
    assert data.get("user", {}).get("role") == "admin"
    return data["access_token"]


@pytest.fixture(scope="module")
def auth_headers(admin_token):
    return {"Authorization": f"Bearer {admin_token}", "Content-Type": "application/json"}


# ----- Settings GET (baseline) -----
class TestAdminSettings:
    def test_get_settings_baseline(self, auth_headers):
        r = requests.get(f"{BASE}/api/admin/settings", headers=auth_headers, timeout=10)
        assert r.status_code == 200
        body = r.json()
        assert "shared_profiles" in body
        assert isinstance(body["shared_profiles"], list)

    def test_put_settings_persists_m3u_content(self, auth_headers):
        # Build a profile list with one m3u entry that has m3u_content
        test_profile_id = f"TEST_{uuid.uuid4()}"
        payload = {
            "shared_profiles": [
                {
                    "id": test_profile_id,
                    "name": "TEST_M3U_Upload",
                    "kind": "m3u",
                    "m3u_url": "",
                    "m3u_content": SAMPLE_M3U,
                }
            ]
        }
        r = requests.put(
            f"{BASE}/api/admin/settings",
            json=payload,
            headers=auth_headers,
            timeout=10,
        )
        assert r.status_code == 200, r.text
        body = r.json()
        profs = body.get("shared_profiles", [])
        match = [p for p in profs if p.get("id") == test_profile_id]
        assert len(match) == 1, f"profile not persisted, got: {profs}"
        assert match[0].get("kind") == "m3u"
        assert match[0].get("m3u_content") == SAMPLE_M3U

        # Re-GET to verify persistence in DB
        r2 = requests.get(f"{BASE}/api/admin/settings", headers=auth_headers, timeout=10)
        assert r2.status_code == 200
        profs2 = r2.json().get("shared_profiles", [])
        match2 = [p for p in profs2 if p.get("id") == test_profile_id]
        assert len(match2) == 1
        assert match2[0].get("m3u_content") == SAMPLE_M3U
        # cleanup is in next test that overwrites with empty list

    def test_shared_profiles_auth_required(self):
        # unauthenticated guest should get 401
        r = requests.get(f"{BASE}/api/shared-profiles", timeout=10)
        assert r.status_code in (401, 403)

    def test_shared_profiles_returns_m3u_content(self, auth_headers):
        r = requests.get(
            f"{BASE}/api/shared-profiles", headers=auth_headers, timeout=10
        )
        assert r.status_code == 200, r.text
        body = r.json()
        assert "profiles" in body
        m3u_profs = [p for p in body["profiles"] if p.get("kind") == "m3u"]
        assert len(m3u_profs) >= 1
        # at least one has m3u_content
        has_content = [p for p in m3u_profs if p.get("m3u_content")]
        assert len(has_content) >= 1
        assert SAMPLE_M3U in has_content[0]["m3u_content"]

    def test_xtream_profile_alongside_m3u(self, auth_headers):
        # Put a multi-profile list mixing xtream + m3u
        payload = {
            "shared_profiles": [
                {
                    "id": "TEST_xtream_1",
                    "name": "TEST_Xtream",
                    "kind": "xtream",
                    "server": "http://x.example.com",
                    "username": "u",
                    "password": "p",
                },
                {
                    "id": "TEST_m3u_2",
                    "name": "TEST_M3U_2",
                    "kind": "m3u",
                    "m3u_url": "https://example.com/p.m3u",
                    "m3u_content": SAMPLE_M3U,
                },
            ]
        }
        r = requests.put(
            f"{BASE}/api/admin/settings",
            json=payload,
            headers=auth_headers,
            timeout=10,
        )
        assert r.status_code == 200, r.text
        body = r.json()
        ids = {p.get("id") for p in body.get("shared_profiles", [])}
        assert "TEST_xtream_1" in ids
        assert "TEST_m3u_2" in ids
        m3u = next(p for p in body["shared_profiles"] if p["id"] == "TEST_m3u_2")
        assert m3u["m3u_content"] == SAMPLE_M3U
        assert m3u["m3u_url"] == "https://example.com/p.m3u"

    def test_cleanup_remove_test_profiles(self, auth_headers):
        # Read current, drop TEST_ prefixed profiles, write back
        r = requests.get(f"{BASE}/api/admin/settings", headers=auth_headers, timeout=10)
        assert r.status_code == 200
        profs = r.json().get("shared_profiles", [])
        kept = [
            p
            for p in profs
            if not (
                str(p.get("id", "")).startswith("TEST_")
                or str(p.get("name", "")).startswith("TEST_")
            )
        ]
        r2 = requests.put(
            f"{BASE}/api/admin/settings",
            json={"shared_profiles": kept},
            headers=auth_headers,
            timeout=10,
        )
        assert r2.status_code == 200
