"""Tests for the PyAuthz CLI."""

import json
import os
import tempfile

from pyauthz.cli.main import main


def _write_policy_file(tmpdir: str, content: str) -> str:
    """Write a YAML policy file and return the path."""
    path = os.path.join(tmpdir, "policies.yaml")
    with open(path, "w") as f:
        f.write(content)
    return path


VALID_YAML = """\
version: 1
roles:
  - name: admin
    permissions:
      - "*:*"
  - name: viewer
    permissions:
      - "documents:read"
policies:
  - name: allow-admin
    effect: allow
    roles:
      - admin
    permissions:
      - "*:*"
  - name: allow-viewer-read
    effect: allow
    roles:
      - viewer
    permissions:
      - "documents:read"
  - name: deny-pii
    effect: deny
    roles:
      - viewer
    permissions:
      - "pii:*"
"""


class TestCheckCommand:
    def test_check_valid_file(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(["check", path])
            assert result == 0

    def test_check_verbose(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(["check", path, "--verbose"])
            assert result == 0
            output = capsys.readouterr().out
            assert "admin" in output
            assert "viewer" in output
            assert "deny-pii" in output

    def test_check_nonexistent_path(self):
        result = main(["check", "/nonexistent/path"])
        assert result == 1

    def test_check_invalid_yaml(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, "- just a list\n")
            result = main(["check", path])
            assert result == 1

    def test_check_directory(self):
        with tempfile.TemporaryDirectory() as tmpdir:
            _write_policy_file(tmpdir, VALID_YAML)
            result = main(["check", tmpdir])
            assert result == 0


class TestSimulateCommand:
    def test_simulate_allowed(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(
                [
                    "simulate",
                    path,
                    "--subject",
                    "alice",
                    "--roles",
                    "admin",
                    "--action",
                    "documents:write",
                    "--resource-type",
                    "documents",
                ]
            )
            assert result == 0
            output = capsys.readouterr().out
            assert "ALLOWED" in output

    def test_simulate_denied(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(
                [
                    "simulate",
                    path,
                    "--subject",
                    "bob",
                    "--roles",
                    "viewer",
                    "--action",
                    "pii:read",
                    "--resource-type",
                    "pii",
                ]
            )
            assert result == 0
            output = capsys.readouterr().out
            assert "DENIED" in output

    def test_simulate_json_output(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(
                [
                    "simulate",
                    path,
                    "--subject",
                    "alice",
                    "--roles",
                    "admin",
                    "--action",
                    "documents:read",
                    "--resource-type",
                    "documents",
                    "--json",
                ]
            )
            assert result == 0
            output = capsys.readouterr().out
            data = json.loads(output)
            assert data["allowed"] is True

    def test_simulate_with_env(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(
                [
                    "simulate",
                    path,
                    "--subject",
                    "alice",
                    "--roles",
                    "admin",
                    "--action",
                    "documents:read",
                    "--resource-type",
                    "documents",
                    "-e",
                    "region=us-east-1",
                ]
            )
            assert result == 0


class TestRolesCommand:
    def test_list_roles(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(["roles", path])
            assert result == 0
            output = capsys.readouterr().out
            assert "admin" in output
            assert "viewer" in output


class TestPoliciesCommand:
    def test_list_policies(self, capsys):
        with tempfile.TemporaryDirectory() as tmpdir:
            path = _write_policy_file(tmpdir, VALID_YAML)
            result = main(["policies", path])
            assert result == 0
            output = capsys.readouterr().out
            assert "deny-pii" in output
            assert "deny" in output


class TestNoCommand:
    def test_no_command_shows_help(self):
        result = main([])
        assert result == 1
