"""Tests del loader NodeGroups kind=Group (issue 0036b).

El binario C++ implementa `node_groups_count_for_group` y
`node_groups_page_for_group` sobre operations.db. El subcomando
`gx-cli group page <container_id>` espejea exactamente esa query, asi
estos tests verifican el contrato SQL: count + columnas fijas
(id, name, type_ref, status, updated_at) + ORDER BY updated_at DESC.

Reusa la fixture `env_dirs` del modulo de tests del CLI.
"""
from __future__ import annotations

import sqlite3

import pytest

from test_gx_cli import OPS_SCHEMA, APP_SCHEMA, env_dirs, run_gx  # noqa: F401


def _seed_group_with_children(ops_db, group_id: str, n_children: int):
    """Inserta un Group + n_children entidades hijas con group_id seteado.

    Las hijas se crean con updated_at distintos (separados un milisegundo)
    para que el ORDER BY updated_at DESC tenga orden estable y verificable.
    """
    cn = sqlite3.connect(ops_db)
    try:
        # El Group contenedor — type_ref='Group' (definicion en 0035a).
        cn.execute(
            "INSERT INTO entities(id, name, type_ref, status, source, "
            "                     metadata, created_at, updated_at) "
            "VALUES (?, ?, 'Group', 'active', 'manual', '{}', "
            "        '2026-05-04T10:00:00.000Z', '2026-05-04T10:00:00.000Z')",
            (group_id, "test-group"),
        )
        # Hijas: Word entities con group_id apuntando al Group. Generamos
        # updated_at descendente para que el orden ORDER BY DESC sea
        # determinista (la primera insertada queda al final del ranking).
        for i in range(n_children):
            child_id = f"word_{i:02d}"
            ts = f"2026-05-04T11:{i:02d}:00.000Z"
            cn.execute(
                "INSERT INTO entities(id, name, type_ref, status, source, "
                "                     metadata, group_id, "
                "                     created_at, updated_at) "
                "VALUES (?, ?, 'Word', 'active', 'manual', '{}', ?, ?, ?)",
                (child_id, f"word-{i}", group_id, ts, ts),
            )
        # Una entidad sin group_id para verificar que NO aparece en el page.
        cn.execute(
            "INSERT INTO entities(id, name, type_ref, status, source, "
            "                     metadata, created_at, updated_at) "
            "VALUES ('orphan_01', 'orphan', 'Word', 'active', 'manual', '{}', "
            "        '2026-05-04T09:00:00.000Z', '2026-05-04T09:00:00.000Z')"
        )
        cn.commit()
    finally:
        cn.close()


class TestGroupPage:
    def test_count_matches_children(self, env_dirs):
        _seed_group_with_children(env_dirs["ops"], "grp_alpha", n_children=5)
        out = run_gx(env_dirs, "group", "page", "grp_alpha")
        assert out["total"] == 5, out
        assert len(out["rows"]) == 5

    def test_columns_are_fixed_set(self, env_dirs):
        _seed_group_with_children(env_dirs["ops"], "grp_alpha", n_children=3)
        out = run_gx(env_dirs, "group", "page", "grp_alpha")
        assert out["rows"], out
        first = out["rows"][0]
        assert set(first.keys()) == {"id", "name", "type_ref",
                                       "status", "updated_at"}

    def test_orphan_not_listed(self, env_dirs):
        _seed_group_with_children(env_dirs["ops"], "grp_alpha", n_children=3)
        out = run_gx(env_dirs, "group", "page", "grp_alpha")
        ids = {r["id"] for r in out["rows"]}
        assert "orphan_01" not in ids
        assert ids == {"word_00", "word_01", "word_02"}

    def test_order_by_updated_at_desc(self, env_dirs):
        _seed_group_with_children(env_dirs["ops"], "grp_alpha", n_children=4)
        out = run_gx(env_dirs, "group", "page", "grp_alpha")
        ids_in_order = [r["id"] for r in out["rows"]]
        # word_03 tiene el updated_at mas reciente (11:03), word_00 el mas
        # antiguo (11:00). El ORDER BY ... DESC los pone en ese orden.
        assert ids_in_order == ["word_03", "word_02", "word_01", "word_00"]

    def test_pagination_offset_limit(self, env_dirs):
        _seed_group_with_children(env_dirs["ops"], "grp_alpha", n_children=10)
        page1 = run_gx(env_dirs, "group", "page", "grp_alpha",
                        "--limit", "3", "--offset", "0")
        page2 = run_gx(env_dirs, "group", "page", "grp_alpha",
                        "--limit", "3", "--offset", "3")
        assert page1["total"] == 10
        assert page2["total"] == 10
        ids1 = [r["id"] for r in page1["rows"]]
        ids2 = [r["id"] for r in page2["rows"]]
        # No deben solaparse y el orden global sigue DESC por updated_at.
        assert set(ids1).isdisjoint(set(ids2))
        assert ids1 == ["word_09", "word_08", "word_07"]
        assert ids2 == ["word_06", "word_05", "word_04"]

    def test_unknown_container_returns_empty(self, env_dirs):
        # Sin seed — la BD esta vacia.
        out = run_gx(env_dirs, "group", "page", "no_such_group")
        assert out["total"] == 0
        assert out["rows"] == []
