from __future__ import annotations

import json
import os
from typing import Any
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen


class StripeCheckoutClient:
    def __init__(
        self,
        *,
        secret_key: str,
        price_id: str,
        api_base_url: str = "https://api.stripe.com/v1",
    ) -> None:
        _require_text(secret_key, "STRIPE_SECRET_KEY")
        _require_text(price_id, "STRIPE_PRICE_ID_SIXXIE_MONTHLY_LAUNCH")
        self.price_id = price_id.strip()
        self.api_base_url = api_base_url.rstrip("/")
        self._secret_key = secret_key.strip()

    @classmethod
    def from_env(cls) -> "StripeCheckoutClient":
        return cls(
            secret_key=os.environ.get("STRIPE_SECRET_KEY", ""),
            price_id=os.environ.get("STRIPE_PRICE_ID_SIXXIE_MONTHLY_LAUNCH", ""),
        )

    def create_subscription_checkout(
        self,
        *,
        user_id: str,
        plan_code: str,
        price_id: str,
        client_surface: str,
        success_url: str,
        cancel_url: str,
    ) -> dict[str, Any]:
        _require_text(user_id, "user_id")
        _require_text(plan_code, "plan_code")
        _require_text(price_id, "price_id")
        _require_text(client_surface, "client_surface")
        _require_https_url(success_url, "success_url")
        _require_https_url(cancel_url, "cancel_url")
        body = urlencode(
            {
                "mode": "subscription",
                "line_items[0][price]": price_id,
                "line_items[0][quantity]": "1",
                "success_url": success_url,
                "cancel_url": cancel_url,
                "client_reference_id": user_id,
                "metadata[user_id]": user_id,
                "metadata[plan_code]": plan_code,
                "metadata[client_surface]": client_surface,
            }
        ).encode("utf-8")
        request = Request(
            f"{self.api_base_url}/checkout/sessions",
            data=body,
            headers={
                "Authorization": f"Bearer {self._secret_key}",
                "Content-Type": "application/x-www-form-urlencoded",
                "Accept": "application/json",
            },
            method="POST",
        )
        try:
            with urlopen(request, timeout=30) as response:
                payload = json.loads(response.read().decode("utf-8"))
        except (HTTPError, URLError, json.JSONDecodeError) as exc:
            raise ValueError("stripe checkout session could not be created") from exc
        if not isinstance(payload, dict) or not payload.get("id") or not payload.get("url"):
            raise ValueError("stripe checkout session returned an invalid response")
        return payload


def _require_text(value: str | None, field_name: str) -> None:
    if not str(value or "").strip():
        raise ValueError(f"{field_name} is required")


def _require_https_url(value: str, field_name: str) -> None:
    _require_text(value, field_name)
    if not value.startswith("https://"):
        raise ValueError(f"{field_name} must be an https URL")
