"""Tests for ``arautopilot.core.user_store``."""

from __future__ import annotations

from pathlib import Path

import pytest

from arautopilot.core.rbac import Role
from arautopilot.core.user import User
from arautopilot.core.user_store import UserStore, seed_demo_users


def test_empty_store_starts_empty(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    assert len(s) == 0
    assert s.all_users() == []


def test_add_and_get(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    u = User.create(display_name="A", role=Role.USER, pin="1234")
    s.add(u)
    assert len(s) == 1
    assert s.get(u.user_id) is not None
    assert s.get(u.user_id).display_name == "A"


def test_duplicate_user_id_rejected(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    u = User.create(display_name="A", role=Role.USER, pin="1234")
    s.add(u)
    with pytest.raises(ValueError):
        s.add(u)


def test_remove_unknown_raises(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    with pytest.raises(KeyError):
        s.remove("nonexistent")


def test_persistence_across_instances(tmp_path: Path) -> None:
    p = tmp_path / "users.json"
    s = UserStore(p)
    s.add(User.create(display_name="A", role=Role.USER, pin="1234"))
    s.add(User.create(display_name="B", role=Role.OWNER, pin="5678"))

    s2 = UserStore(p)
    assert len(s2) == 2
    a = s2.find_by_name("A")
    b = s2.find_by_name("B")
    assert a is not None and a.verify_pin("1234")
    assert b is not None and b.verify_pin("5678")


def test_by_role_filters_correctly(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    s.add(User.create(display_name="SA",    role=Role.SUPER_ADMIN, pin="0001"))
    s.add(User.create(display_name="Eng1",  role=Role.ENGINEER,    pin="0002"))
    s.add(User.create(display_name="Eng2",  role=Role.ENGINEER,    pin="0003"))
    s.add(User.create(display_name="Own",   role=Role.OWNER,       pin="0004"))
    assert len(s.by_role(Role.ENGINEER)) == 2
    assert len(s.by_role(Role.OWNER)) == 1
    assert len(s.by_role(Role.USER)) == 0


def test_seed_demo_creates_one_of_each_role(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    seed_demo_users(s)
    assert len(s) == 4
    assert s.find_by_name("Alvaro") is not None
    assert s.find_by_name("Alvaro").role is Role.SUPER_ADMIN
    assert s.find_by_name("Alvaro").verify_pin("1111")


def test_seed_demo_idempotent(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    seed_demo_users(s)
    seed_demo_users(s)  # no-op
    assert len(s) == 4


def test_replace_updates_existing(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    u = User.create(display_name="A", role=Role.USER, pin="1234")
    s.add(u)
    u2 = u.set_pin("9999")
    s.replace(u2)
    assert len(s) == 1
    fetched = s.get(u.user_id)
    assert fetched is not None
    assert fetched.verify_pin("9999")
    assert not fetched.verify_pin("1234")


def test_membership_test(tmp_path: Path) -> None:
    s = UserStore(tmp_path / "users.json")
    u = User.create(display_name="A", role=Role.USER, pin="1234")
    s.add(u)
    assert u.user_id in s
    assert "nope" not in s
