"""product_key routinely contains slashes (a crawl:host:https://... URL, or
a shopify:...:gid://shopify/Product/123 key) -- these routes must accept
that as one path parameter, not split on it, and the /pairings route must
still be matched ahead of the plainer product route.

The key is URL-encoded before use, matching how a real caller must send it
(encodeURIComponent on the frontend) -- an unencoded "/" in a client.get()
f-string is a client-side ambiguity, not what these routes are tested for."""
from unittest.mock import patch
from urllib.parse import quote

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient

from app.api import catalog as catalog_api

SLASHY_KEY = "crawl:shop.example.com:https://shop.example.com/collections/all/products/x"
ENCODED_KEY = quote(SLASHY_KEY, safe="")


@pytest.fixture
def client():
    app = FastAPI()
    app.include_router(catalog_api.router)
    return TestClient(app)


def test_a_product_key_containing_slashes_is_matched_whole(client):
    with patch.object(catalog_api, "get_product", return_value={"name": "X"}):
        resp = client.get(f"/catalog/products/{ENCODED_KEY}", params={"tenant_id": "org_x"})

    assert resp.status_code == 200
    assert resp.json() == {"name": "X"}


def test_pairings_route_still_matches_ahead_of_the_plain_product_route(client):
    with patch.object(catalog_api, "pairings_for",
                      return_value={"similar": [], "complement": [], "upsell": []}) as pairings, \
         patch.object(catalog_api, "get_product") as get_product:
        resp = client.get(f"/catalog/products/{ENCODED_KEY}/pairings", params={"tenant_id": "org_x"})

    assert resp.status_code == 200
    assert resp.json() == {"similar": [], "complement": [], "upsell": []}
    # The full slashy key must reach pairings_for, not be truncated at the
    # first slash, and get_product (the plainer route) must never be hit.
    pairings.assert_called_once_with("org_x", SLASHY_KEY)
    get_product.assert_not_called()


def test_unknown_product_key_is_a_404_not_a_routing_miss(client):
    with patch.object(catalog_api, "get_product", return_value=None):
        resp = client.get(f"/catalog/products/{ENCODED_KEY}", params={"tenant_id": "org_x"})

    assert resp.status_code == 404
    assert resp.json()["detail"] == "Product not found"


def test_deleting_a_slashy_product_key_is_matched_whole(client):
    with patch.object(catalog_api, "delete_product", return_value=True) as delete:
        resp = client.delete(f"/catalog/products/{ENCODED_KEY}", params={"tenant_id": "org_x"})

    assert resp.status_code == 200
    assert resp.json() == {"product_key": SLASHY_KEY, "status": "deleted"}
    delete.assert_called_once_with("org_x", SLASHY_KEY)


def test_deleting_an_unknown_product_key_is_a_404(client):
    with patch.object(catalog_api, "delete_product", return_value=False):
        resp = client.delete(f"/catalog/products/{ENCODED_KEY}", params={"tenant_id": "org_x"})

    assert resp.status_code == 404
    assert resp.json()["detail"] == "Product not found"
