import pytest
import json
import tempfile
from unittest.mock import patch, mock_open, MagicMock
from pathlib import Path
import sys
import os

# Add parent directory to path so we can import check-versions
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
from check_versions import get_latest_version, get_current_version, main

@pytest.fixture
def mock_config():
    return {
        'test-package': {
            'github_repo': 'owner/repo',
            'version_method': 'release',
            'pkgbuild_path': 'test-package/PKGBUILD'
        },
        'tag-package': {
            'github_repo': 'owner/repo2',
            'version_method': 'tag',
            'pkgbuild_path': 'tag-package/PKGBUILD',
            'version_pattern': 'v(\\d+\\.\\d+\\.\\d+)'
        }
    }

@pytest.fixture
def mock_headers():
    return {
        'Authorization': 'token test-token',
        'Accept': 'application/vnd.github.v3+json'
    }

def test_get_latest_version_release(mock_config, mock_headers):
    with patch('requests.get') as mock_get:
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {'tag_name': 'v1.2.3'}
        mock_get.return_value = mock_response

        version = get_latest_version(mock_config['test-package'], mock_headers)
        assert version == '1.2.3'
        mock_get.assert_called_with(
            'https://api.github.com/repos/owner/repo/releases/latest',
            headers=mock_headers
        )

def test_get_latest_version_tag(mock_config, mock_headers):
    with patch('requests.get') as mock_get:
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = [{'name': 'v2.3.4'}]
        mock_get.return_value = mock_response

        version = get_latest_version(mock_config['tag-package'], mock_headers)
        assert version == '2.3.4'
        mock_get.assert_called_with(
            'https://api.github.com/repos/owner/repo2/tags',
            headers=mock_headers
        )

def test_get_current_version():
    pkgbuild_content = '''
# Maintainer: Test User <test@example.com>
pkgname=test-package
pkgver=1.2.3
pkgrel=1
    '''
    with patch('builtins.open', mock_open(read_data=pkgbuild_content)):
        version = get_current_version('dummy/path')
        assert version == '1.2.3'

def test_main_with_updates():
    config_yaml = '''
packages:
  test-package:
    github_repo: owner/repo
    version_method: release
    pkgbuild_path: test-package/PKGBUILD
'''
    pkgbuild_content = '''
pkgname=test-package
pkgver=1.2.3
pkgrel=1
'''
    
    with tempfile.NamedTemporaryFile(mode='w+') as github_output:
        with patch.dict('os.environ', {'GITHUB_TOKEN': 'test-token', 'GITHUB_OUTPUT': github_output.name}):
            # Create a dictionary to store different file contents and mocks
            file_contents = {
                'aur-packages.yml': config_yaml,
                'test-package/PKGBUILD': pkgbuild_content,
                github_output.name: ''
            }
            
            # Store file mocks
            file_mocks = {}
            
            def mock_open_file(filename, mode='r'):
                if mode == 'w':
                    if filename not in file_mocks:
                        file_mocks[filename] = mock_open()
                    return file_mocks[filename](filename, mode)
                return mock_open(read_data=file_contents.get(filename, ''))(filename, mode)

            with patch('builtins.open', side_effect=mock_open_file):
                with patch('requests.get') as mock_get:
                    mock_response = MagicMock()
                    mock_response.status_code = 200
                    mock_response.json.return_value = {'tag_name': 'v1.2.4'}
                    mock_get.return_value = mock_response
                    
                    main()
                    
                    # Get the mock for the output file
                    output_mock = file_mocks[github_output.name]
                    handle = output_mock()
                    
                    # Get all write calls
                    write_calls = [c[1][0] for c in handle.mock_calls if c[0] == 'write']
                    written_content = ''.join(write_calls)
                    
                    assert 'updates_needed=true' in written_content
                    assert '"latest": "1.2.4"' in written_content
                    assert '"current": "1.2.3"' in written_content

def test_main_no_updates():
    config_yaml = '''
packages:
  test-package:
    github_repo: owner/repo
    version_method: release
    pkgbuild_path: test-package/PKGBUILD
'''
    pkgbuild_content = '''
pkgname=test-package
pkgver=1.2.3
pkgrel=1
'''
    
    with tempfile.NamedTemporaryFile(mode='w+') as github_output:
        with patch.dict('os.environ', {'GITHUB_TOKEN': 'test-token', 'GITHUB_OUTPUT': github_output.name}):
            # Create a dictionary to store different file contents and mocks
            file_contents = {
                'aur-packages.yml': config_yaml,
                'test-package/PKGBUILD': pkgbuild_content,
                github_output.name: ''
            }
            
            # Store file mocks
            file_mocks = {}
            
            def mock_open_file(filename, mode='r'):
                if mode == 'w':
                    if filename not in file_mocks:
                        file_mocks[filename] = mock_open()
                    return file_mocks[filename](filename, mode)
                return mock_open(read_data=file_contents.get(filename, ''))(filename, mode)

            with patch('builtins.open', side_effect=mock_open_file):
                with patch('requests.get') as mock_get:
                    mock_response = MagicMock()
                    mock_response.status_code = 200
                    mock_response.json.return_value = {'tag_name': 'v1.2.3'}
                    mock_get.return_value = mock_response
                    
                    main()
                    
                    # Get the mock for the output file
                    output_mock = file_mocks[github_output.name]
                    handle = output_mock()
                    
                    # Get all write calls
                    write_calls = [c[1][0] for c in handle.mock_calls if c[0] == 'write']
                    written_content = ''.join(write_calls)
                    
                    assert 'updates_needed=false' in written_content
                    assert '[]' in written_content 