from __future__ import annotations

import json

from web_core.auth import profile_store as store


def test_save_and_load_settings_are_isolated_by_profile(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    store.save_web_settings({"symbol": "AAPL", "period": "1mo"}, profile_id="alice")
    store.save_web_settings({"symbol": "MSFT", "period": "3mo"}, profile_id="bob")

    alice = store.load_web_settings(profile_id="alice")
    bob = store.load_web_settings(profile_id="bob")
    unknown = store.load_web_settings(profile_id="carol")

    assert alice["symbol"] == "AAPL"
    assert alice["period"] == "1mo"
    assert bob["symbol"] == "MSFT"
    assert bob["period"] == "3mo"
    assert unknown["symbol"] == "AAPL"  # fallback default


def test_load_settings_migrates_legacy_flat_payload_to_default_profile(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    legacy_payload = {"symbol": "TSLA", "interval": "1h", "max_bars": 9999}
    legacy_path.write_text(json.dumps(legacy_payload), encoding="utf-8")

    loaded = store.load_web_settings(profile_id="default")
    assert loaded["symbol"] == "TSLA"
    assert loaded["interval"] == "1h"
    assert loaded["max_bars"] == 5000  # normalized max cap

    store.save_web_settings({"symbol": "TSLA"}, profile_id="default")
    stored = json.loads(settings_path.read_text(encoding="utf-8"))
    assert "profiles" in stored
    assert "default" in stored["profiles"]
    assert "settings" in stored["profiles"]["default"]
    assert "audit" in stored["profiles"]["default"]


def test_list_web_profiles_includes_saved_profiles(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    store.save_web_settings({"symbol": "AAPL"}, profile_id="zoe")
    store.save_web_settings({"symbol": "AAPL"}, profile_id="alice")

    profile_ids = store.list_web_profiles()
    assert "default" in profile_ids
    assert "alice" in profile_ids
    assert "zoe" in profile_ids


def test_resolve_login_profile_prefers_session_then_query() -> None:
    assert store.resolve_login_profile("alice", "bob") == "alice"
    assert store.resolve_login_profile("", "bob") == "bob"
    assert store.resolve_login_profile(None, None) is None


def test_profile_exists_normalizes_input() -> None:
    profiles = {"default", "alice"}
    assert store.profile_exists("alice", profiles) is True
    assert store.profile_exists("  ", profiles) is True  # normalizes to default
    assert store.profile_exists("bob", profiles) is False


def test_profile_exists_is_case_insensitive() -> None:
    profiles = {"default", "Alice"}
    assert store.profile_exists("alice", profiles) is True
    assert store.find_existing_profile_id("ALICE", profiles) == "Alice"


def test_is_profile_session_expired_after_timeout() -> None:
    now_epoch = 2000.0
    assert store.is_profile_session_expired(1000.0, now_epoch, timeout_sec=900) is True
    assert store.is_profile_session_expired(1500.0, now_epoch, timeout_sec=900) is False
    assert store.is_profile_session_expired(None, now_epoch, timeout_sec=900) is False


def test_is_truthy_flag_parses_common_values() -> None:
    assert store.is_truthy_flag("1") is True
    assert store.is_truthy_flag("true") is True
    assert store.is_truthy_flag("yes") is True
    assert store.is_truthy_flag("0") is False
    assert store.is_truthy_flag(None) is False


def test_create_profile_with_pin_requires_pin_for_verification(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    store.create_profile("alice", pin="1234", now_epoch=1700000000)

    assert store.profile_requires_pin("alice") is True
    assert store.verify_profile_pin("alice", "1234") is True
    assert store.verify_profile_pin("alice", "9999") is False


def test_audit_stamps_update_on_save_and_login(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    store.create_profile("alice", now_epoch=1700000000)
    store.save_web_settings({"symbol": "MSFT"}, profile_id="alice")
    store.mark_profile_login("alice", now_epoch=1700000010)

    audit = store.get_profile_audit("alice")
    assert audit["created_at"] == 1700000000
    assert audit["last_login_at"] == 1700000010
    assert audit["last_symbol"] == "MSFT"


def test_load_settings_migrates_old_profiles_map_structure(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    old_payload = {
        "last_profile": "alice",
        "profiles": {
            "alice": {"symbol": "TSLA", "interval": "1d"},
            "bob": {"symbol": "MSFT", "interval": "1h"},
        },
    }
    settings_path.write_text(json.dumps(old_payload), encoding="utf-8")

    alice_settings = store.load_web_settings("alice")
    bob_settings = store.load_web_settings("bob")
    assert alice_settings["symbol"] == "TSLA"
    assert bob_settings["symbol"] == "MSFT"

    store.save_web_settings({"symbol": "AAPL"}, profile_id="alice")
    stored = json.loads(settings_path.read_text(encoding="utf-8"))
    assert isinstance(stored["profiles"]["alice"], dict)
    assert "settings" in stored["profiles"]["alice"]


def test_watchlist_round_trip_keeps_multiple_symbols(tmp_path, monkeypatch) -> None:
    settings_path = tmp_path / "settings.json"
    legacy_path = tmp_path / "legacy.json"
    monkeypatch.setattr(store, "SETTINGS_PATH", settings_path)
    monkeypatch.setattr(store, "LEGACY_SETTINGS_PATH", legacy_path)

    store.save_web_settings({"symbol": "AMD", "watchlist": ["AMD", "TSLA"]}, profile_id="matt")
    loaded = store.load_web_settings(profile_id="matt")
    assert loaded["watchlist"] == ["AMD", "TSLA"]
