import os
import unittest
from unittest.mock import patch
from deployment_kit.models import profile, pbtxt, trtexec_args
from app.fall_runtime import FallSettings, project_fall


class SiteIncrementalTests(unittest.TestCase):
    def test_crowd_resolution_contract(self):
        p = profile('crowd')
        self.assertEqual(p['resolution'], 512)
        self.assertEqual(p['outputs'], dict(dets=[300, 4], labels=[300, 3]))
        self.assertIn('dims: [3, 512, 512]', pbtxt(p))
        self.assertIn('--maxShapes=input:4x3x512x512', trtexec_args(p))
        self.assertNotIn(',\n]', pbtxt(p))

    def test_legacy_resolution_unchanged(self):
        for key in ('medium', 'pose', 'fire'):
            p = profile(key)
            self.assertEqual(p['resolution'], 576)
            self.assertIn('dims: [3, 576, 576]', pbtxt(p))

    def test_global_default_off(self):
        with patch.dict(os.environ, {}, clear=True):
            self.assertFalse(FallSettings.parse({}).policy.test_skip_down_hold)

    def test_site_default_and_explicit_off(self):
        with patch.dict(os.environ, CONTEXTRA_FALL_SKIP_DOWN_HOLD_DEFAULT='true'):
            self.assertTrue(FallSettings.parse({}).policy.test_skip_down_hold)
            self.assertFalse(FallSettings.parse({'test_skip_down_hold': False}).policy.test_skip_down_hold)

    def test_web_preserves_explicit_and_applies_absent(self):
        request = [dict(scenarioCode='FALL', enabled=True, confidence=.3, rois=[])]
        with patch.dict(os.environ, CONTEXTRA_FALL_SKIP_DOWN_HOLD_DEFAULT='true'):
            for original, expected in [({}, True), ({'fall': {'test_skip_down_hold': False}}, False)]:
                project_fall(original, request)
                self.assertEqual(original['fall']['test_skip_down_hold'], expected)
                project_fall(original, request)
                self.assertEqual(original['fall']['test_skip_down_hold'], expected)

    def test_invalid_site_default_rejected(self):
        with patch.dict(os.environ, CONTEXTRA_FALL_SKIP_DOWN_HOLD_DEFAULT='invalid'):
            with self.assertRaises(ValueError):
                FallSettings.parse({})
