"""R5-SITE-DEFAULT-01: preserve every non-FIGHT value during site migration."""
from copy import deepcopy
import hashlib
import json
from pathlib import Path
import sys

import yaml


def migrate_spec(spec):
    from app.fight_runtime import FightSettings
    if not isinstance(spec, dict):
        raise ValueError('R5_SPEC_MAPPING_REQUIRED')
    candidate = deepcopy(spec)
    old = spec.get('fight')
    if old is None:
        old = {}
    if not isinstance(old, dict):
        raise ValueError('R5_FIGHT_MAPPING_REQUIRED')
    candidate['fight'] = FightSettings.parse(dict(old, engine='r5')).settings_payload()
    if candidate['fight']['enabled'] != old.get('enabled', False):
        raise ValueError('R5_ENABLED_CHANGED')
    return candidate


def migrate_document(value, kind):
    if not isinstance(value, dict):
        raise ValueError('R5_CONFIG_MAPPING_REQUIRED')
    if kind == 'template':
        return migrate_spec(value)
    key = {'base': 'streams', 'runtime': 'added'}[kind]
    if not isinstance(value.get(key), list):
        raise ValueError('R5_CONFIG_LIST_REQUIRED')
    result = deepcopy(value)
    result[key] = [migrate_spec(spec) for spec in value[key]]
    return result


def prepare(root):
    root = Path(root)
    plan = json.loads((root / 'settings-inputs.json').read_text())
    output = root / 'settings-after'
    output.mkdir(mode=0o700)
    changes = []
    for entry in plan:
        raw = (root / 'settings-before' / entry['name']).read_bytes()
        if hashlib.sha256(raw).hexdigest() != entry['before']:
            raise ValueError('R5_SETTINGS_COPY_CHANGED')
        old = json.loads(raw) if entry['format'] == 'json' else yaml.safe_load(raw)
        new = migrate_document(old, entry['kind'])
        if old == new:
            encoded = raw
        elif entry['format'] == 'json':
            encoded = (json.dumps(new, indent=2, ensure_ascii=False) + '\n').encode()
        else:
            encoded = yaml.safe_dump(new, allow_unicode=True, sort_keys=False).encode()
        target = output / entry['name']
        target.write_bytes(encoded)
        target.chmod(0o600)
        specs = [new] if entry['kind'] == 'template' else new[{'base':'streams','runtime':'added'}[entry['kind']]]
        changes.append(dict(entry, after=hashlib.sha256(encoded).hexdigest(), changed=raw!=encoded,
                            count=len(specs), r5_count=sum(s['fight']['engine']=='r5' for s in specs)))
    (root / 'settings-migration.json').write_text(json.dumps(changes, indent=2) + '\n')
    print(json.dumps({entry['kind']:dict(count=entry['count'],r5_count=entry['r5_count'],changed=entry['changed']) for entry in changes}))


if __name__ == '__main__':
    prepare(sys.argv[1])
