import pytest
from unittest import mock
from ImportNinja import cli
import sys


@pytest.fixture
def mock_find_python_files():
    with mock.patch('ImportNinja.cli.find_python_files') as mock_find:
        yield mock_find


@pytest.fixture
def mock_extract_imports_and_usage():
    with mock.patch('ImportNinja.cli.extract_imports_and_usage') as mock_extract:
        yield mock_extract

      
@pytest.fixture
def mock_open_file():
    with mock.patch('builtins.open', mock.mock_open(read_data='import os\nprint(os.getcwd())')) as mock_file:
        yield mock_file


@pytest.fixture
def mock_get_requirements_imports():
    with mock.patch('ImportNinja.cli.get_requirements_imports') as mock_requirements:
        yield mock_requirements


@pytest.fixture
def mock_write_requirements_file():
    with mock.patch('ImportNinja.cli.write_requirements_file') as mock_write:
        yield mock_write


@pytest.fixture
def mock_print_functions():
    with mock.patch('ImportNinja.cli.print_counts'), \
         mock.patch('ImportNinja.cli.print_syntax_error_files'), \
         mock.patch('ImportNinja.cli.print_unused_imports'), \
         mock.patch('ImportNinja.cli.print_imports'), \
         mock.patch('ImportNinja.cli.requirements_file_analysis'):
        yield


def test_cli_basic_run(mock_find_python_files, mock_extract_imports_and_usage, mock_open_file, mock_print_functions):
    # Mock the file discovery and import extraction
    mock_find_python_files.return_value = ['file1.py', 'file2.py']
    mock_extract_imports_and_usage.return_value = ({'os', 'sys'}, {'sys'})

    # Simulate CLI arguments
    test_args = ['cli.py', '.', '-r', 'requirements.txt']
    with mock.patch.object(sys, 'argv', test_args):
        cli.main()

    # Verify the mocks were called as expected
    mock_find_python_files.assert_called_once_with('.')
    mock_extract_imports_and_usage.assert_called()


def test_cli_write_requirements_file(mock_write_requirements_file, mock_extract_imports_and_usage, mock_print_functions):
    mock_extract_imports_and_usage.return_value = ({'os', 'requests'}, {'os'})

    test_args = ['cli.py', '.', '-r', 'requirements.txt']
    with mock.patch.object(sys, 'argv', test_args):
        cli.main()

    mock_write_requirements_file.assert_called_once_with('requirements.txt', {'os', 'requests'})


def test_cli_syntax_error_handling(mock_find_python_files, mock_print_functions):
    with mock.patch('ImportNinja.cli.check_syntax', return_value=False), \
        mock.patch('builtins.open', mock.mock_open(read_data='')):  # Mock open to prevent file access
        
        mock_find_python_files.return_value = ['syntax_error_file.py']

        test_args = ['cli.py', '.']
        with mock.patch.object(sys, 'argv', test_args):
            cli.main()

        mock_find_python_files.assert_called_once_with('.')

