from math import isfinite

def _num(x): return isinstance(x,(int,float)) and not isinstance(x,bool) and isfinite(x)
def _r(x): return round(float(x)+0.0,2)

def _out(state, vals, reason):
    keys=['annual_ownership_cost','power_cost','total_relevant_cost','idle_capacity','useful_work_units','unit_cost']
    d={'decision_state':state}
    for k in keys: d[k]=None if vals is None else vals.get(k)
    d['reason_code']=reason
    return d

def evaluate(c):
    decisive=['asset_id','capacity_unit','acquisition_cost','sunk_cost','remaining_value','replacement_horizon','depreciation_basis','license_cost','support_cost','power_kw','energy_rate','facility_cost','maintenance_cost','utilization_pct','full_capacity_units','useful_work_units','measurement_period','allocated_shared_cost','max_unit_cost','min_utilization_pct','sensitivity_driver','evidence_ref']
    if any(c.get(k) in (None,'',[]) for k in decisive): return _out('HOLD',None,'DECISIVE_EVIDENCE_MISSING')
    nums=['acquisition_cost','sunk_cost','remaining_value','replacement_horizon','depreciation_basis','license_cost','support_cost','power_kw','energy_rate','facility_cost','maintenance_cost','utilization_pct','full_capacity_units','useful_work_units','allocated_shared_cost','max_unit_cost','min_utilization_pct']
    if any(not _num(c.get(k)) for k in nums): return _out('HOLD',None,'INVALID_NUMERIC_EVIDENCE')
    if c['measurement_period']!='ANNUAL' or c['replacement_horizon']<=0 or c['full_capacity_units']<=0 or c['useful_work_units']<=0: return _out('HOLD',None,'INVALID_PERIOD_OR_DENOMINATOR')
    if any(c[k] < 0 for k in ['acquisition_cost','sunk_cost','remaining_value','depreciation_basis','license_cost','support_cost','power_kw','energy_rate','facility_cost','maintenance_cost','allocated_shared_cost']): return _out('HOLD',None,'NEGATIVE_COST_EVIDENCE')
    if not (0 < c['utilization_pct'] <= 100) or not (0 <= c['min_utilization_pct'] <= 100): return _out('HOLD',None,'INVALID_UTILIZATION_EVIDENCE')
    if c['sunk_cost'] > c['acquisition_cost']+1e-9: return _out('DISPUTED',None,'SUNK_EXCEEDS_ACQUISITION')
    if c.get('support_avoidable') is True and c.get('support_treatment')=='SUNK': return _out('DISPUTED',None,'AVOIDABLE_SUPPORT_MISCLASSIFIED_AS_SUNK')
    if c.get('shared_cost_scope')!='COMPUTE_POOL_ONLY': return _out('DISPUTED',None,'SHARED_COST_SCOPE_MISMATCH')
    expected=c['full_capacity_units']*c['utilization_pct']/100.0
    if abs(expected-c['useful_work_units']) > max(0.5, expected*0.001): return _out('DISPUTED',None,'USEFUL_WORK_DENOMINATOR_MISMATCH')
    annual_ownership=max(c['depreciation_basis']-c['remaining_value'],0)/c['replacement_horizon']
    power=c['power_kw']*8760*c['energy_rate']
    total=annual_ownership+c['license_cost']+c['support_cost']+power+c['facility_cost']+c['maintenance_cost']+c['allocated_shared_cost']
    unit=total/c['useful_work_units']
    vals={'annual_ownership_cost':_r(annual_ownership),'power_cost':_r(power),'total_relevant_cost':_r(total),'idle_capacity':_r(100-c['utilization_pct']),'useful_work_units':_r(c['useful_work_units']),'unit_cost':_r(unit)}
    if c['utilization_pct']+1e-9 < c['min_utilization_pct']: return _out('RESIZE',vals,'UTILIZATION_BELOW_GOVERNED_MINIMUM')
    if unit > c['max_unit_cost']+1e-9: return _out('REPRICE',vals,'UNIT_COST_ABOVE_GOVERNED_CEILING')
    return _out('LOCAL_OK',vals,'BOUNDED_LOCAL_COST_WITHIN_DECLARED_LIMITS')
