import dataclasses
import json
from typing import List, Dict, Any, Tuple, Optional
@dataclasses.dataclass
class FileRule:
    file_path: str = None
    item_type: str = None # Base type determined by classification (e.g., MAP_COL, EXTRA)
    item_type_override: str = None # Renamed from map_type_override
    target_asset_name_override: str = None
    resolution_override: Tuple[int, int] = None
    channel_merge_instructions: Dict[str, Any] = dataclasses.field(default_factory=dict)
    output_format_override: str = None

    def to_json(self) -> str:
        return json.dumps(dataclasses.asdict(self), indent=4)

    @classmethod
    def from_json(cls, json_string: str) -> 'FileRule':
        data = json.loads(json_string)
        return cls(**data)

@dataclasses.dataclass
class AssetRule:
    asset_name: str = None
    asset_type: str = None # Predicted type
    asset_type_override: str = None
    common_metadata: Dict[str, Any] = dataclasses.field(default_factory=dict)
    files: List[FileRule] = dataclasses.field(default_factory=list)

    def to_json(self) -> str:
        return json.dumps(dataclasses.asdict(self), indent=4)

    @classmethod
    def from_json(cls, json_string: str) -> 'AssetRule':
        data = json.loads(json_string)
        # Manually deserialize nested FileRule objects
        data['files'] = [FileRule.from_json(json.dumps(file_data)) for file_data in data.get('files', [])]
        return cls(**data)

@dataclasses.dataclass
class SourceRule:
    supplier_identifier: str = None # Predicted/Original identifier
    supplier_override: str = None
    high_level_sorting_parameters: Dict[str, Any] = dataclasses.field(default_factory=dict)
    assets: List[AssetRule] = dataclasses.field(default_factory=list)
    input_path: str = None
    preset_name: str = None

    def to_json(self) -> str:
        return json.dumps(dataclasses.asdict(self), indent=4)

    @classmethod
    def from_json(cls, json_string: str) -> 'SourceRule':
        data = json.loads(json_string)
        # Manually deserialize nested AssetRule objects
        data['assets'] = [AssetRule.from_json(json.dumps(asset_data)) for asset_data in data.get('assets', [])]
        return cls(**data)