"""Tests for the enhanced /search/aliases/ endpoint (search-driven library)."""
import pytest
from django.test import Client
from django.urls import reverse
from links.models import Link, Tag


@pytest.fixture
def db_links(db):
    """A small, deterministic link library for search tests."""
    l1 = Link.objects.create(
        alias="github", original_url="https://github.com", link_type="LINK", click_count=5,
        description="Code hosting",
    )
    l2 = Link.objects.create(
        alias="gitlab", original_url="https://gitlab.com", link_type="LINK", click_count=2,
        description="Another code host",
    )
    l3 = Link.objects.create(
        alias="docs", original_url="https://docs.example.com/{page,default=index}", link_type="LINK",
        click_count=0, description="Template link",
    )
    l4 = Link.objects.create(
        alias="notify", original_url="", link_type="ACTION",
        action_config={"action_type": "discord_send"}, click_count=0,
    )
    tag = Tag.objects.create(name="dev")
    l1.tags.add(tag)
    return [l1, l2, l3, l4]


@pytest.mark.django_db
def test_search_aliases_matches_alias_and_returns_enriched_fields(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "git"})
    assert resp.status_code == 200
    data = resp.json()
    aliases = {item["alias"] for item in data}
    assert aliases == {"github", "gitlab"}

    github = next(i for i in data if i["alias"] == "github")
    # Enriched management fields are present and correct
    assert github["id"] == db_links[0].id
    assert github["link_type"] == "LINK"
    assert github["detail_url"] == f"/link/{db_links[0].id}/"
    assert github["edit_url"] == f"/link/{db_links[0].id}/edit/"
    assert github["click_count"] == 5
    assert github["description"] == "Code hosting"
    assert github["original_url"] == "https://github.com"
    # Backwards-compatible fields (hero autocomplete relies on these)
    assert github["url"].endswith("/github/")


@pytest.mark.django_db
def test_search_aliases_matches_original_url(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "gitlab.com"})
    assert resp.status_code == 200
    assert [i["alias"] for i in resp.json()] == ["gitlab"]


@pytest.mark.django_db
def test_search_aliases_matches_description(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "template link"})
    assert resp.status_code == 200
    assert [i["alias"] for i in resp.json()] == ["docs"]


@pytest.mark.django_db
def test_search_aliases_matches_tag_name(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "dev"})
    assert resp.status_code == 200
    assert [i["alias"] for i in resp.json()] == ["github"]


@pytest.mark.django_db
def test_search_aliases_priority_exact_first(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "github"})
    assert resp.status_code == 200
    assert resp.json()[0]["alias"] == "github"


@pytest.mark.django_db
def test_search_aliases_empty_query_returns_recent(client, db_links):
    # Touch l2 so it becomes the most recently updated (auto_now needs the
    # field explicitly listed in update_fields to refresh).
    db_links[1].click_count = 3
    db_links[1].save(update_fields=["click_count", "updated_at"])
    resp = client.get(reverse("search_aliases"))
    assert resp.status_code == 200
    data = resp.json()
    assert len(data) >= 4
    assert data[0]["alias"] == "gitlab"  # most recently updated first


@pytest.mark.django_db
def test_search_aliases_action_type_surfaces(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "notify"})
    assert resp.status_code == 200
    item = resp.json()[0]
    assert item["link_type"] == "ACTION"
    assert item["detail_url"] == f"/link/{db_links[3].id}/"


@pytest.mark.django_db
def test_search_aliases_no_results(client, db_links):
    resp = client.get(reverse("search_aliases"), {"q": "zzzznothing"})
    assert resp.status_code == 200
    assert resp.json() == []


# ---------------- /search/palette/ (⌘K command palette) ----------------

@pytest.mark.django_db
def test_palette_groups_links_pages_posts(client, db_links):
    from links.models import Page, Post
    Page.objects.create(url="https://github.com/about", title="About GitHub", summary="dev")
    Post.objects.create(title="Weekly digest", summary="dev roundup", content="body")
    resp = client.get(reverse("search_palette"), {"q": "github"})
    assert resp.status_code == 200
    data = resp.json()
    # links group matches alias/url; pages group matches title/url
    assert any(i["alias"] == "github" for i in data["links"])
    assert any(i["title"] == "About GitHub" for i in data["pages"])
    # posts group does not match "github"
    assert data["posts"] == []


@pytest.mark.django_db
def test_palette_matches_posts(client, db_links):
    from links.models import Post
    Post.objects.create(title="Weekly digest", summary="dev roundup", content="body")
    resp = client.get(reverse("search_palette"), {"q": "digest"})
    data = resp.json()
    assert any(i["title"] == "Weekly digest" for i in data["posts"])
    assert data["posts"][0]["edit_url"].startswith("/ui/posts/")


@pytest.mark.django_db
def test_palette_link_entry_has_management_fields(client, db_links):
    resp = client.get(reverse("search_palette"), {"q": "notify"})
    data = resp.json()
    item = next(i for i in data["links"] if i["alias"] == "notify")
    assert item["link_type"] == "ACTION"
    assert item["detail_url"] == f"/link/{db_links[3].id}/"
    assert item["edit_url"] == f"/link/{db_links[3].id}/edit/"


@pytest.mark.django_db
def test_palette_empty_query_returns_recent_links(client, db_links):
    resp = client.get(reverse("search_palette"))
    data = resp.json()
    assert len(data["links"]) >= 4
    assert data["pages"] == []
    assert data["posts"] == []


@pytest.mark.django_db
def test_palette_no_results(client, db_links):
    resp = client.get(reverse("search_palette"), {"q": "zzzznothing"})
    data = resp.json()
    assert data == {"links": [], "pages": [], "posts": []}
