"""FIREPATH-01/FIREV1: provider selection is distinct from scenario activation."""
from dataclasses import dataclass

FIRE_MODEL = 'RFDETRFireSmoke'
FIRE_NAMES = ('smoke_visible', 'flame_visible')


@dataclass(frozen=True)
class FireConfig:
    # Keep old fire.enabled meaning and payload when no scenario was requested.
    enabled: bool = False
    scenario: object | None = None

    @classmethod
    def parse(cls, value):
        if type(value) is not dict or set(value) - {'enabled', 'scenario'}:
            raise ValueError('Invalid Fire settings.')
        return cls(**value)

    def __post_init__(self):
        if type(self.enabled) is not bool:
            raise ValueError('Invalid Fire toggle.')
        if self.scenario is not None:
            from app.fire_scenario import FireScenarioConfig
            value = self.scenario
            if type(value) is dict:
                value = FireScenarioConfig.parse(value)
            if not isinstance(value, FireScenarioConfig):
                raise ValueError('Invalid Fire scenario.')
            if value.enabled and not self.enabled:
                raise ValueError('FIRE requires Fire provider.')
            object.__setattr__(self, 'scenario', value)

    @property
    def event_enabled(self):
        return self.scenario is not None and self.scenario.enabled

    def payload(self):
        value = {'enabled': self.enabled}
        if self.scenario is not None:
            value['scenario'] = self.scenario.settings_payload()
        return value

    def patched(self, changes):
        if type(changes) is not dict:
            raise ValueError('Invalid Fire settings patch.')
        value = self.payload()
        if 'scenario' in changes:
            if type(changes['scenario']) is not dict:
                raise ValueError('Invalid Fire scenario patch.')
            value['scenario'] = dict(value.get('scenario', {}), **changes['scenario'])
        value.update({k: v for k, v in changes.items() if k != 'scenario'})
        return type(self).parse(value)


def fire_plan(spec, pose_required):
    fire = FireConfig.parse(spec.get('fire', {}))
    if not fire.enabled:
        return None
    if not spec.get('server_id') or not spec.get('source_id'):
        raise ValueError('Canonical identity is required for Fire.')
    if spec.get('store', True) or spec.get('active_learning', True):
        raise ValueError('Fire storage/Active Learning is not supported yet.')
    if spec.get('scenarios', 'off') not in ('off', None, []):
        raise ValueError('Use canonical fire.scenario, not legacy scenario registry.')
    categories = (spec.get('visualization') or {}).get('categories')
    if categories is not None and any(k not in FIRE_NAMES for k in categories):
        raise ValueError('Fire cannot supply requested person/other categories.')
    return dict(category='fire_smoke', model=FIRE_MODEL, role='det', outputs=['bbox'])


def scenario_enabled(spec):
    return FireConfig.parse(spec.get('fire', {})).event_enabled


def build_engine(spec):
    fire = FireConfig.parse(spec.get('fire', {}))
    if not fire.event_enabled:
        return None
    from app.fire_scenario import Fire
    return Fire(fire.scenario)


def project_fire(spec, scenarios):
    """Project FIRE event/ROI only; provider selection is owned by provider_plan."""
    requested = next(s for s in scenarios if s['scenarioCode'] == 'FIRE')
    current = FireConfig.parse(spec.get('fire', {}))
    if not requested['enabled'] and not current.event_enabled:
        return
    from app.fire_scenario import FireScenarioConfig
    cfg = (current.scenario.settings_payload() if current.scenario
           else FireScenarioConfig().settings_payload())
    roi = requested['rois'][0] if requested['rois'] else None
    cfg.update(enabled=requested['enabled'],
               roi=roi['points'] if roi else [],
               roi_name=roi['label'] if roi else 'Fire ROI')
    spec['fire'] = FireConfig(enabled=requested['enabled'], scenario=cfg).payload()
