from __future__ import annotations

import json

import httpx
import pytest
import respx

from rightnow import RightNow, AsyncRightNow
from rightnow._exceptions import AuthenticationError, BadRequestError, RightNowError


BASE = "https://arabic-api-backend.rightnowai.co"


# ── Init tests ──────────────────────────────────────────────────────────────


def test_requires_api_key():
    import os
    os.environ.pop("RIGHTNOW_API_KEY", None)
    with pytest.raises(RightNowError, match="API key is required"):
        RightNow()


def test_custom_base_url():
    client = RightNow(api_key="test", base_url="http://localhost:8080")
    assert client.base_url == "http://localhost:8080"
    client.close()


# ── Sync chat ───────────────────────────────────────────────────────────────


@respx.mock
def test_chat_completion():
    mock_response = {
        "id": "chatcmpl-123",
        "object": "chat.completion",
        "created": 1700000000,
        "model": "falcon-h1-arabic-7b",
        "choices": [
            {
                "index": 0,
                "message": {"role": "assistant", "content": "أهلاً!"},
                "finish_reason": "stop",
            }
        ],
        "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15},
    }

    respx.post(f"{BASE}/v1/chat/completions").mock(
        return_value=httpx.Response(200, json=mock_response)
    )

    client = RightNow(api_key="test-key", base_url=BASE)
    result = client.chat.completions.create(
        model="falcon-h1-arabic-7b",
        messages=[{"role": "user", "content": "مرحبا"}],
    )

    assert result.choices[0].message.content == "أهلاً!"
    assert result.usage.total_tokens == 15
    client.close()


@respx.mock
def test_chat_401():
    respx.post(f"{BASE}/v1/chat/completions").mock(
        return_value=httpx.Response(
            401, json={"error": {"message": "Invalid API key"}}
        )
    )

    client = RightNow(api_key="bad-key", base_url=BASE)
    with pytest.raises(AuthenticationError, match="Invalid API key"):
        client.chat.completions.create(
            model="falcon-h1-arabic-7b",
            messages=[{"role": "user", "content": "test"}],
        )
    client.close()


# ── Sync models ─────────────────────────────────────────────────────────────


@respx.mock
def test_list_models():
    mock_response = {
        "object": "list",
        "data": [
            {"id": "falcon-h1-arabic-7b", "object": "model", "created": 1700000000, "owned_by": "rightnow"},
        ],
    }

    respx.get(f"{BASE}/v1/models").mock(
        return_value=httpx.Response(200, json=mock_response)
    )

    client = RightNow(api_key="test-key", base_url=BASE)
    result = client.models.list()
    assert len(result.data) == 1
    assert result.data[0].id == "falcon-h1-arabic-7b"
    client.close()


# ── Sync embeddings ─────────────────────────────────────────────────────────


@respx.mock
def test_embeddings():
    mock_response = {
        "object": "list",
        "data": [{"object": "embedding", "index": 0, "embedding": [0.1, 0.2, 0.3]}],
        "model": "bge-m3-arabic",
        "usage": {"prompt_tokens": 5, "completion_tokens": 0, "total_tokens": 5},
    }

    respx.post(f"{BASE}/v1/embeddings").mock(
        return_value=httpx.Response(200, json=mock_response)
    )

    client = RightNow(api_key="test-key", base_url=BASE)
    result = client.embeddings.create(model="bge-m3-arabic", input="مرحبا")
    assert len(result.data) == 1
    assert result.data[0].embedding == [0.1, 0.2, 0.3]
    client.close()


# ── Sync dialects ───────────────────────────────────────────────────────────


@respx.mock
def test_dialect_detect():
    mock_response = {
        "primary_dialect": "egyptian",
        "confidence": 0.95,
        "scores": [
            {"dialect": "egyptian", "confidence": 0.95},
            {"dialect": "msa", "confidence": 0.03},
        ],
    }

    respx.post(f"{BASE}/v1/dialects/detect").mock(
        return_value=httpx.Response(200, json=mock_response)
    )

    client = RightNow(api_key="test-key", base_url=BASE)
    result = client.dialects.detect(text="ازيك يا حبيبي")
    assert result.primary_dialect == "egyptian"
    assert result.confidence == 0.95
    client.close()


# ── Async chat ──────────────────────────────────────────────────────────────


@respx.mock
@pytest.mark.asyncio
async def test_async_chat_completion():
    mock_response = {
        "id": "chatcmpl-456",
        "object": "chat.completion",
        "created": 1700000000,
        "model": "falcon-h1-arabic-7b",
        "choices": [
            {
                "index": 0,
                "message": {"role": "assistant", "content": "مرحباً بك!"},
                "finish_reason": "stop",
            }
        ],
        "usage": {"prompt_tokens": 10, "completion_tokens": 5, "total_tokens": 15},
    }

    respx.post(f"{BASE}/v1/chat/completions").mock(
        return_value=httpx.Response(200, json=mock_response)
    )

    async with AsyncRightNow(api_key="test-key", base_url=BASE) as client:
        result = await client.chat.completions.create(
            model="falcon-h1-arabic-7b",
            messages=[{"role": "user", "content": "مرحبا"}],
        )
        assert result.choices[0].message.content == "مرحباً بك!"
