"""Tests for team branding endpoints (logo upload + company display name)."""

import uuid

import pytest
from httpx import AsyncClient
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select

from app.core.security import get_password_hash
from app.models.account import Account
from app.models.team import Team
from app.models.user import User


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

async def _create_team_with_admin(
    test_db: AsyncSession,
    client: AsyncClient,
    *,
    team_name: str = "Branding Test Team",
) -> tuple[dict, str, Team]:
    """Create a team + team admin user. Returns (auth_headers, team_id_str, team)."""
    account = Account(name=team_name, display_code=uuid.uuid4().hex[:8].upper())
    test_db.add(account)
    team = Team(name=team_name)
    test_db.add(team)
    await test_db.flush()

    email = f"admin_{uuid.uuid4().hex[:8]}@test.com"
    user = User(
        email=email,
        password_hash=get_password_hash("Password123!"),
        name="Team Admin",
        is_active=True,
        team_id=team.id,
        is_team_admin=True,
        role="engineer",
        account_id=account.id,
        account_role="engineer",
    )
    test_db.add(user)
    await test_db.commit()

    resp = await client.post(
        "/api/v1/auth/login/json",
        json={"email": email, "password": "Password123!"},
    )
    assert resp.status_code == 200
    token = resp.json()["access_token"]
    headers = {"Authorization": f"Bearer {token}"}
    return headers, str(team.id), team


async def _create_team_member(
    test_db: AsyncSession,
    client: AsyncClient,
    team: Team,
    *,
    is_team_admin: bool = False,
) -> dict:
    """Create a regular team member. Returns auth_headers."""
    # Look up the account associated with this team via an existing member
    from sqlalchemy import select as _select
    from app.models.user import User as _User
    result = await test_db.execute(
        _select(_User).where(_User.team_id == team.id).limit(1)
    )
    team_member = result.scalar_one_or_none()
    member_account_id = team_member.account_id if team_member else None

    email = f"member_{uuid.uuid4().hex[:8]}@test.com"
    user = User(
        email=email,
        password_hash=get_password_hash("Password123!"),
        name="Team Member",
        is_active=True,
        team_id=team.id,
        is_team_admin=is_team_admin,
        role="engineer",
        account_id=member_account_id,
        account_role="engineer",
    )
    test_db.add(user)
    await test_db.commit()

    resp = await client.post(
        "/api/v1/auth/login/json",
        json={"email": email, "password": "Password123!"},
    )
    assert resp.status_code == 200
    token = resp.json()["access_token"]
    return {"Authorization": f"Bearer {token}"}


# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------

@pytest.mark.asyncio
async def test_get_branding_defaults(client: AsyncClient, test_db: AsyncSession):
    """GET branding with no logo returns defaults (has_logo=False)."""
    headers, team_id, _ = await _create_team_with_admin(test_db, client)

    resp = await client.get(f"/api/v1/teams/{team_id}/branding", headers=headers)
    assert resp.status_code == 200
    data = resp.json()
    assert data["has_logo"] is False
    assert data["company_display_name"] is None
    assert data["logo_content_type"] is None


@pytest.mark.asyncio
async def test_upload_logo_with_company_name(client: AsyncClient, test_db: AsyncSession):
    """PATCH with valid PNG logo + company name succeeds."""
    headers, team_id, _ = await _create_team_with_admin(test_db, client)

    # 1x1 transparent PNG (67 bytes)
    png_bytes = (
        b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01"
        b"\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89"
        b"\x00\x00\x00\nIDATx\x9cc\x00\x01\x00\x00\x05\x00\x01"
        b"\r\n\xb4\x00\x00\x00\x00IEND\xaeB`\x82"
    )

    resp = await client.patch(
        f"/api/v1/teams/{team_id}/branding",
        headers=headers,
        files={"logo": ("logo.png", png_bytes, "image/png")},
        data={"company_display_name": "Acme MSP"},
    )
    assert resp.status_code == 200, resp.text
    data = resp.json()
    assert data["has_logo"] is True
    assert data["logo_content_type"] == "image/png"
    assert data["company_display_name"] == "Acme MSP"


