"""
Parsers for various file formats
"""
import logging
from pathlib import Path
from typing import Dict, List, Optional, Union

from .polars_utils import POLARS_AVAILABLE

LOG = logging.getLogger(__name__)


def parse_org_file(filepath: Union[str, Path]) -> List[Dict]:
    """
    Parse KEGG organism file.
    
    Format: org_code\tname\turl
    """
    filepath = Path(filepath)
    data = []
    
    with open(filepath, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            line = line.strip()
            if not line or line.startswith('#'):
                continue
            
            parts = line.split('\t')
            if len(parts) >= 3:
                data.append({
                    'org_code': parts[0],
                    'name': parts[1],
                    'url': parts[2],
                    'line_number': line_num
                })
            elif len(parts) == 2:
                data.append({
                    'org_code': parts[0],
                    'name': parts[1],
                    'url': '',
                    'line_number': line_num
                })
            else:
                LOG.warning(f"Line {line_num}: Invalid format: {line}")
    
    LOG.info(f"Parsed {len(data)} organisms from {filepath}")
    return data


def parse_kegg_file(filepath: Union[str, Path]) -> List[Dict]:
    """
    Parse KEGG .keg file.
    
    Returns list of entries with their KOs and pathways.
    """
    filepath = Path(filepath)
    data = []
    
    current_pathway = None
    current_ko = None
    
    with open(filepath, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            line = line.strip()
            if not line:
                continue
            
            # Pathway line
            if line.startswith('C'):
                # Format: C   PATH: koXXXXX
                parts = line.split()
                if len(parts) >= 2 and parts[1].startswith('PATH:'):
                    current_pathway = parts[1].replace('PATH:', '')
                continue
            
            # KO line
            if line.startswith('D'):
                parts = line.split('\t')
                if len(parts) >= 2:
                    # Format: D      GENE_ID\tKO_NAME DESCRIPTION
                    gene_part = parts[0].split()
                    if len(gene_part) >= 2:
                        gene_id = gene_part[1]
                        
                        ko_info = parts[1].split() if len(parts) > 1 else []
                        if ko_info:
                            ko_id = ko_info[0]
                            ko_desc = ' '.join(ko_info[1:]) if len(ko_info) > 1 else ''
                        else:
                            ko_id = '-'
                            ko_desc = ''
                        
                        data.append({
                            'gene_id': gene_id,
                            'ko_id': ko_id,
                            'ko_description': ko_desc,
                            'pathway': current_pathway,
                            'line_number': line_num
                        })
    
    LOG.info(f"Parsed {len(data)} entries from {filepath}")
    return data


def parse_ko_file(filepath: Union[str, Path]) -> Dict[str, List[Dict]]:
    """
    Parse KO file into organized structure.
    
    Returns: {pathway_id: [{gene_id, ko_id, ko_description}]}
    """
    filepath = Path(filepath)
    result = {}
    
    entries = parse_kegg_file(filepath)
    
    for entry in entries:
        pathway = entry.get('pathway')
        if not pathway:  # Skip entries without pathway
            continue
            
        if pathway not in result:
            result[pathway] = []
        
        result[pathway].append({
            'gene_id': entry['gene_id'],
            'ko_id': entry['ko_id'],
            'ko_description': entry['ko_description']
        })
    
    return result


def parse_ko_file_to_gene_dict(filepath: Union[str, Path]) -> Dict[str, Dict[str, List[str]]]:
    """
    Parse KO file into gene-centric structure.
    
    Returns: {gene_id: {"ko": [ko_ids], "pathway": [pathway_ids]}}
    """
    filepath = Path(filepath)
    result = {}
    
    current_pathway = None
    total_lines = 0
    genes_with_ko = 0
    genes_without_ko = 0
    
    with open(filepath, 'r', encoding='utf-8') as f:
        for line_num, line in enumerate(f, 1):
            line = line.strip()
            if not line:
                continue
            
            total_lines += 1
            
            # Pathway line (C)
            if line.startswith('C'):
                # Format: C   PATH: koXXXXX
                parts = line.split()
                if len(parts) >= 2 and parts[1].startswith('PATH:'):
                    current_pathway = parts[1].replace('PATH:', '')
                    LOG.debug(f"Found pathway: {current_pathway}")
                continue
            
            # Gene line (D)
            if line.startswith('D'):
                parts = line.split('\t')
                if len(parts) >= 2:
                    # Format: D      GENE_ID\tKO_NAME DESCRIPTION
                    gene_part = parts[0].split()
                    if len(gene_part) >= 2:
                        gene_id = gene_part[1].strip()
                        
                        ko_info = parts[1].split() if len(parts) > 1 else []
                        if ko_info:
                            ko_id = ko_info[0].strip()
                        else:
                            ko_id = '-'
                        
                        # Skip if KO is just a dash or empty
                        if ko_id != '-' and ko_id:
                            if gene_id not in result:
                                result[gene_id] = {"ko": [], "pathway": []}
                            
                            if ko_id not in result[gene_id]["ko"]:
                                result[gene_id]["ko"].append(ko_id)
                            
                            if current_pathway and current_pathway not in result[gene_id]["pathway"]:
                                result[gene_id]["pathway"].append(current_pathway)
                            
                            genes_with_ko += 1
                            LOG.debug(f"Gene {gene_id} -> KO {ko_id} in pathway {current_pathway}")
                        else:
                            genes_without_ko += 1
                            LOG.debug(f"Gene {gene_id} has no KO (ko_id='{ko_id}')")
    
    LOG.info(f"Parsed {len(result)} genes with KO annotations from {filepath}")
    LOG.info(f"  Total D lines: {total_lines}")
    LOG.info(f"  Genes with KO: {genes_with_ko}")
    LOG.info(f"  Genes without KO: {genes_without_ko}")
    
    # Debug: Show first few entries
    if result:
        LOG.debug(f"First 5 gene-KO mappings:")
        for i, (gene_id, data) in enumerate(list(result.items())[:5]):
            LOG.debug(f"  {gene_id}: KOs={data['ko']}, Pathways={data['pathway']}")
    else:
        LOG.warning(f"No gene-KO mappings found in {filepath}")
    
    return result


def parse_pathway_file(filepath: Union[str, Path]) -> Dict:
    """
    Parse KEGG pathway file.
    """
    filepath = Path(filepath)
    data = {}
    
    with open(filepath, 'r', encoding='utf-8') as f:
        current_section = None
        current_data = []
        
        for line in f:
            line = line.strip()
            if not line:
                continue
            
            # Section header
            if line.startswith('###'):
                # Save previous section
                if current_section:
                    data[current_section] = current_data
                
                current_section = line[3:].strip()
                current_data = []
            else:
                current_data.append(line)
        
        # Save last section
        if current_section:
            data[current_section] = current_data
    
    return data


def parse_compound_file(filepath: Union[str, Path]) -> List[Dict]:
    """
    Parse KEGG compound file.
    """
    filepath = Path(filepath)
    data = []
    current_entry = {}
    
    with open(filepath, 'r', encoding='utf-8') as f:
        for line in f:
            line = line.strip()
            if not line:
                # End of entry
                if current_entry:
                    data.append(current_entry)
                    current_entry = {}
                continue
            
            # Entry line
            if line.startswith('ENTRY'):
                parts = line.split(None, 2)
                if len(parts) >= 2:
                    current_entry['entry'] = parts[1]
            elif line.startswith('NAME'):
                name = line[4:].strip()
                if 'name' in current_entry:
                    current_entry['name'] += '; ' + name
                else:
                    current_entry['name'] = name
            elif line.startswith('FORMULA'):
                current_entry['formula'] = line[7:].strip()
            elif line.startswith('EXACT_MASS'):
                current_entry['exact_mass'] = line[10:].strip()
            elif line.startswith('MOL_WEIGHT'):
                current_entry['mol_weight'] = line[10:].strip()
            elif line.startswith('REMARK'):
                if 'remark' not in current_entry:
                    current_entry['remark'] = []
                current_entry['remark'].append(line[6:].strip())
    
    # Don't forget the last entry
    if current_entry:
        data.append(current_entry)
    
    LOG.info(f"Parsed {len(data)} compounds from {filepath}")
    return data
    