import json
import os
import pytest
from pathlib import Path
from unittest.mock import MagicMock, patch
from oaa.app_runners.custom_app import CustomAppRunner

BASE_DIR = Path(os.path.dirname(os.path.realpath(__file__)))


@pytest.fixture
def api_config(config):
    config.update(
        config_file=BASE_DIR / 'config-v2-2.yaml',
        config_format='yaml',
        config_version='v2',
    )
    yield config
    config.reset()


@pytest.fixture
def dry_run_save_json_runner(api_config):
    runner = CustomAppRunner(dry_run=True, save_json=True)
    yield runner


@pytest.fixture
def dry_run_no_save_runner(api_config):
    runner = CustomAppRunner(dry_run=True, save_json=False)
    yield runner


def test_dry_run_with_save_json_creates_file(dry_run_save_json_runner, tmp_path, monkeypatch):
    '''dry_run=True + save_json=True should write JSON to disk without pushing.'''
    monkeypatch.chdir(tmp_path)

    mock_veza = MagicMock()
    with patch('oaa.oaa_utils.get_oaa_client', return_value=mock_veza):
        dry_run_save_json_runner.run()

    json_files = list(tmp_path.glob('*.json'))
    assert len(json_files) == 1, 'Expected exactly one JSON file to be written'

    # Verify file contains a valid OAA payload
    payload = json.loads(json_files[0].read_text())
    assert 'applications' in payload
    assert 'permissions' in payload

    # Verify nothing was pushed to Veza
    mock_veza.push_application.assert_not_called()


def test_dry_run_without_save_json_creates_no_file(dry_run_no_save_runner, tmp_path, monkeypatch):
    '''dry_run=True + save_json=False should not write any file.'''
    monkeypatch.chdir(tmp_path)

    mock_veza = MagicMock()
    with patch('oaa.oaa_utils.get_oaa_client', return_value=mock_veza):
        dry_run_no_save_runner.run()

    json_files = list(tmp_path.glob('*.json'))
    assert len(json_files) == 0, 'Expected no JSON files to be written'

    mock_veza.push_application.assert_not_called()


def test_dry_run_save_json_filename_contains_datasource(dry_run_save_json_runner, tmp_path, monkeypatch):
    '''The saved filename should include the datasource name.'''
    monkeypatch.chdir(tmp_path)

    mock_veza = MagicMock()
    with patch('oaa.oaa_utils.get_oaa_client', return_value=mock_veza):
        dry_run_save_json_runner.run()

    json_files = list(tmp_path.glob('*.json'))
    assert len(json_files) == 1
    assert dry_run_save_json_runner._datasource_name in json_files[0].name
