"""CORS helpers for REST handlers and API Gateway responses."""

from __future__ import annotations

import os
from typing import Mapping
from urllib.parse import urlsplit

_DEFAULT_ALLOWED_ORIGINS = (
    "http://localhost:*,"
    "http://127.0.0.1:*,"
)

_RAW_CORS_ALLOW_ORIGINS = (
    os.environ.get("CORS_ALLOW_ORIGINS") or os.environ.get("CORS_ALLOW_ORIGIN") or _DEFAULT_ALLOWED_ORIGINS
)


def _normalize_origins(raw: str) -> list[str]:
    return [origin.strip() for origin in raw.split(",") if origin.strip()]


CORS_ALLOW_ORIGINS = _normalize_origins(_RAW_CORS_ALLOW_ORIGINS)


def _normalize_origin(value: str) -> str | None:
    origin = value.strip().rstrip("/")
    if not origin:
        return None
    if origin.endswith(":*"):
        return origin

    try:
        parsed = urlsplit(origin)
    except ValueError:
        return None

    if not parsed.scheme or not parsed.hostname:
        return None

    try:
        parsed_port = parsed.port
    except ValueError:
        return None

    if parsed_port is None:
        return f"{parsed.scheme}://{parsed.hostname}"

    if (parsed.scheme == "http" and parsed_port == 80) or (parsed.scheme == "https" and parsed_port == 443):
        return f"{parsed.scheme}://{parsed.hostname}"

    return f"{parsed.scheme}://{parsed.hostname}:{parsed_port}"


def _origin_matches_pattern(origin: str, pattern: str) -> bool:
    normalized_origin = _normalize_origin(origin)
    normalized_pattern = _normalize_origin(pattern)
    if not normalized_origin or not normalized_pattern:
        return False

    if normalized_pattern.endswith(":*"):
        prefix = normalized_pattern[:-2]
        return normalized_origin == prefix or normalized_origin.startswith(f"{prefix}:")

    return normalized_origin == normalized_pattern


def request_origin(headers: Mapping[str, str] | None) -> str | None:
    if not headers:
        return None
    for key, value in headers.items():
        if str(key).lower() == "origin":
            return str(value)
    return None


def resolve_allow_origin(origin: str | None) -> str | None:
    if not origin:
        return None
    normalized_origin = _normalize_origin(origin)
    if not normalized_origin:
        return None
    if "*" in CORS_ALLOW_ORIGINS:
        return normalized_origin
    for allowed_origin in CORS_ALLOW_ORIGINS:
        if _origin_matches_pattern(normalized_origin, allowed_origin):
            return normalized_origin
    return None


__all__ = ["CORS_ALLOW_ORIGINS", "request_origin", "resolve_allow_origin"]

