"""Retain useful dependency conflicts without leaking child credentials or a truncated tail."""
import io
import unittest
from native_pods_diagnostics import diagnostic


class DiagnosticsTests(unittest.TestCase):
    def test_versions_survive_while_current_env_and_generic_credentials_are_removed(self):
        environment = {"OWNED_SERVICE_CREDENTIAL": "http://owned-user:private-password@service.invalid:8000",
                       "GITHUB_TOKEN": "private-github-token", "PUBLIC_SETTING": "allowed"}
        body = ('[!] CocoaPods could not find compatible versions for pod "Firebase/CoreOnly":\n'
                'In snapshot (Podfile.lock): Firebase/CoreOnly (= 11.9.0)\n'
                'In Podfile: Firebase/CoreOnly (= 11.8.0)\n'
                'owned-user private-password private-github-token\n'
                'https://owned-user:private-password@proxy.invalid:8000\n'
                'Proxy-Authorization: Basic cHJpdmF0ZTpwYXNzd29yZA==\n'
                '{"private_key":"PRIVATE_JSON_MARKER", "access_token":"PRIVATE_ACCESS_MARKER"}\n'
                'abcDef0123456789_abcDef0123456789_SECRET\n')
        result = diagnostic(io.BytesIO(body.encode()), environment)
        self.assertIn('Firebase/CoreOnly (= 11.9.0)', result)
        self.assertIn('Firebase/CoreOnly (= 11.8.0)', result)
        for private in ('owned-user', 'private-password', 'private-github-token', 'https://',
                        'cHJpdmF0ZTpwYXNzd29yZA==', 'PRIVATE_JSON_MARKER', 'PRIVATE_ACCESS_MARKER', 'SECRET'):
            self.assertNotIn(private, result)

    def test_error_codes_survive_while_opaque_runs_of_the_same_length_do_not(self):
        """The classifier reads the plugin's own code back out of this text, and
        thirteen of the twenty-seven are 32 characters or more. Task 1185's iOS
        failure published `"code": "[long value redacted]"` with an empty
        `signals` list because the catch-all erased it (2026-09-09)."""
        body = ('{"code": "native_podfile_lock_commit_required", "ok": false}\n'
                'native_google_transport_helper_required native_pods_operation_unverified\n'
                'digest 9f2b7c1e4a8d3b6f0c5e2a9d7b4f1c8e3a6d0b5f were removed\n'
                'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQ==\n'
                'a_secret_looking_run_of_lowercase_words_kept\n')
        result = diagnostic(io.BytesIO(body.encode()), {})
        for code in ('native_podfile_lock_commit_required', 'native_google_transport_helper_required',
                     'native_pods_operation_unverified'):
            self.assertIn(code, result)
        # A hex digest and base64 material carry no underscore and stay opaque.
        for opaque in ('9f2b7c1e4a8d3b6f0c5e2a9d7b4f1c8e3a6d0b5f',
                       'MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQ=='):
            self.assertNotIn(opaque, result)
        self.assertIn('[long value redacted]', result)

    def test_truncated_first_line_and_small_proxy_credentials_cannot_escape(self):
        body = b"x" * 17000 + b"TAIL_SECRET\n[!] Unable to satisfy dependency version 12.3.\n"
        self.assertNotIn("TAIL_SECRET", diagnostic(io.BytesIO(body), {}))
        result = diagnostic(io.BytesIO(b"username=Q password=Z\n"), {"HTTPS_PROXY": "http://Q:Z@fixture.invalid:8000"})
        self.assertNotIn("Q", result)
        self.assertNotIn("Z", result)

    def test_bounds_and_pem_text_are_private(self):
        body = b"[!] conflict 1.0 versus 2.0\n" * 1000
        result = diagnostic(io.BytesIO(body), {})
        self.assertLessEqual(len(result), 4000)
        self.assertLessEqual(len(result.splitlines()), 30)
        pem = b"-----BEGIN PRIVATE KEY-----\nPRIVATE_PEM_VALUE\n-----END PRIVATE KEY-----\n"
        self.assertNotIn("PRIVATE_PEM_VALUE", diagnostic(io.BytesIO(pem), {}))

    def test_cocoapods_primary_exception_survives_long_stack_and_secondary_failure(self):
        body = ('Analyzing dependencies\n### Error\n\n```\n'
                'FixturePodError - cannot install dependency 12.3\n'
                'Authorization: Bearer fixture-private-value\n'
                'https://fixture-user:fixture-password@example.invalid/private\n')
        body += ''.join(f'/ruby/gems/example/file_{index}.rb:12:in helper_{index}\n' for index in range(80))
        body += '```\nTEMPLATE END\nSearching for inspections failed: secondary query refused\n'
        result = diagnostic(io.BytesIO(body.encode()), {})
        self.assertIn('FixturePodError - cannot install dependency 12.3', result)
        self.assertIn('secondary query refused', result)
        self.assertNotIn('fixture-private-value', result)
        self.assertNotIn('fixture-password', result)
        self.assertNotIn('example.invalid', result)
        self.assertLessEqual(len(result), 4000)
        self.assertLessEqual(len(result.splitlines()), 30)
        self.assertEqual(diagnostic(io.BytesIO(result.encode()), {}), result)

    def test_primary_exception_survives_character_bound_as_well_as_line_bound(self):
        body = '### Error\n\n```\nFixturePodError - initial failure\n'
        body += ('frame with many ordinary path components ' * 8 + '\n') * 28
        body += 'secondary cleanup failure\n'
        result = diagnostic(io.BytesIO(body.encode()), {})
        self.assertIn('FixturePodError - initial failure', result)
        self.assertIn('secondary cleanup failure', result)
        self.assertLessEqual(len(result), 4000)
        self.assertLessEqual(len(result.splitlines()), 30)
