"""
Smoke tests for the SupportHub multi-tenant Flask app.

These tests use Flask's built-in test client with CSRF disabled so we
can POST forms without extracting tokens.  The real database is used
(read-only queries), so the suite requires the PostgreSQL instance to
be reachable with the credentials in .env / environment.
"""

from __future__ import annotations

import pytest
from supporthub.app.main import create_app


# ---------------------------------------------------------------------------
# Fixtures
# ---------------------------------------------------------------------------


@pytest.fixture(scope="module")
def app():
    """Create the Flask application configured for testing."""
    flask_app = create_app()
    flask_app.config.update(
        TESTING=True,
        WTF_CSRF_ENABLED=False,
        # Disable the stat reloader / debugger behaviour that isn't needed
        # in tests.
        DEBUG=False,
    )
    return flask_app


@pytest.fixture()
def client(app):
    """Unauthenticated test client (fresh per test, no session leakage)."""
    return app.test_client()


@pytest.fixture(scope="module")
def auth_client(app):
    """Test client that is already logged in as the admin user."""
    with app.test_client() as c:
        rv = c.post(
            "/login",
            data={"email": "admin@local.test", "password": "Admin123!ChangeMe"},
            follow_redirects=False,
        )
        # A successful login redirects away from /login
        assert rv.status_code in (301, 302), (
            f"Login fixture failed (status {rv.status_code}): "
            f"{rv.data[:200]}"
        )
        yield c


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


class TestLoginPage:
    def test_login_page_loads(self, client):
        """GET /login should return HTTP 200."""
        rv = client.get("/login")
        assert rv.status_code == 200
        assert b"login" in rv.data.lower() or b"email" in rv.data.lower()

    def test_login_success(self, client):
        """POST /login with correct credentials should redirect (302) to /inbox."""
        rv = client.post(
            "/login",
            data={"email": "admin@local.test", "password": "Admin123!ChangeMe"},
            follow_redirects=False,
        )
        assert rv.status_code in (301, 302)
        location = rv.headers.get("Location", "")
        assert "inbox" in location or location.endswith("/")

    def test_login_success_follow(self, client):
        """POST /login with correct credentials, following the redirect, lands on 200."""
        rv = client.post(
            "/login",
            data={"email": "admin@local.test", "password": "Admin123!ChangeMe"},
            follow_redirects=True,
        )
        assert rv.status_code == 200

    def test_login_wrong_password(self, client):
        """POST /login with bad password should stay on /login (200) with an error."""
        rv = client.post(
            "/login",
            data={"email": "admin@local.test", "password": "wrongpassword"},
            follow_redirects=False,
        )
        assert rv.status_code == 200
        assert b"invalid" in rv.data.lower() or b"error" in rv.data.lower()


class TestAuthRequired:
    def test_inbox_requires_auth(self, client):
        """GET /inbox without login should redirect to /login."""
        rv = client.get("/inbox", follow_redirects=False)
        assert rv.status_code in (301, 302)
        location = rv.headers.get("Location", "")
        assert "login" in location

    def test_ticket_detail_requires_auth(self, client):
        """GET /ticket/1 without login should redirect to /login."""
        rv = client.get("/ticket/1", follow_redirects=False)
        assert rv.status_code in (301, 302)
        location = rv.headers.get("Location", "")
        assert "login" in location


class TestAuthenticatedViews:
    def test_inbox_loads_after_login(self, auth_client):
        """GET /inbox after login should return 200 and contain ticket rows."""
        rv = auth_client.get("/inbox")
        assert rv.status_code == 200
        assert b"data-ticket-id" in rv.data

    def test_ticket_detail_loads(self, auth_client):
        """GET /ticket/1 after login should return 200 with reply UI present."""
        rv = auth_client.get("/ticket/1")
        assert rv.status_code == 200
        # The reply bar is always rendered in the ticket template
        assert b"reply" in rv.data.lower()
