import base64
import os
from datetime import datetime, timezone
from typing import Generator

from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

os.environ.setdefault("WEB_SENTINEL_POSTGRES_URL", "sqlite:///./test_admin_payments.db")
os.environ.setdefault("WEB_SENTINEL_ADMIN_JWT_SECRET", "test-secret")

from admin.backend.app.database import get_session
from admin.backend.app.main import create_app
from admin.backend.app.models import Base
from admin.backend.app.models.admin_user import AdminUser
from admin.backend.app.models.license import License
from admin.backend.app.security import hash_password

engine = create_engine(os.environ["WEB_SENTINEL_POSTGRES_URL"], future=True)
TestingSession = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)

Base.metadata.create_all(bind=engine)


def override_session() -> Generator:
    db = TestingSession()
    try:
        yield db
    finally:
        db.close()


app = create_app()
app.dependency_overrides[get_session] = override_session
client = TestClient(app)


def setup_module() -> None:
    Base.metadata.create_all(bind=engine)
    with TestingSession() as session:
        session.query(AdminUser).delete()
        session.query(License).delete()
        session.add(
            AdminUser(
                email="sysop@web-sentinel.com",
                hashed_password=hash_password("secret"),
                role="super-admin",
            )
        )
        session.add_all(
            [
                License(
                    email="billing@example.com",
                    api_key="bill1",
                    tier="PRO",
                    status="active",
                    stripe_subscription_id="sub_1",
                    created_at=datetime(2024, 1, 1, tzinfo=timezone.utc),
                    updated_at=datetime(2024, 1, 1, tzinfo=timezone.utc),
                ),
                License(
                    email="billing@example.com",
                    api_key="bill2",
                    tier="PRO",
                    status="cancelled",
                    stripe_subscription_id="sub_2",
                    created_at=datetime(2024, 2, 1, tzinfo=timezone.utc),
                    updated_at=datetime(2024, 2, 1, tzinfo=timezone.utc),
                ),
            ]
        )
        session.commit()


def teardown_module() -> None:
    Base.metadata.drop_all(bind=engine)


def _login() -> str:
    response = client.post(
        "/api/v1/auth/login",
        data={"username": "sysop@web-sentinel.com", "password": "secret"},
        headers={"Content-Type": "application/x-www-form-urlencoded"},
    )
    assert response.status_code == 200
    return response.json()["access_token"]


def test_payment_summary():
    token = _login()
    resp = client.get("/api/v1/payments/summary", headers={"Authorization": f"Bearer {token}"})
    assert resp.status_code == 200
    assert resp.json()["active_subscriptions"] >= 1


def test_list_subscriptions():
    token = _login()
    resp = client.get("/api/v1/payments/subscriptions", headers={"Authorization": f"Bearer {token}"})
    assert resp.status_code == 200
    assert len(resp.json()) == 2


def test_export_transactions_csv():
    token = _login()
    resp = client.get(
        "/api/v1/payments/export",
        headers={"Authorization": f"Bearer {token}"},
        params={"status": "active", "start_date": "2024-01-01", "end_date": "2024-12-31", "format": "csv"},
    )
    assert resp.status_code == 200
    payload = resp.json()
    assert payload["format"] == "csv"
    assert "content" in payload
    assert "sub_1" in payload["content"]
    assert "sub_2" not in payload["content"]


def test_export_transactions_excel():
    token = _login()
    resp = client.get(
        "/api/v1/payments/export",
        headers={"Authorization": f"Bearer {token}"},
        params={"format": "excel"},
    )
    assert resp.status_code == 200
    payload = resp.json()
    assert payload["format"] == "excel"
    content = base64.b64decode(payload["content_base64"])
    assert content.startswith(b"PK")  # XLSX est un zip


def test_export_transactions_json():
    token = _login()
    resp = client.get(
        "/api/v1/payments/export",
        headers={"Authorization": f"Bearer {token}"},
        params={"format": "json"},
    )
    assert resp.status_code == 200
    payload = resp.json()
    assert payload["format"] == "json"
    assert payload["count"] == 2
    assert any(item["subscription_id"] == "sub_1" for item in payload["items"])
