"""
Test download commands
"""
import pytest
from unittest.mock import Mock, patch, call
from pathlib import Path

from juicekeggers.commands.download_ko import (
    read_organism_codes, download_single_ko, download_ko_files
)
from juicekeggers.commands.download_proteins import (
    parse_organism_file, download_protein_file, download_protein_files
)


def test_read_organism_codes(temp_dir):
    """Test reading organism codes from file."""
    # Test one per line
    file1 = temp_dir / "orgs1.txt"
    file1.write_text("hsa\nmmu\neco\n# Comment\n\nrno")
    
    codes1 = read_organism_codes(file1)
    assert codes1 == ["hsa", "mmu", "eco", "rno"]
    
    # Test TSV format
    file2 = temp_dir / "orgs2.tsv"
    file2.write_text("hsa\tHuman\nmmu\tMouse\neco\tE. coli")
    
    codes2 = read_organism_codes(file2)
    assert codes2 == ["hsa", "mmu", "eco"]


@patch('juicekeggers.commands.download_ko.urllib.request.urlopen')
def test_download_single_ko(mock_urlopen, temp_dir):
    """Test downloading single KO file."""
    # Mock successful download
    mock_response = Mock()
    mock_response.read.return_value = b"KEGG KO file content"
    mock_urlopen.return_value.__enter__.return_value = mock_response
    
    result = download_single_ko("hsa", temp_dir, max_retries=1, skip_existing=False)
    
    assert result["success"] is True
    assert result["org_code"] == "hsa"
    assert result["filepath"] is not None
    assert result["size_bytes"] == len(b"KEGG KO file content")
    
    # Check file was created
    output_file = temp_dir / "hsa00001.keg"
    assert output_file.exists()
    assert output_file.read_text() == "KEGG KO file content"
    
    # Test 404 error
    mock_response.read.return_value = b"Error not found"
    from urllib.error import HTTPError
    mock_urlopen.side_effect = HTTPError("url", 404, "Not Found", {}, None)
    
    result = download_single_ko("nonexistent", temp_dir, max_retries=1)
    assert result["success"] is False
    assert "404" in result["error"]


@patch('juicekeggers.commands.download_ko.ThreadPoolExecutor')
def test_download_ko_files(mock_executor, sample_organisms_tsv, temp_dir):
    """Test downloading multiple KO files."""
    # Mock executor
    mock_future = Mock()
    mock_future.result.return_value = {
        'org_code': 'hsa',
        'success': True,
        'error': None,
        'filepath': str(temp_dir / "hsa00001.keg"),
        'size_bytes': 100
    }
    
    mock_executor_instance = Mock()
    mock_executor_instance.__enter__.return_value.submit.return_value = mock_future
    mock_executor.return_value = mock_executor_instance
    
    result = download_ko_files(
        org_file=str(sample_organisms_tsv),
        output_dir=str(temp_dir),
        concurrent=1,
        max_retries=1
    )
    
    # Should return 0 (success) in mock scenario
    assert result in [0, 1, 2]  # Valid return codes


def test_parse_organism_file(temp_dir):
    """Test parsing organism file for protein downloads."""
    org_data = """hsa\tHuman\tftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/XXX
mmu\tMouse\thttp://example.com  # Not NCBI
eco\tE. coli\tftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/YYY
"""
    
    org_file = temp_dir / "orgs.tsv"
    org_file.write_text(org_data)
    
    result = parse_organism_file(org_file)
    
    # Should only include NCBI FTP URLs
    assert len(result) == 2  # hsa and eco
    assert result[0]["org_code"] == "hsa"
    assert result[1]["org_code"] == "eco"
    assert "ftp.ncbi.nlm.nih.gov" in result[0]["url"]
    assert "ftp.ncbi.nlm.nih.gov" in result[1]["url"]


@patch('juicekeggers.commands.download_proteins.urllib.request.urlopen')
def test_download_protein_file(mock_urlopen, temp_dir):
    """Test downloading protein file."""
    # Mock response
    mock_response = Mock()
    mock_response.read.return_value = b">protein1\nATCG\n>protein2\nGCTA"
    mock_urlopen.return_value.__enter__.return_value = mock_response
    
    organism = {
        'org_code': 'test',
        'name': 'Test organism',
        'url': 'ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/000/001/405/GCF_000001405.40'
    }
    
    result = download_protein_file(
        organism,
        temp_dir,
        format="fasta",
        max_retries=1,
        skip_existing=False
    )
    
    assert result["success"] is True
    assert result["org_code"] == "test"
    assert result["filepath"] is not None
    
    # Check file was created
    output_file = temp_dir / "test.pep.fasta"
    assert output_file.exists()


def test_command_line_interface():
    """Test that commands can be imported and have main functions."""
    # Test import of all command modules
    from juicekeggers.commands import (
        download_org, download_ko, download_proteins,
        process_proteins, makedb, make_keg, plot_keg, get_ranks
    )
    
    # Check they have main functions
    assert hasattr(download_org, 'main')
    assert hasattr(download_ko, 'main')
    assert hasattr(download_proteins, 'main')
    assert hasattr(process_proteins, 'main')
    assert hasattr(makedb, 'main')
    assert hasattr(make_keg, 'main')
    assert hasattr(plot_keg, 'main')
    assert hasattr(get_ranks, 'main')
	