from __future__ import annotations

import os
import sys
from pathlib import Path
import asyncio
from typing import Any, Dict, List

import pytest
from fastapi import HTTPException

PROJECT_ROOT = Path(__file__).resolve().parents[1]
if str(PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(PROJECT_ROOT))

os.environ.setdefault("APPWRITE_ENDPOINT", "http://localhost/v1")
os.environ.setdefault("APPWRITE_PROJECT_ID", "test-project")
os.environ.setdefault("APPWRITE_API_KEY", "test-key")
os.environ.setdefault("APPWRITE_DATABASE_ID", "test-db")
os.environ.setdefault("APPWRITE_COLLECTION_PRODUTOS_CATALOGO_ID", "test-produtos")
os.environ.setdefault("APPWRITE_COLLECTION_LABORATORIOS_ID", "test-labs")
os.environ.setdefault("APPWRITE_COLLECTION_CATEGORIAS_ID", "test-categories")
os.environ.setdefault("APPWRITE_COLLECTION_SUBCATEGORIAS_ID", "test-subcategories")

pytest.importorskip("appwrite")

from src.modules.produtos_catalogo.schemas import ProdutoCatalogoCreateRequest
from src.modules.produtos_catalogo.service import ProdutosCatalogoService


class _DummyDatabases:
    """Minimal stub for the Appwrite databases service used in unit tests."""

    def __init__(self, *, list_documents_response: Dict[str, Any] | None = None) -> None:
        self._list_documents_response = list_documents_response or {"documents": []}
        self.list_documents_calls: List[Dict[str, Any]] = []

    def list_documents(
        self,
        database_id: str,
        collection_id: str,
        *,
        queries: List[Any] | None = None,
    ) -> Dict[str, Any]:
        self.list_documents_calls.append(
            {
                "database_id": database_id,
                "collection_id": collection_id,
                "queries": queries or [],
            }
        )
        return self._list_documents_response


def _build_service(*, databases: _DummyDatabases | None = None) -> ProdutosCatalogoService:
    return ProdutosCatalogoService(
        databases=databases or _DummyDatabases(),
        database_id="test-db",
        collection_id="test-produtos",
        laboratorios_collection_id="test-labs",
        categorias_collection_id="test-categories",
        subcategorias_collection_id="test-subcategories",
    )


def test_map_document_for_list_uses_codigo_ean_when_codigo_barras_missing() -> None:
    service = _build_service()
    document = {
        "$id": "prod_1",
        "$createdAt": "2024-01-01T00:00:00Z",
        "$updatedAt": "2024-01-01T00:00:00Z",
        "codigo_ean": "7891234567890",
        "codigo_barras": "",  # stored empty in some documents
        "nome": "Produto Teste",
        "preco_consumidor": 10.5,
    }

    mapped = service._map_document_for_list(document)

    assert mapped["codigo_ean"] == "7891234567890"


def test_map_document_prefers_preco_base_field() -> None:
    service = _build_service()
    document = {
        "$id": "prod_2",
        "$createdAt": "2024-01-01T00:00:00Z",
        "$updatedAt": "2024-01-01T00:00:00Z",
        "codigo_ean": "7890000000000",
        "nome": "Produto com Preço Base",
        "preco_base": 45.9,
        "preco_consumidor": 10.0,
    }

    mapped = service._map_document(document)

    assert mapped.preco_consumidor == pytest.approx(45.9)


def test_create_request_accepts_reference_field_aliases() -> None:
    payload = ProdutoCatalogoCreateRequest(
        documentId="prod_3",
        data={
            "codigo_ean": "7891234523190",
            "nome": "Produto Exemplo",
            "preco_base": 100.0,
            "laboratorio": "lab_123",
            "categoria": "cat_456",
            "subcategoria": "sub_789",
        },
    )

    assert payload.data.laboratorioId == "lab_123"
    assert payload.data.categoriaId == "cat_456"
    assert payload.data.subcategoriaId == "sub_789"


def test_get_by_codigo_ean_returns_document() -> None:
    codigo_ean = "7898148305100"
    databases = _DummyDatabases(
        list_documents_response={
            "documents": [
                {
                    "$id": "prod_10",
                    "codigo_ean": codigo_ean,
                    "nome": "Produto Catálogo",
                    "$createdAt": "2024-01-01T00:00:00Z",
                    "$updatedAt": "2024-01-01T00:00:00Z",
                    "preco_base": 12.5,
                }
            ]
        }
    )
    service = _build_service(databases=databases)

    produto = asyncio.run(service.get_by_codigo_ean(codigo_ean))

    assert produto.id == "prod_10"
    assert produto.codigo_barras == codigo_ean
    assert produto.nome == "Produto Catálogo"


def test_get_by_codigo_ean_not_found() -> None:
    service = _build_service(databases=_DummyDatabases(list_documents_response={"documents": []}))

    with pytest.raises(HTTPException) as excinfo:
        asyncio.run(service.get_by_codigo_ean("7899999999999"))

    assert excinfo.value.status_code == 404


def test_get_by_codigo_ean_rejects_blank_value() -> None:
    service = _build_service()

    with pytest.raises(HTTPException) as excinfo:
        asyncio.run(service.get_by_codigo_ean("   "))

    assert excinfo.value.status_code == 400
