# app/compile/format_compiler.py
"""Format compilation module for converting custom formats"""
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Optional
import json
import yaml

from .mappings import TargetApp, ValueResolver


@dataclass
class Specification:
    """Data class for format specifications"""
    name: str
    implementation: str
    negate: bool = False
    required: bool = False
    fields: List[Dict[str, str]] = None

    def __post_init__(self):
        if self.fields is None:
            self.fields = []


@dataclass
class CustomFormat:
    """Data class for custom format definitions"""
    name: str
    description: str
    tags: List[str]
    conditions: List[Dict]
    tests: List[Dict]


@dataclass
class ConvertedFormat:
    """Data class for converted format output"""
    name: str
    specifications: List[Specification]


class FormatConverter:
    """Converts between different format types"""

    def __init__(self, patterns: Dict[str, str]):
        self.patterns = patterns

    def _create_specification(
            self, condition: Dict,
            target_app: TargetApp) -> Optional[Specification]:
        condition_type = condition['type']

        if condition_type in ['release_title', 'release_group', 'edition']:
            pattern_name = condition['pattern']
            pattern = self.patterns.get(pattern_name)
            if not pattern:
                return None
            implementation = ('ReleaseTitleSpecification'
                              if condition_type == 'release_title' else
                              'ReleaseGroupSpecification' if condition_type
                              == 'release_group' else 'EditionSpecification')
            fields = [{'name': 'value', 'value': pattern}]

        elif condition_type == 'source':
            implementation = 'SourceSpecification'
            value = ValueResolver.get_source(condition['source'], target_app)
            fields = [{'name': 'value', 'value': value}]

        elif condition_type == 'resolution':
            implementation = 'ResolutionSpecification'
            value = ValueResolver.get_resolution(condition['resolution'])
            fields = [{'name': 'value', 'value': value}]

        elif condition_type == 'indexer_flag':
            implementation = 'IndexerFlagSpecification'
            value = ValueResolver.get_indexer_flag(condition.get('flag', ''),
                                                   target_app)
            fields = [{'name': 'value', 'value': value}]

        elif condition_type == 'quality_modifier':
            if target_app == TargetApp.SONARR:
                return None
            implementation = 'QualityModifierSpecification'
            value = ValueResolver.get_quality_modifier(
                condition['qualityModifier'])
            fields = [{'name': 'value', 'value': value}]

        elif condition_type == 'size':
            implementation = 'SizeSpecification'
            min_size = condition.get('minSize')
            max_size = condition.get('maxSize')
            fields = [{
                'name': 'min',
                'value': min_size
            }, {
                'name': 'max',
                'value': max_size
            }]

        elif condition_type == 'year':
            implementation = 'YearSpecification'
            min_year = condition.get('minYear')
            max_year = condition.get('maxYear')
            fields = [{
                'name': 'min',
                'value': min_year
            }, {
                'name': 'max',
                'value': max_year
            }]

        elif condition_type == 'release_type':
            if target_app == TargetApp.RADARR:
                return None
            implementation = 'ReleaseTypeSpecification'
            value = ValueResolver.get_release_type(condition['releaseType'])
            fields = [{'name': 'value', 'value': value}]

        elif condition_type == 'language':
            implementation = 'LanguageSpecification'
            language_name = condition['language'].lower()
            try:
                language_data = ValueResolver.get_language(language_name,
                                                           target_app,
                                                           for_profile=False)
                fields = [{'name': 'value', 'value': language_data['id']}]
                if 'exceptLanguage' in condition:
                    except_value = condition['exceptLanguage']
                    fields.append({
                        'name': 'exceptLanguage',
                        'value': except_value
                    })
            except Exception:
                return None

        else:
            return None

        return Specification(name=condition.get('name', ''),
                             implementation=implementation,
                             negate=condition.get('negate', False),
                             required=condition.get('required', False),
                             fields=fields)

    def convert_format(self, custom_format: CustomFormat,
                       target_app: TargetApp) -> ConvertedFormat:
        specifications = []
        for condition in custom_format.conditions:
            try:
                spec = self._create_specification(condition, target_app)
                if spec:
                    specifications.append(spec)
            except Exception:
                continue

        return ConvertedFormat(name=custom_format.name,
                               specifications=specifications)


class FormatProcessor:
    """Main class for processing format files"""

    def __init__(self, input_dir: Path, output_dir: Path, patterns_dir: Path):
        self.input_dir = input_dir
        self.output_dir = output_dir
        self.patterns = self._load_patterns(patterns_dir)
        self.converter = FormatConverter(self.patterns)

    @staticmethod
    def _load_patterns(patterns_dir: Path) -> Dict[str, str]:
        patterns = {}
        for file_path in patterns_dir.glob('*.yml'):
            with file_path.open('r') as f:
                pattern_data = yaml.safe_load(f)
                patterns[pattern_data['name']] = pattern_data['pattern']
        return patterns

    def _load_custom_format(self, format_name: str) -> Optional[CustomFormat]:
        format_path = self.input_dir / f"{format_name}.yml"
        if not format_path.exists():
            return None

        with format_path.open('r') as f:
            raw_data = yaml.safe_load(f)
            return CustomFormat(**raw_data)

    def process_format(self,
                       format_name: str,
                       target_app: TargetApp,
                       return_data: bool = False) -> Optional[ConvertedFormat]:
        custom_format = self._load_custom_format(format_name)
        if not custom_format:
            return None

        converted_format = self.converter.convert_format(
            custom_format, target_app)

        output_data = [{
            'name':
            converted_format.name,
            'specifications':
            [vars(spec) for spec in converted_format.specifications]
        }]

        if not return_data:
            output_path = self.output_dir / f"{format_name}.json"
            with output_path.open('w') as f:
                json.dump(output_data, f, indent=2)

        return converted_format


def compile_custom_format(format_data: Dict) -> List[Dict]:
    custom_format = CustomFormat(**format_data)
    patterns = {}
    converter = FormatConverter(patterns)
    converted = converter.convert_format(custom_format, TargetApp.RADARR)
    output_data = [{
        'name':
        converted.name,
        'specifications': [vars(spec) for spec in converted.specifications]
    }]
    return output_data
