"""CROWD admission guards and side-effect-free future Runtime projection seams.

No boolean flag can bypass the predevelopment gate. Removing the gate requires
an explicitly reviewed Runtime change after actual model/export verification.
"""
from copy import deepcopy

from app.crowd_config import CROWD_MODEL, CrowdConfig, FULL_FRAME

MODEL_PENDING = 'CROWD_NEEDS_MODEL_CONTRACT_CONFIRMATION'
STANDALONE_REQUIRED = 'CROWD_STANDALONE_REQUIRED'
TRACKING_UNSUPPORTED = 'CROWD_TRACKING_UNSUPPORTED'


def _request(scenarios):
    found = [s for s in scenarios if s.get('scenarioCode') == 'CROWD']
    if len(found) != 1:
        raise ValueError('CROWD_REQUEST_REQUIRED')
    request = found[0]
    if type(request.get('enabled')) is not bool:
        raise ValueError('CROWD_INVALID_ENABLED')
    return request


def validate_web_request(scenarios):
    """Six-scenario snapshot validation; coexistence is owned by provider_plan."""
    _request(scenarios)


def validate_standalone(spec, config):
    """Compatibility name: validate CROWD identity only, not standalone ownership."""
    if config.enabled and (not spec.get('server_id') or not spec.get('source_id')):
        raise ValueError('CROWD_CANONICAL_IDENTITY_REQUIRED')


def crowd_plan(spec):
    raw = spec.get('crowd')
    config = CrowdConfig.parse({} if raw is None else raw)
    if not config.enabled:
        return None
    validate_standalone(spec, config)
    return dict(category='crowd', model=CROWD_MODEL, role='det', outputs=['bbox'])


def project_crowd_candidate(spec, scenarios):
    """Project CROWD settings without taking ownership of global Tracking/profile."""
    request = _request(scenarios)
    candidate = deepcopy(spec)
    if not request['enabled'] and 'crowd' not in candidate:
        return candidate
    current = CrowdConfig.parse(candidate.get('crowd') or {})
    rois = request.get('rois') or []
    first = rois[0] if rois else None
    changes = dict(enabled=request['enabled'],
                   roi=first['points'] if first else FULL_FRAME,
                   roi_name=first['label'] if first else 'Crowd ROI')
    configured = current.patched(changes)
    candidate['crowd'] = configured.settings_payload()
    validate_standalone(candidate, configured)
    return candidate

def patch_crowd_candidate(spec, changes):
    """Private configuration helper; no HTTP/CAS/persistence side effects."""
    current = CrowdConfig.parse(spec.get('crowd') or {})
    configured = current.patched(changes)
    candidate = deepcopy(spec)
    if configured != current:
        candidate['crowd'] = configured.settings_payload()
    validate_standalone(candidate, configured)
    return candidate
