from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import StaticPool

from app.db.base import Base
from app.api.main import app
from app.api.routers import clients as clients_router

# Setup test DB
engine = create_engine(
    "sqlite://",
    connect_args={"check_same_thread": False},
    poolclass=StaticPool,
    future=True,
)
TestingSessionLocal = sessionmaker(bind=engine)
Base.metadata.create_all(bind=engine)


def override_get_db():
    db = TestingSessionLocal()
    try:
        yield db
    finally:
        db.close()

# Override dependency in the clients router
app.dependency_overrides[clients_router.get_db] = override_get_db
client = TestClient(app)


def test_create_and_get_client_api():
    payload = {"cedula": "12345678", "full_name": "API User", "email": "api@example.com", "phone": "123"}
    r = client.post("/clients/", json=payload)
    assert r.status_code == 200
    data = r.json()
    assert data["id"] is not None
    assert data["cedula"] == payload["cedula"]

    client_id = data["id"]
    r2 = client.get(f"/clients/{client_id}")
    assert r2.status_code == 200
    data2 = r2.json()
    assert data2["email"] == payload["email"]


def test_update_client_partial_api():
    payload = {"cedula": "87654321", "full_name": "Partial Update", "email": "partial@example.com", "phone": "555"}
    created = client.post("/clients/", json=payload)
    assert created.status_code == 200
    client_id = created.json()["id"]

    updated = client.put(f"/clients/{client_id}", json={"phone": "999"})
    assert updated.status_code == 200
    data = updated.json()
    assert data["phone"] == "999"
    assert data["full_name"] == "Partial Update"


def test_client_cedula_search_and_unique_validation():
    payload = {"cedula": "11111111", "full_name": "Cedula Search", "email": "search@example.com", "phone": "321"}
    created = client.post("/clients/", json=payload)
    assert created.status_code == 200

    lookup = client.get("/clients/search/11111111")
    assert lookup.status_code == 200
    assert lookup.json()["cedula"] == "11111111"

    duplicate = client.post("/clients/", json={"cedula": "11111111", "full_name": "Otro", "email": "otro@example.com"})
    assert duplicate.status_code == 409


def test_duplicate_email_is_allowed_when_cedula_is_different():
    first = client.post("/clients/", json={"cedula": "22222222", "full_name": "Primer", "email": "shared@example.com", "phone": "111"})
    assert first.status_code == 200

    second = client.post("/clients/", json={"cedula": "33333333", "full_name": "Segundo", "email": "shared@example.com", "phone": "222"})
    assert second.status_code == 200
    assert second.json()["cedula"] == "33333333"
