#!/usr/bin/env python3
"""Read one HTTPS resource, preserving the caller's HTTP proxy chain."""
import os
import sys
from urllib.parse import urlsplit
import requests


class ConfigurationError(ValueError):
    """A controlled configuration message authored by this helper."""


class IPCheckTokenError(ValueError):
    """The public IP check must not receive destination credentials."""


def get_status(url, token=None):
    parsed = urlsplit(url)
    if parsed.scheme != 'https' or not parsed.hostname or parsed.username or parsed.password:
        raise ConfigurationError('Use an HTTPS destination without credentials in its URL.')
    effective_proxy = requests.utils.get_environ_proxies(url).get('https')
    if not effective_proxy or urlsplit(effective_proxy).scheme not in ('http', 'https'):
        raise ConfigurationError('No effective HTTP/HTTPS proxy for the protected HTTPS destination.')
    if token and parsed.hostname.lower() == 'ip.quotaguard.com':
        raise IPCheckTokenError('Destination tokens are not allowed for the public IP check.')
    headers = {'Accept': 'application/json'}
    if token:
        headers['Authorization'] = 'Bearer ' + token
    # trust_env=True is deliberate: inside the Bash sandbox this uses its local
    # proxy, which enforces policy before forwarding to the configured upstream.
    with requests.Session() as session:
        session.trust_env = True
        with session.get(url, headers=headers, timeout=(10, 30),
                         allow_redirects=False, stream=True) as response:
            return response.status_code


def main():
    try:
        url = os.environ.get('PROTECTED_URL')
        if not url:
            raise ConfigurationError('Set PROTECTED_URL to the intended HTTPS destination.')
        status = get_status(url, os.environ.get('DESTINATION_TOKEN'))
    except IPCheckTokenError:
        print('IP check rejects DESTINATION_TOKEN. Run: env -u DESTINATION_TOKEN '
              'PROTECTED_URL=https://ip.quotaguard.com python3 protected_get.py', file=sys.stderr)
        return 2
    except ConfigurationError as error:
        print(str(error), file=sys.stderr)
        return 2
    except requests.exceptions.SSLError:
        print('TLS verification or handshake failed; check approved CA trust and proxy transport. '
              'Keep certificate verification enabled.', file=sys.stderr)
        return 2
    except requests.exceptions.ProxyError:
        print('Proxy connection failed; check proxy authentication, permitted route and upstream '
              'compatibility. This exception alone does not identify the cause.', file=sys.stderr)
        return 2
    except requests.exceptions.Timeout:
        print('Request timed out; check reachability, network policy and service availability.', file=sys.stderr)
        return 2
    except requests.exceptions.ConnectionError:
        print('Connection failed; check DNS, host reachability and network policy.', file=sys.stderr)
        return 2
    except (KeyError, ValueError, OSError, requests.RequestException):
        print('Request failed; inspect redacted diagnostics and route settings.', file=sys.stderr)
        return 2
    print('HTTP status:', status)
    return 0 if 200 <= status < 300 else 1


if __name__ == '__main__':
    sys.exit(main())
