"""
Agent Tollbooth (x402 Micropayment Proxy Middleware for Python)
Charge AI scrapers & crawlers HTTP 402 Payment Required unless authenticated.

Usage (Flask):
    from flask import Flask
    from agent_tollbooth import AgentTollbooth
    
    app = Flask(__name__)
    AgentTollbooth(app, price_per_request=0.005, checkout_url="https://proofchain.us/tollbooth/")

Usage (FastAPI / ASGI):
    from fastapi import FastAPI
    from agent_tollbooth import AgentTollboothASGIMiddleware
    
    app = FastAPI()
    app.add_middleware(AgentTollboothASGIMiddleware, price_per_request=0.005)
"""

import re
import json

AI_BOT_SIGNATURES = [
    r'gptbot',
    r'chatgpt-user',
    r'claudebot',
    r'claude-web',
    r'anthropic-ai',
    r'perplexitybot',
    r'bytespider',
    r'ccbot',
    r'diffbot',
    r'facebookbot',
    r'google-extended',
    r'cohere-ai',
    r'omgilibot',
    r'scrapy',
    r'amazonbot',
    r'turnitinbot',
    r'youbot',
    r'webz\.io',
    r'imagesiftbot',
    r'applebot-extended'
]

BOT_REGEX = re.compile('|'.join(AI_BOT_SIGNATURES), re.IGNORECASE)

class AgentTollbooth:
    """WSGI / Flask Middleware for Agent Tollbooth x402 Micropayments"""
    def __init__(self, app=None, api_key=None, price_per_request=0.005, checkout_url="https://proofchain.us/tollbooth/", bypass_paths=None):
        self.app = app
        self.api_key = api_key
        self.price_per_request = price_per_request
        self.checkout_url = checkout_url
        self.bypass_paths = set(bypass_paths or ['/health', '/ping', '/favicon.ico'])
        
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        @app.before_request
        def verify_agent_access():
            from flask import request, jsonify
            
            if request.path in self.bypass_paths:
                return None

            user_agent = request.headers.get('User-Agent', '')
            agent_token = request.headers.get('X-Agent-Token') or request.headers.get('Authorization', '')

            # Check for valid token
            if agent_token and (agent_token.startswith('tb_') or 'Bearer tb_' in agent_token):
                return None

            # Detect AI Bot
            if BOT_REGEX.search(user_agent):
                payload = {
                    "status": 402,
                    "error": "Payment Required",
                    "message": "AI Agent access to this endpoint requires a pre-funded Agent Token or micropayment rail.",
                    "bot_detected": user_agent,
                    "protocol": "x402-v1",
                    "paywall_provider": "Agent Tollbooth by ProofChain",
                    "pricing": {
                        "per_request_usd": self.price_per_request,
                        "currency": "USD"
                    },
                    "checkout_url": self.checkout_url,
                    "instructions": "Pass header 'X-Agent-Token: tb_live_...' or 'Authorization: Bearer tb_live_...' to access."
                }
                response = jsonify(payload)
                response.status_code = 402
                response.headers['X-402-Payment-Required'] = 'true'
                response.headers['X-402-Price'] = str(self.price_per_request)
                return response

            return None


class AgentTollboothASGIMiddleware:
    """ASGI / FastAPI Middleware for Agent Tollbooth x402 Micropayments"""
    def __init__(self, app, api_key=None, price_per_request=0.005, checkout_url="https://proofchain.us/tollbooth/", bypass_paths=None):
        self.app = app
        self.api_key = api_key
        self.price_per_request = price_per_request
        self.checkout_url = checkout_url
        self.bypass_paths = set(bypass_paths or ['/health', '/ping', '/favicon.ico'])

    async def __call__(self, scope, receive, send):
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        path = scope.get("path", "")
        if path in self.bypass_paths:
            await self.app(scope, receive, send)
            return

        headers = dict((k.decode("utf-8").lower(), v.decode("utf-8")) for k, v in scope.get("headers", []))
        user_agent = headers.get("user-agent", "")
        agent_token = headers.get("x-agent-token") or headers.get("authorization", "")

        if agent_token and ("tb_" in agent_token):
            await self.app(scope, receive, send)
            return

        if BOT_REGEX.search(user_agent):
            body = json.dumps({
                "status": 402,
                "error": "Payment Required",
                "message": "AI Agent access to this endpoint requires a pre-funded Agent Token or micropayment rail.",
                "bot_detected": user_agent,
                "protocol": "x402-v1",
                "paywall_provider": "Agent Tollbooth by ProofChain",
                "pricing": {
                    "per_request_usd": self.price_per_request,
                    "currency": "USD"
                },
                "checkout_url": self.checkout_url,
                "instructions": "Pass header 'X-Agent-Token: tb_live_...' or 'Authorization: Bearer tb_live_...' to access."
            }).encode("utf-8")

            response_headers = [
                (b"content-type", b"application/json"),
                (b"x-402-payment-required", b"true"),
                (b"x-402-price", str(self.price_per_request).encode("utf-8")),
            ]

            await send({
                "type": "http.response.start",
                "status": 402,
                "headers": response_headers,
            })
            await send({
                "type": "http.response.body",
                "body": body,
            })
            return

        await self.app(scope, receive, send)
