import json
import os
from pathlib import Path
import tempfile
import unittest
from unittest.mock import patch
from app.metadata_samples import MetadataSamples


class MetadataSamplesTest(unittest.TestCase):
    def test_opt_in_exact_payload_cap_permissions_and_disable(self):
        with tempfile.TemporaryDirectory() as root:
            path = Path(root)
            sample = MetadataSamples(root)
            value = {'frameSeq': 0, 'objects': [{'visible': True, 'trackId': 1}]}
            sample.capture(value)
            self.assertEqual(list(path.iterdir()), [])
            (path/'capture.enabled').touch(mode=0o600)
            for i in range(5):
                value['frameSeq'] = i
                sample.capture(value)
            self.assertEqual(len(list(path.glob('sample-*.json'))), 3)
            self.assertEqual(json.loads((path/'sample-1.json').read_text())['frameSeq'], 0)
            self.assertEqual((path/'sample-1.json').stat().st_mode & 0o777, 0o600)
            before = (path/'sample-1.json').read_bytes()
            MetadataSamples(root).capture(value)
            self.assertEqual((path/'sample-1.json').read_bytes(), before)
            (path/'capture.enabled').unlink()
            self.assertIsNone(sample.error)

    def test_environment_default_off_and_unsafe_directory(self):
        with patch.dict(os.environ, {}, clear=True):
            self.assertIsNone(MetadataSamples.from_environment())
        with self.assertRaises(ValueError):
            MetadataSamples('relative')

    def test_empty_first_frame_then_only_visible_and_error_is_bounded(self):
        with tempfile.TemporaryDirectory() as root:
            path = Path(root)
            (path/'capture.enabled').touch(mode=0o600)
            sample = MetadataSamples(root)
            sample.capture({'objects': []})
            sample.capture({'objects': []})
            self.assertEqual(sample.attempts, 1)
            sample.capture({'objects': [{'visible': True}], 'data': 'x' * 140000})
            self.assertEqual(sample.error, 'SAMPLE_TOO_LARGE')


if __name__ == '__main__':
    unittest.main()
