# -*- coding: utf-8 -*-
"""Module Description.
Location: ./tests/unit/mcpgateway/test_cli_config_schema.py
Copyright 2026
SPDX-License-Identifier: Apache-2.0
Authors: Mihai Criveti

Module documentation...
"""

import json
import subprocess
import sys
from pathlib import Path
from unittest.mock import MagicMock

import pytest
from pydantic import BaseModel, ValidationError


def test_config_schema_prints_json():
    """Schema command should emit valid JSON when no output file is given."""
    result = subprocess.run([sys.executable, "-m", "mcpgateway.cli", "--config-schema"], capture_output=True, text=True, check=True)

    assert result.returncode == 0
    data = json.loads(result.stdout)
    assert "title" in data
    assert "properties" in data


def test_config_schema_writes_to_file(tmp_path: Path):
    """Schema command should write to a file when --output is given."""
    out_file = tmp_path / "schema.json"

    subprocess.run([sys.executable, "-m", "mcpgateway.cli", "--config-schema", str(out_file)], check=True)

    assert out_file.exists()
    data = json.loads(out_file.read_text())
    assert "title" in data
    assert "properties" in data


def test_insert_defaults_injects_app_host_port():
    """Defaults should be injected when no app/host/port provided."""
    # First-Party
    import mcpgateway.cli as cli

    args = cli._insert_defaults([])
    assert args[0] == cli.DEFAULT_APP
    assert "--host" in args
    assert "--port" in args


def test_insert_defaults_skips_host_port_for_uds():
    """Host/port defaults should be skipped when UDS is used."""
    # First-Party
    import mcpgateway.cli as cli

    args = cli._insert_defaults(["--uds", "/tmp/socket.sock"])
    assert args[0] == cli.DEFAULT_APP
    assert "--host" not in args
    assert "--port" not in args


def test_handle_validate_config_success(monkeypatch, capsys):
    """Validation success prints confirmation."""
    # First-Party
    import mcpgateway.cli as cli

    class DummySettings:
        def __init__(self, _env_file=None):
            self.path = _env_file

    monkeypatch.setattr(cli, "Settings", DummySettings)

    cli._handle_validate_config("custom.env")
    out = capsys.readouterr().out
    assert "Configuration in custom.env is valid" in out


def test_handle_validate_config_failure(monkeypatch, capsys):
    """Validation errors raise SystemExit and write to stderr."""
    # First-Party
    import mcpgateway.cli as cli

    class DummyModel:
        @staticmethod
        def build_error():
            class TempModel(BaseModel):
                field: int

            try:
                TempModel(field="bad")
            except ValidationError as exc:
                return exc
            raise AssertionError("ValidationError not raised")

    validation_error = DummyModel.build_error()

    def raise_error(*args, **kwargs):
        raise validation_error

    monkeypatch.setattr(cli, "Settings", raise_error)

    with pytest.raises(SystemExit):
        cli._handle_validate_config("bad.env")

    err = capsys.readouterr().err
    assert "Invalid configuration in bad.env" in err


def test_handle_config_schema_outputs_json(monkeypatch, capsys):
    """Schema helper prints JSON when no output is specified."""
    # First-Party
    import mcpgateway.cli as cli

    class DummySettings:
        @classmethod
        def model_json_schema(cls, mode="validation"):
            return {"title": "Dummy", "properties": {"x": {"type": "string"}}}

    monkeypatch.setattr(cli, "Settings", DummySettings)

    cli._handle_config_schema()
    data = json.loads(capsys.readouterr().out)
    assert data["title"] == "Dummy"


def test_handle_config_schema_writes_output(monkeypatch, tmp_path: Path):
    """Schema helper writes JSON to file when output is given."""
    # First-Party
    import mcpgateway.cli as cli

    class DummySettings:
        @classmethod
        def model_json_schema(cls, mode="validation"):
            return {"title": "Dummy", "properties": {"x": {"type": "string"}}}

    monkeypatch.setattr(cli, "Settings", DummySettings)

    out_file = tmp_path / "schema.json"
    cli._handle_config_schema(str(out_file))

    data = json.loads(out_file.read_text())
    assert data["title"] == "Dummy"


def test_handle_support_bundle_success(monkeypatch, tmp_path: Path, capsys):
    """Support bundle helper prints success message."""
    # First-Party
    import mcpgateway.cli as cli

    bundle_path = tmp_path / "bundle.zip"
    bundle_path.write_bytes(b"data")

    class DummyService:
        def __init__(self):
            self.called = False

        def generate_bundle(self, _config):
            self.called = True
            return bundle_path

    monkeypatch.setattr("mcpgateway.services.support_bundle_service.SupportBundleService", DummyService)

    cli._handle_support_bundle(output_dir=str(tmp_path), log_lines=10, include_logs=False, include_env=False, include_system=False)
    out = capsys.readouterr().out
    assert "Support bundle created" in out


def test_handle_support_bundle_failure(monkeypatch):
    """Support bundle helper raises SystemExit on failure."""
    # First-Party
    import mcpgateway.cli as cli

    class DummyService:
        def generate_bundle(self, _config):
            raise RuntimeError("boom")

    monkeypatch.setattr("mcpgateway.services.support_bundle_service.SupportBundleService", DummyService)

    with pytest.raises(SystemExit):
        cli._handle_support_bundle()


def test_main_support_bundle_parsing(monkeypatch):
    """CLI main should parse support bundle flags and invoke handler."""
    # First-Party
    import mcpgateway.cli as cli

    called = {}

    def fake_handle_support_bundle(**kwargs):
        called.update(kwargs)

    monkeypatch.setattr(cli, "_handle_support_bundle", fake_handle_support_bundle)
    monkeypatch.setattr(sys, "argv", ["mcpgateway", "--support-bundle", "--output-dir", "/tmp", "--log-lines", "42", "--no-logs", "--no-env"])

    cli.main()

    assert called["output_dir"] == "/tmp"
    assert called["log_lines"] == 42
    assert called["include_logs"] is False
    assert called["include_env"] is False
    assert called["include_system"] is True


def test_main_version_flag(monkeypatch, capsys):
    """CLI main should print version and exit."""
    # First-Party
    import mcpgateway.cli as cli

    monkeypatch.setattr(sys, "argv", ["mcpgateway", "--version"])
    cli.main()
    out = capsys.readouterr().out
    assert "mcpgateway" in out


def test_main_export_import_branch(monkeypatch):
    """CLI main should delegate to export/import subcommands."""
    # First-Party
    import mcpgateway.cli as cli

    mock_main = MagicMock()
    monkeypatch.setattr("mcpgateway.cli_export_import.main_with_subcommands", mock_main)
    monkeypatch.setattr(sys, "argv", ["mcpgateway", "export"])

    cli.main()
    mock_main.assert_called_once()


def test_main_calls_uvicorn(monkeypatch):
    """CLI main should invoke uvicorn with defaults."""
    # First-Party
    import mcpgateway.cli as cli

    called = {}

    def fake_main():
        called["argv"] = list(sys.argv)

    monkeypatch.setattr(cli.uvicorn, "main", fake_main)
    monkeypatch.setattr(sys, "argv", ["mcpgateway", "--reload"])

    cli.main()
    assert called["argv"][0] == "mcpgateway"
    assert cli.DEFAULT_APP in called["argv"]
