"""Local acceptance-control lab, not a live CAPTCHA or a production form.

Python 3.10+. No arguments, secrets, dependencies, external requests or files.
Provider replies are fixtures. Only the local HTTP form boundary is exercised.
"""
import json
import re
import threading
from http.client import HTTPConnection
from http.server import BaseHTTPRequestHandler, HTTPServer


class FixtureVerifier:
    """Chosen replies demonstrate application handling, not bot detection."""

    def __init__(self):
        self.used = set()

    def verify(self, token):
        if token == 'fixture-timeout':
            raise TimeoutError('Chosen provider timeout')
        if token == 'fixture-malformed':
            return ['not', 'an', 'object']
        if token == 'fixture-string-success':
            return {'success': 'true'}
        if token == 'fixture-expired' or token in self.used:
            return {'success': False, 'error-codes': ['timeout-or-duplicate']}
        replies = {
            'fixture-wrong-host': ('other.example.test', 'lead'),
            'fixture-wrong-action': ('form.example.test', 'login'),
            'fixture-pass-once': ('form.example.test', 'lead'),
        }
        if token not in replies:
            return {'success': False, 'error-codes': ['invalid-input-response']}
        self.used.add(token)
        hostname, action = replies[token]
        return {'success': True, 'hostname': hostname, 'action': action}


class AcceptanceGate:
    def __init__(self, verifier):
        self.verifier = verifier
        self.leads = []
        self.pending_receipts = []

    # BEGIN ACCEPTANCE GATE
    def submit(self, payload):
        if not isinstance(payload, dict):
            return 400, 'invalid-payload'
        token = payload.get('token')
        if not isinstance(token, str) or not 1 <= len(token) <= 2048:
            return 400, 'missing-or-invalid-token'
        email = payload.get('email')
        # Deliberately only a format check: no ownership or deliverability proof.
        if not isinstance(email, str) or len(email) > 254 or not re.fullmatch(r'[^\s@]+@[^\s@]+\.[^\s@]+', email):
            return 422, 'invalid-email-format'
        try:
            result = self.verifier.verify(token)
        except (TimeoutError, OSError):
            return 503, 'verification-unavailable'
        if not isinstance(result, dict) or type(result.get('success')) is not bool:
            return 503, 'invalid-verification-result'
        if result['success'] is not True:
            return 403, 'verification-rejected'
        if result.get('hostname') != 'form.example.test':
            return 403, 'hostname-mismatch'
        if result.get('action') != 'lead':
            return 403, 'action-mismatch'
        lead_id = 'local-lead-' + str(len(self.leads) + 1)
        self.leads.append({'id': lead_id, 'qualification': 'unreviewed'})
        self.pending_receipts.append({'lead_id': lead_id, 'state': 'pending'})
        return 202, 'accepted-for-review'
    # END ACCEPTANCE GATE


def run():
    gate = AcceptanceGate(FixtureVerifier())

    class Handler(BaseHTTPRequestHandler):
        def log_message(self, *_):
            pass

        def do_POST(self):
            if self.path != '/lead':
                self.send_error(404)
                return
            try:
                length = int(self.headers.get('Content-Length', '0'))
                if not 0 < length <= 8192:
                    raise ValueError('body-size')
                payload = json.loads(self.rfile.read(length).decode('utf-8'))
            except (ValueError, UnicodeDecodeError):
                status, decision = 400, 'invalid-json-or-body'
            else:
                status, decision = gate.submit(payload)
            body = json.dumps({'decision': decision}).encode('utf-8')
            self.send_response(status)
            self.send_header('Content-Type', 'application/json')
            self.send_header('Content-Length', str(len(body)))
            self.end_headers()
            self.wfile.write(body)

    server = HTTPServer(('127.0.0.1', 0), Handler)
    thread = threading.Thread(target=server.serve_forever, daemon=True)
    thread.start()
    good = {'email': 'not-a-real-inbox@example.test'}
    cases = [
        ('missing_token', good),
        ('client_approved_only', {**good, 'challenge_passed': True}),
        ('provider_failure', {**good, 'token': 'fixture-invalid'}),
        ('provider_timeout', {**good, 'token': 'fixture-timeout'}),
        ('malformed_result', {**good, 'token': 'fixture-malformed'}),
        ('string_success', {**good, 'token': 'fixture-string-success'}),
        ('wrong_hostname', {**good, 'token': 'fixture-wrong-host'}),
        ('wrong_action', {**good, 'token': 'fixture-wrong-action'}),
        ('invalid_email', {'email': 'not-an-email', 'token': 'fixture-pass-once'}),
        ('expiry_failure_fixture', {**good, 'token': 'fixture-expired'}),
        ('valid_but_unqualified', {**good, 'token': 'fixture-pass-once'}),
        ('replayed_token', {**good, 'token': 'fixture-pass-once'}),
    ]
    observations = []
    try:
        for name, payload in cases:
            connection = HTTPConnection('127.0.0.1', server.server_port, timeout=5)
            try:
                connection.request('POST', '/lead', json.dumps(payload), {'Content-Type': 'application/json'})
                response = connection.getresponse()
                body = json.loads(response.read())
                observations.append({'case': name, 'http_status': response.status, 'decision': body['decision'], 'stored_leads_after': len(gate.leads), 'pending_receipts_after': len(gate.pending_receipts)})
            finally:
                connection.close()
    finally:
        server.shutdown()
        server.server_close()
        thread.join(timeout=5)
    return {'mode': 'loopback-http-with-fixture-verifier', 'provider_validation_executed': False, 'external_requests': 0, 'observations': observations, 'stored_leads': len(gate.leads), 'pending_receipts': len(gate.pending_receipts), 'qualified_leads': sum(x['qualification'] == 'qualified' for x in gate.leads), 'ad_events_sent': 0}


if __name__ == '__main__':
    print(json.dumps(run(), indent=2))
