"""Tests for CLI commands."""

import json
import os

import pytest
from click.testing import CliRunner

from yaml_doctor.cli import cli


@pytest.fixture
def runner():
    return CliRunner()


@pytest.fixture
def good_yaml(tmp_path):
    f = tmp_path / "good.yaml"
    f.write_text("---\nname: test\nvalue: 42\n")
    return str(f)


@pytest.fixture
def bad_yaml(tmp_path):
    f = tmp_path / "bad.yaml"
    f.write_text("apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: test\nspec:\n  replicas: 1\n  template:\n    spec:\n      containers:\n        - name: app\n          image: nginx:latest\n          securityContext:\n            privileged: true\n")
    return str(f)


@pytest.fixture
def invalid_yaml(tmp_path):
    f = tmp_path / "invalid.yaml"
    f.write_text("key: [broken")
    return str(f)


class TestLintCommand:
    def test_lint_good(self, runner, good_yaml):
        result = runner.invoke(cli, ["lint", good_yaml])
        assert result.exit_code == 0

    def test_lint_bad_exits_1(self, runner, bad_yaml):
        result = runner.invoke(cli, ["lint", bad_yaml])
        assert result.exit_code == 1

    def test_lint_invalid(self, runner, invalid_yaml):
        result = runner.invoke(cli, ["lint", invalid_yaml])
        assert result.exit_code == 1

    def test_lint_json(self, runner, good_yaml, tmp_path):
        out = str(tmp_path / "report.json")
        result = runner.invoke(cli, ["lint", good_yaml, "-j", out])
        assert result.exit_code == 0
        data = json.loads(open(out).read())
        assert "file" in data
        assert "score" in data

    def test_lint_html(self, runner, good_yaml, tmp_path):
        out = str(tmp_path / "report.html")
        result = runner.invoke(cli, ["lint", good_yaml, "--html", out])
        assert result.exit_code == 0
        html = open(out).read()
        assert "yaml-doctor" in html

    def test_lint_nonexistent(self, runner):
        result = runner.invoke(cli, ["lint", "/nonexistent/file.yaml"])
        assert result.exit_code != 0


class TestScanCommand:
    def test_scan_dir(self, runner, tmp_path):
        (tmp_path / "a.yaml").write_text("---\nname: a\n")
        result = runner.invoke(cli, ["scan", str(tmp_path)])
        assert result.exit_code == 0

    def test_scan_json(self, runner, tmp_path):
        (tmp_path / "a.yaml").write_text("---\nname: a\n")
        out = str(tmp_path / "scan.json")
        result = runner.invoke(cli, ["scan", str(tmp_path), "-j", out])
        assert result.exit_code == 0
        data = json.loads(open(out).read())
        assert "total_files" in data
        assert "files" in data

    def test_scan_html(self, runner, tmp_path):
        (tmp_path / "a.yaml").write_text("---\nname: a\n")
        out = str(tmp_path / "report.html")
        result = runner.invoke(cli, ["scan", str(tmp_path), "--html", out])
        assert result.exit_code == 0
        assert os.path.exists(out)

    def test_scan_no_recursive(self, runner, tmp_path):
        sub = tmp_path / "sub"
        sub.mkdir()
        (tmp_path / "root.yaml").write_text("---\nname: root\n")
        (sub / "child.yaml").write_text("---\nname: child\n")
        result = runner.invoke(cli, ["scan", str(tmp_path), "--no-recursive"])
        assert result.exit_code == 0


class TestRulesCommand:
    def test_rules(self, runner):
        result = runner.invoke(cli, ["rules"])
        assert result.exit_code == 0
        assert "60 rules" in result.output


class TestDemoCommand:
    def test_demo_all(self, runner):
        result = runner.invoke(cli, ["demo"])
        assert result.exit_code == 0
        assert "Demo Mode" in result.output

    def test_demo_kubernetes(self, runner):
        result = runner.invoke(cli, ["demo", "--type", "kubernetes"])
        assert result.exit_code == 0

    def test_demo_compose(self, runner):
        result = runner.invoke(cli, ["demo", "--type", "compose"])
        assert result.exit_code == 0

    def test_demo_github_actions(self, runner):
        result = runner.invoke(cli, ["demo", "--type", "github-actions"])
        assert result.exit_code == 0

    def test_demo_gitlab_ci(self, runner):
        result = runner.invoke(cli, ["demo", "--type", "gitlab-ci"])
        assert result.exit_code == 0

    def test_demo_yaml(self, runner):
        result = runner.invoke(cli, ["demo", "--type", "yaml"])
        assert result.exit_code == 0

    def test_demo_html(self, runner, tmp_path):
        out = str(tmp_path / "demo.html")
        result = runner.invoke(cli, ["demo", "--html", out])
        assert result.exit_code == 0
        assert os.path.exists(out)

    def test_demo_json(self, runner, tmp_path):
        out = str(tmp_path / "demo.json")
        result = runner.invoke(cli, ["demo", "-j", out])
        assert result.exit_code == 0
        data = json.loads(open(out).read())
        assert "total_files" in data


class TestFixCommand:
    def test_fix_with_issues(self, runner, bad_yaml):
        result = runner.invoke(cli, ["fix", bad_yaml])
        assert result.exit_code == 0
        assert "Fix suggestions" in result.output or "→" in result.output

    def test_fix_clean(self, runner, good_yaml):
        result = runner.invoke(cli, ["fix", good_yaml])
        assert result.exit_code == 0


class TestVersion:
    def test_version(self, runner):
        result = runner.invoke(cli, ["--version"])
        assert result.exit_code == 0
        assert "1.0.0" in result.output
