from copy import deepcopy
import pytest
from fall_r2_settings import migrate_spec,migrate_document
from install import updated_bindings

def test_migration_preserves_other_scenarios_and_idempotence():
    old=dict(uri='rtsp://fixture.invalid/video',fall=dict(enabled=True,person_score=.15,joint_score=.3),
             fight=dict(engine='r5',person_score=.35),event_cooldowns={'FALL':10.,'FIGHT':10.},arbitrary=[1,2])
    saved=deepcopy(old);new=migrate_spec(old)
    assert old==saved and new['fall']['enabled'] and new['fall']['engine']=='r2'
    assert (new['fall']['person_score'],new['fall']['joint_score'])==(.25,.3)
    assert {k:v for k,v in new.items() if k!='fall'}=={k:v for k,v in old.items() if k!='fall'}
    assert migrate_spec(new)==new

def test_new_channel_defaults_and_higher_values():
    new=migrate_spec({'fight':{'engine':'r5'}})
    assert not new['fall']['enabled'] and new['event_cooldowns']['FALL']==10
    assert (new['fall']['person_score'],new['fall']['joint_score'])==(.25,.1)
    new=migrate_spec({'fall':dict(enabled=False,person_score=.8,joint_score=.5)})
    assert (new['fall']['person_score'],new['fall']['joint_score'])==(.8,.5)

def test_migration_error_is_not_a_default_reset():
    for value in (None,True,5,11,'10'):
        old={'event_cooldowns':{'FALL':value}}
        with pytest.raises(ValueError):migrate_spec(old)
        assert old=={'event_cooldowns':{'FALL':value}}

def test_document_scope_and_cas():
    old={'added':[{'fall':{'enabled':False}}],'removed':['unchanged']}
    new=migrate_document(old,'runtime');assert new['removed']==old['removed']
    records={'/data/config':{'directory':{'runtime.yaml':'old'}},'/data/config/runtime.yaml':'old'}
    change=dict(path='/data/config/runtime.yaml',before='old',after='new',changed=True)
    new=updated_bindings(records,[change]);assert new['/data/config/runtime.yaml']=='new'
    assert records['/data/config/runtime.yaml']=='old'
    with pytest.raises(ValueError):updated_bindings(records,[dict(change,before='wrong')])