@pytest.mark.asyncio
async def test_upload_oversized_logo(client: AsyncClient, test_db: AsyncSession):
    """PATCH with >2MB file returns 400."""
    headers, team_id, _ = await _create_team_with_admin(test_db, client)

    big_bytes = b"\x00" * (2 * 1024 * 1024 + 1)  # 2MB + 1 byte

    resp = await client.patch(
        f"/api/v1/teams/{team_id}/branding",
        headers=headers,
        files={"logo": ("big.png", big_bytes, "image/png")},
    )
    assert resp.status_code == 400
    assert "maximum size" in resp.json()["detail"].lower()


@pytest.mark.asyncio
async def test_upload_invalid_content_type(client: AsyncClient, test_db: AsyncSession):
    """PATCH with application/pdf content type returns 400."""
    headers, team_id, _ = await _create_team_with_admin(test_db, client)

    resp = await client.patch(
        f"/api/v1/teams/{team_id}/branding",
        headers=headers,
        files={"logo": ("doc.pdf", b"%PDF-fake", "application/pdf")},
    )
    assert resp.status_code == 400
    assert "content type" in resp.json()["detail"].lower()


@pytest.mark.asyncio
async def test_delete_logo(client: AsyncClient, test_db: AsyncSession):
    """DELETE logo clears logo_data while keeping company_display_name."""
    headers, team_id, _ = await _create_team_with_admin(test_db, client)

    # Upload a logo + name first
    png_bytes = b"\x89PNG\r\n\x1a\n" + b"\x00" * 50
    await client.patch(
        f"/api/v1/teams/{team_id}/branding",
        headers=headers,
        files={"logo": ("logo.png", png_bytes, "image/png")},
        data={"company_display_name": "Keep This Name"},
    )

    # Delete logo
    resp = await client.delete(
        f"/api/v1/teams/{team_id}/branding/logo",
        headers=headers,
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["has_logo"] is False
    assert data["logo_content_type"] is None
    assert data["company_display_name"] == "Keep This Name"


@pytest.mark.asyncio
async def test_non_admin_cannot_update(client: AsyncClient, test_db: AsyncSession):
    """Regular team member (non-admin) cannot PATCH branding — returns 403."""
    admin_headers, team_id, team = await _create_team_with_admin(test_db, client)
    member_headers = await _create_team_member(test_db, client, team)

    resp = await client.patch(
        f"/api/v1/teams/{team_id}/branding",
        headers=member_headers,
        data={"company_display_name": "Should Fail"},
    )
    assert resp.status_code == 403


@pytest.mark.asyncio
async def test_non_admin_cannot_delete_logo(client: AsyncClient, test_db: AsyncSession):
    """Regular team member cannot DELETE logo — returns 403."""
    admin_headers, team_id, team = await _create_team_with_admin(test_db, client)
    member_headers = await _create_team_member(test_db, client, team)

    resp = await client.delete(
        f"/api/v1/teams/{team_id}/branding/logo",
        headers=member_headers,
    )
    assert resp.status_code == 403


@pytest.mark.asyncio
async def test_non_member_cannot_read(client: AsyncClient, test_db: AsyncSession):
    """User from a different team cannot GET branding — returns 403."""
    _, team_id, _ = await _create_team_with_admin(test_db, client, team_name="Team A")
    other_headers, _, _ = await _create_team_with_admin(test_db, client, team_name="Team B")

    resp = await client.get(
        f"/api/v1/teams/{team_id}/branding",
        headers=other_headers,
    )
    assert resp.status_code == 403


@pytest.mark.asyncio
async def test_member_can_read_branding(client: AsyncClient, test_db: AsyncSession):
    """Regular team member CAN read branding."""
    admin_headers, team_id, team = await _create_team_with_admin(test_db, client)
    member_headers = await _create_team_member(test_db, client, team)

    resp = await client.get(
        f"/api/v1/teams/{team_id}/branding",
        headers=member_headers,
    )
    assert resp.status_code == 200
    assert resp.json()["has_logo"] is False


@pytest.mark.asyncio
async def test_update_display_name_only(client: AsyncClient, test_db: AsyncSession):
    """PATCH with only company_display_name (no logo) succeeds."""
    headers, team_id, _ = await _create_team_with_admin(test_db, client)

    resp = await client.patch(
        f"/api/v1/teams/{team_id}/branding",
        headers=headers,
        data={"company_display_name": "Just A Name"},
    )
    assert resp.status_code == 200
    data = resp.json()
    assert data["company_display_name"] == "Just A Name"
    assert data["has_logo"] is False
