"""Tests for workspace configuration reading."""

from pathlib import Path

import pytest


class TestWorkspaceConfig:
    """Tests for reading .beadhub configuration."""

    def test_load_workspace_config_returns_workspace_id(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should return workspace_id from .beadhub file."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(
            """\
workspace_id: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
beadhub_url: "http://localhost:8000"
alias: "test-agent"
"""
        )

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id == "a1b2c3d4-5678-90ab-cdef-1234567890ab"
        assert config.beadhub_url == "http://localhost:8000"
        assert config.alias == "test-agent"

    def test_load_workspace_config_handles_unquoted_values(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should handle values without quotes."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(
            """\
workspace_id: no-quotes-id
beadhub_url: http://example.com:9000
alias: my-agent
"""
        )

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id == "no-quotes-id"
        assert config.beadhub_url == "http://example.com:9000"
        assert config.alias == "my-agent"

    def test_load_workspace_config_returns_none_if_file_missing(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should return None if .beadhub doesn't exist."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        # No .beadhub file created

        config = load_workspace_config()

        assert config is None

    def test_load_workspace_config_skips_comments(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should skip comment lines."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(
            """\
# Generated by: bdh init
# DO NOT COMMIT

workspace_id: "test-id"
beadhub_url: "http://localhost:8000"
alias: "claude-code"
"""
        )

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id == "test-id"

    def test_load_workspace_config_uses_custom_path(self, tmp_path: Path):
        """load_workspace_config should accept a custom path."""
        from beadhub.workspace_config import load_workspace_config

        config_file = tmp_path / "custom" / ".beadhub"
        config_file.parent.mkdir()
        config_file.write_text('workspace_id: "custom-id"\n')

        config = load_workspace_config(path=config_file.parent)

        assert config is not None
        assert config.workspace_id == "custom-id"

    def test_load_workspace_config_handles_empty_file(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should handle empty .beadhub file."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text("")

        config = load_workspace_config()

        # Should return config but with None/empty values
        assert config is not None
        assert config.workspace_id is None


class TestGetWorkspaceId:
    """Tests for get_workspace_id helper function."""

    def test_get_workspace_id_returns_from_file(self, tmp_path: Path, monkeypatch):
        """get_workspace_id should return workspace_id from .beadhub."""
        from beadhub.workspace_config import get_workspace_id

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('workspace_id: "file-workspace-id"\n')

        workspace_id = get_workspace_id()

        assert workspace_id == "file-workspace-id"

    def test_get_workspace_id_override_takes_precedence(self, tmp_path: Path, monkeypatch):
        """Explicit override should take precedence over file."""
        from beadhub.workspace_config import get_workspace_id

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('workspace_id: "file-id"\n')

        workspace_id = get_workspace_id(override="explicit-id")

        assert workspace_id == "explicit-id"

    def test_get_workspace_id_returns_none_if_no_file(self, tmp_path: Path, monkeypatch):
        """get_workspace_id should return None if no .beadhub and no override."""
        from beadhub.workspace_config import get_workspace_id

        monkeypatch.chdir(tmp_path)

        workspace_id = get_workspace_id()

        assert workspace_id is None


class TestEdgeCases:
    """Edge case tests for .beadhub parsing."""

    def test_handles_url_with_multiple_colons(self, tmp_path: Path, monkeypatch):
        """Parser should handle values containing colons (e.g., URLs)."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('beadhub_url: "http://localhost:8000"\n')

        config = load_workspace_config()

        assert config is not None
        assert config.beadhub_url == "http://localhost:8000"

    def test_handles_mismatched_quotes(self, tmp_path: Path, monkeypatch):
        """Mismatched quotes should be preserved."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text("workspace_id: \"value'\n")

        config = load_workspace_config()

        # Mismatched quotes should NOT be stripped
        assert config is not None
        assert config.workspace_id == "\"value'"

    def test_handles_empty_key(self, tmp_path: Path, monkeypatch):
        """Lines with empty key (like ': value') should be skipped."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(": ignored\nworkspace_id: valid\n")

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id == "valid"

    def test_last_key_wins_on_duplicate(self, tmp_path: Path, monkeypatch):
        """When duplicate keys exist, last one wins."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('workspace_id: "first"\nworkspace_id: "second"\n')

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id == "second"

    def test_rejects_oversized_file(self, tmp_path: Path, monkeypatch):
        """Should reject files larger than MAX_CONFIG_SIZE."""
        from beadhub.workspace_config import MAX_CONFIG_SIZE, load_workspace_config

        monkeypatch.chdir(tmp_path)
        # Create file larger than max
        (tmp_path / ".beadhub").write_text("x" * (MAX_CONFIG_SIZE + 1))

        with pytest.raises(ValueError, match="too large"):
            load_workspace_config()

    def test_handles_unicode_values(self, tmp_path: Path, monkeypatch):
        """Parser should handle non-ASCII values."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('alias: "测试-agent"\n', encoding="utf-8")

        config = load_workspace_config()

        assert config is not None
        assert config.alias == "测试-agent"

    def test_handles_whitespace_in_values(self, tmp_path: Path, monkeypatch):
        """Parser should preserve whitespace inside values."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('alias: "my agent name"\n')

        config = load_workspace_config()

        assert config is not None
        assert config.alias == "my agent name"

    def test_handles_empty_quoted_value(self, tmp_path: Path, monkeypatch):
        """Empty quoted values should be treated as missing."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('workspace_id: ""\n')

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id is None


class TestProjectSlug:
    """Tests for project_slug support in workspace config."""

    def test_load_workspace_config_returns_project_slug(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should return project_slug from .beadhub file."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(
            """\
workspace_id: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
project_slug: "beadhub"
beadhub_url: "http://localhost:8000"
"""
        )

        config = load_workspace_config()

        assert config is not None
        assert config.project_slug == "beadhub"

    def test_get_project_slug_returns_from_file(self, tmp_path: Path, monkeypatch):
        """get_project_slug should return project_slug from .beadhub."""
        from beadhub.workspace_config import get_project_slug

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('project_slug: "my-project"\n')

        project_slug = get_project_slug()

        assert project_slug == "my-project"

    def test_get_project_slug_override_takes_precedence(self, tmp_path: Path, monkeypatch):
        """Explicit override should take precedence over file."""
        from beadhub.workspace_config import get_project_slug

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('project_slug: "file-slug"\n')

        project_slug = get_project_slug(override="explicit-slug")

        assert project_slug == "explicit-slug"

    def test_get_project_slug_returns_none_if_missing(self, tmp_path: Path, monkeypatch):
        """get_project_slug should return None if not in file and no override."""
        from beadhub.workspace_config import get_project_slug

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('workspace_id: "ws-id"\n')

        project_slug = get_project_slug()

        assert project_slug is None


class TestHumanName:
    """Tests for human_name support in workspace config."""

    def test_load_workspace_config_returns_human_name(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should return human_name from .beadhub file."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(
            """\
workspace_id: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
human_name: "Juan"
beadhub_url: "http://localhost:8000"
"""
        )

        config = load_workspace_config()

        assert config is not None
        assert config.human_name == "Juan"

    def test_get_human_name_returns_from_file(self, tmp_path: Path, monkeypatch):
        """get_human_name should return human_name from .beadhub."""
        from beadhub.workspace_config import get_human_name

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('human_name: "Maria"\n')

        human_name = get_human_name()

        assert human_name == "Maria"

    def test_get_human_name_override_takes_precedence(self, tmp_path: Path, monkeypatch):
        """Explicit override should take precedence over file."""
        from beadhub.workspace_config import get_human_name

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('human_name: "FileHuman"\n')

        human_name = get_human_name(override="ExplicitHuman")

        assert human_name == "ExplicitHuman"

    def test_get_human_name_returns_none_if_missing(self, tmp_path: Path, monkeypatch):
        """get_human_name should return None if not in file and no override."""
        from beadhub.workspace_config import get_human_name

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text('workspace_id: "ws-id"\n')

        human_name = get_human_name()

        assert human_name is None


class TestFullConfig:
    """Tests for loading a complete .beadhub config with all fields."""

    def test_load_complete_config(self, tmp_path: Path, monkeypatch):
        """load_workspace_config should return all fields from a complete .beadhub file."""
        from beadhub.workspace_config import load_workspace_config

        monkeypatch.chdir(tmp_path)
        (tmp_path / ".beadhub").write_text(
            """\
# Generated by: bdh init
# DO NOT COMMIT - add to .gitignore

workspace_id: "a1b2c3d4-5678-90ab-cdef-1234567890ab"
beadhub_url: "http://localhost:8000"
alias: "claude-code"
human_name: "Juan"
project_slug: "beadhub"
"""
        )

        config = load_workspace_config()

        assert config is not None
        assert config.workspace_id == "a1b2c3d4-5678-90ab-cdef-1234567890ab"
        assert config.beadhub_url == "http://localhost:8000"
        assert config.alias == "claude-code"
        assert config.human_name == "Juan"
        assert config.project_slug == "beadhub"
