"""Closed failure propagation through remote output, transport and the public CLI."""
from contextlib import redirect_stdout
import io
import json
import sys
import unittest
from unittest.mock import patch
from test_identity_diagnostics import READER, SINCE


class IdentityFailures(unittest.TestCase):
    def test_every_fixed_remote_refusal_survives_the_ssh_exit(self):
        args = type('Args', (), dict(app='fixture', service='api', since=SINCE, host='fixture.invalid', user='root'))()
        for code in READER.FAILURES:
            raw = json.dumps({'schema': READER.SCHEMA, 'ok': False, 'failure': code, 'records': []}).encode()
            with self.subTest(code=code), patch.object(READER, 'bounded', return_value=(1, raw)) as run:
                with self.assertRaises(READER.ReaderFailure) as failure:
                    READER.local(args)
                self.assertEqual(failure.exception.code, code)
                self.assertTrue(run.call_args.kwargs['with_status'])

    def test_transport_and_unknown_refusals_never_export_raw_values(self):
        for status, raw, expected in [(255, b'PRIVATE_SENTINEL', 'transport_failure'),
                (1, b'PRIVATE_SENTINEL', 'remote_invalid'),
                (1, json.dumps({'schema': READER.SCHEMA, 'ok': False,
                    'failure': 'PRIVATE_SENTINEL', 'records': []}).encode(), 'unclassified')]:
            with self.assertRaises(READER.ReaderFailure) as failure:
                READER.decode_remote(status, raw)
            self.assertEqual(failure.exception.code, expected)
            self.assertNotIn('PRIVATE_SENTINEL', str(failure.exception))

    def test_nonzero_process_keeps_only_validated_structured_refusal(self):
        payload = json.dumps({'schema': READER.SCHEMA, 'ok': False,
                              'failure': 'container_scope_mismatch', 'records': []})
        status, raw = READER.bounded([sys.executable, '-c',
            'import sys; print(sys.argv[1]); print("PRIVATE_SENTINEL", file=sys.stderr); sys.exit(1)', payload],
            with_status=True)
        with self.assertRaisesRegex(READER.ReaderFailure, '^container_scope_mismatch$'):
            READER.decode_remote(status, raw)
        self.assertNotIn(b'PRIVATE_SENTINEL', raw)

    def test_cli_known_and_unknown_errors_produce_closed_failure_envelopes(self):
        argv = ['reader', '--remote', '--app', 'fixture', '--service', 'api', '--since', SINCE]
        for error, expected in [(READER.ReaderFailure('command_timeout'), 'command_timeout'),
                                (RuntimeError('PRIVATE_SENTINEL'), 'unclassified')]:
            output = io.StringIO()
            with patch.object(sys, 'argv', argv), patch.object(READER, 'remote', side_effect=error), \
                    redirect_stdout(output):
                self.assertEqual(READER.main(), 1)
            self.assertEqual(json.loads(output.getvalue()), {
                'schema': READER.SCHEMA, 'ok': False, 'failure': expected, 'records': []})
            self.assertNotIn('PRIVATE_SENTINEL', output.getvalue())


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