"""WebhookReceiver — HTTP server that accepts TradingView alert webhooks."""

import json
import logging
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from typing import Callable, Optional

from pulse_tradingview.converter import AlertConverter

logger = logging.getLogger(__name__)


class WebhookReceiver:
    """HTTP server that receives TradingView webhook alerts.

    TradingView sends an HTTP POST to your webhook URL when an alert fires.
    WebhookReceiver listens on a configurable port, parses the alert,
    and calls your handler function.

    Example:
        >>> def handle(params):
        ...     print(f"Signal: {params['pair']} {params['direction']}")
        ...
        >>> receiver = WebhookReceiver(port=8888, on_signal=handle)
        >>> receiver.start()
        >>> # Set TradingView webhook URL to: http://YOUR_IP:8888/
        >>> receiver.stop()

    Or use as a context manager:
        >>> with WebhookReceiver(port=8888, on_signal=handle) as r:
        ...     input("Press Enter to stop...")
    """

    def __init__(
        self,
        port: int = 8888,
        on_signal: Optional[Callable] = None,
        secret: Optional[str] = None,
        host: str = "0.0.0.0",
    ):
        """
        Args:
            port: Port to listen on (default: 8888)
            on_signal: Callback called with parsed params dict on each alert
            secret: Optional shared secret for basic auth validation
            host: Host to bind to (default: 0.0.0.0 = all interfaces)
        """
        self.port = port
        self.host = host
        self.on_signal = on_signal or (lambda params: None)
        self.secret = secret
        self._server: Optional[HTTPServer] = None
        self._thread: Optional[threading.Thread] = None
        self._converter = AlertConverter()

    def start(self) -> None:
        """Start the webhook server in a background thread."""
        handler = self._make_handler()
        self._server = HTTPServer((self.host, self.port), handler)
        self._thread = threading.Thread(
            target=self._server.serve_forever,
            daemon=True,
            name="pulse-tradingview-webhook",
        )
        self._thread.start()
        logger.info(f"WebhookReceiver listening on {self.host}:{self.port}")
        print(f"[pulse-tradingview] Webhook server started on port {self.port}")
        print(f"[pulse-tradingview] Set TradingView webhook URL to: http://YOUR_SERVER_IP:{self.port}/")

    def stop(self) -> None:
        """Stop the webhook server."""
        if self._server:
            self._server.shutdown()
            self._server = None
        logger.info("WebhookReceiver stopped")

    def __enter__(self):
        self.start()
        return self

    def __exit__(self, *args):
        self.stop()

    def _make_handler(self):
        """Create the HTTP request handler class."""
        receiver = self

        class Handler(BaseHTTPRequestHandler):
            def do_POST(self):
                # Validate secret if configured
                if receiver.secret:
                    auth = self.headers.get("X-PULSE-Secret", "")
                    if auth != receiver.secret:
                        self.send_error(401, "Unauthorized")
                        return

                # Read body
                content_length = int(self.headers.get("Content-Length", 0))
                raw = self.rfile.read(content_length).decode("utf-8", errors="replace")

                if not raw.strip():
                    self.send_error(400, "Empty request body")
                    return

                # Parse alert
                try:
                    params = receiver._converter.parse(raw)
                except ValueError as e:
                    logger.error(f"Alert parse error: {e} | raw={raw[:200]}")
                    self.send_error(400, str(e))
                    return

                # Log the incoming signal
                logger.info(
                    f"Alert received: {params.get('pair')} {params.get('direction')} "
                    f"(confidence={params.get('confidence', 1.0):.0%})"
                )

                # Call handler
                try:
                    results = receiver.on_signal(params)
                    response = {
                        "status": "ok",
                        "pair": params.get("pair"),
                        "direction": params.get("direction"),
                        "results": results if isinstance(results, list) else [],
                    }
                    self.send_response(200)
                    self.send_header("Content-Type", "application/json")
                    self.end_headers()
                    self.wfile.write(json.dumps(response).encode())
                except Exception as e:
                    logger.error(f"Handler error: {e}")
                    self.send_error(500, str(e))

            def do_GET(self):
                """Health check endpoint."""
                self.send_response(200)
                self.send_header("Content-Type", "application/json")
                self.end_headers()
                self.wfile.write(json.dumps({
                    "status": "ok",
                    "service": "pulse-tradingview",
                    "version": "0.1.0",
                    "message": "Webhook server is running. POST your TradingView alerts here.",
                }).encode())

            def log_message(self, fmt, *args):
                # Route HTTP server logs through Python logging
                logger.debug(f"HTTP: {fmt % args}")

        return Handler
