"""Read an iOS .app Info.plist locally. Does not execute or upload the app."""
import argparse
import json
import plistlib
from pathlib import Path


def inspect(app):
    path = Path(app)
    if path.suffix != '.app' or not path.is_dir():
        raise ValueError('Choose an extracted iOS .app directory.')
    metadata = path / 'Info.plist'
    if metadata.stat().st_size > 2_000_000:
        raise ValueError('Info.plist exceeds 2 MB.')
    data = plistlib.loads(metadata.read_bytes())
    if not isinstance(data, dict):
        raise ValueError('Info.plist must contain a dictionary.')
    platforms = data.get('CFBundleSupportedPlatforms')
    if platforms is not None and (not isinstance(platforms, list) or not set(platforms).intersection({'iPhoneOS', 'iPhoneSimulator'})):
        raise ValueError('Choose an iOS app bundle, not another platform.')
    return {'platform': 'ios', 'identifier': data.get('CFBundleIdentifier', ''),
            'version': data.get('CFBundleShortVersionString', ''), 'build': data.get('CFBundleVersion', ''),
            'permissions': [{'name': key, 'purpose': value} for key, value in data.items() if key.endswith('UsageDescription') and isinstance(value, str)],
            'collection': {'source': 'Info.plist', 'privacyManifestPresent': (path / 'PrivacyInfo.xcprivacy').is_file(),
                           'coverage': 'Metadata only. Supply privacyPolicyUrl, createsAccounts and accountDeletion after verifying actual app behaviour. Embedded SDKs and signing are not inspected.'}}


if __name__ == '__main__':
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument('app'); p.add_argument('output'); a = p.parse_args()
    result = inspect(a.app)
    with open(a.output, 'x') as handle:
        json.dump(result, handle, indent=2)
    print('Metadata exported. Complete behavioural and policy fields before review.')
