"""Tests for the backend monetisation services."""

import json
import os
import tempfile
import time

import pytest

from web_sentinel.backend import (
    AuthenticationService,
    SubscriptionBackend,
    SubscriptionRecord,
    SubscriptionRepository,
)
from web_sentinel.database.mysql_manager import MySQLManager


@pytest.fixture()
def repo(tmp_path):
    manager = MySQLManager({"driver": "sqlite", "database": tmp_path / "subscriptions.db"})
    repository = SubscriptionRepository(manager)
    with manager.get_connection() as conn:
        cursor = conn.cursor()
        cursor.execute(
            "INSERT OR IGNORE INTO users (id, email, subscription_tier) VALUES (?, ?, ?)",
            (123, "user@example.com", "FREE"),
        )
        cursor.execute(
            "INSERT OR IGNORE INTO users (id, email, subscription_tier) VALUES (?, ?, ?)",
            (456, "client@site.com", "FREE"),
        )
        cursor.execute(
            "INSERT OR IGNORE INTO users (id, email, subscription_tier) VALUES (?, ?, ?)",
            (789, "user@domain.tld", "FREE"),
        )
        cursor.execute(
            "INSERT OR IGNORE INTO users (id, email, subscription_tier) VALUES (?, ?, ?)",
            (999, "token@domain.tld", "PRO"),
        )
        conn.commit()
    return repository


def _build_signature(payload: str, secret: str, timestamp: int) -> str:
    import hmac
    import hashlib

    signature = hmac.new(
        secret.encode("utf-8"),
        f"{timestamp}.{payload}".encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()
    return f"t={timestamp},v1={signature}"


def test_repository_upsert_and_list(repo):
    record = SubscriptionRecord(
        user_id=123,
        email="user@example.com",
        tier="pro",
        stripe_customer_id="cus_123",
        stripe_subscription_id="sub_123",
        status="active",
        current_period_end=int(time.time()) + 3600,
    )
    repo.upsert_subscription(record)

    fetched = repo.get_subscription(123)
    assert fetched is not None
    assert fetched.tier.lower() == record.tier.lower()

    items = list(repo.list_active())
    assert len(items) == 1
    assert items[0].user_id == 123


def test_handle_checkout_session(repo):
    secret = "whsec_test"
    backend = SubscriptionBackend(repo, secret)

    payload = json.dumps(
        {
            "type": "checkout.session.completed",
            "data": {
                "object": {
                    "metadata": {"user_id": 456, "tier": "enterprise"},
                    "customer": "cus_456",
                    "subscription": "sub_456",
                    "subscription_period_end": int(time.time()) + 7200,
                    "customer_details": {"email": "client@site.com"},
                }
            },
        }
    )
    header = _build_signature(payload, secret, int(time.time()))

    assert backend.handle_webhook(payload, header)

    stored = repo.get_subscription(456)
    assert stored is not None
    assert stored.tier.lower() == "enterprise"
    assert stored.status == "active"


def test_handle_subscription_update(repo):
    secret = "whsec_test"
    backend = SubscriptionBackend(repo, secret)

    payload = json.dumps(
        {
            "type": "customer.subscription.updated",
            "data": {
                "object": {
                    "id": "sub_789",
                    "customer": "cus_789",
                    "status": "canceled",
                    "current_period_end": int(time.time()) + 3600,
                    "metadata": {
                        "user_id": 789,
                        "tier": "pro",
                        "email": "user@domain.tld",
                    },
                }
            },
        }
    )

    header = _build_signature(payload, secret, int(time.time()))

    assert backend.handle_webhook(payload, header)

    stored = repo.get_subscription(789)
    assert stored is not None
    assert stored.status == "canceled"
    assert stored.tier.lower() == "pro"


def test_authentication_service(repo):
    record = SubscriptionRecord(
        user_id=999,
        email="token@domain.tld",
        tier="pro",
        stripe_customer_id="cus_token",
        stripe_subscription_id="sub_token",
        status="active",
        current_period_end=int(time.time()) + 5000,
    )
    repo.upsert_subscription(record)

    auth = AuthenticationService(repo, secret="secret-seed")
    token = auth.issue_token(999)
    assert auth.validate_token(999, token)
    assert not auth.validate_token(999, "invalid")
