"""短视频 CDN 代理：转发请求并附带 Referer / User-Agent，供前端 <video> 播放。"""

from urllib.parse import urlparse

import requests
from flask import Flask, Response, request, stream_with_context

app = Flask(__name__)

DEFAULT_UA = (
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
    "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
)

REFERER_RULES = (
    ("douyinvod.com", "https://www.douyin.com/"),
    ("douyinpic.com", "https://www.douyin.com/"),
    ("douyin.com", "https://www.douyin.com/"),
    ("xhscdn.com", "https://www.xiaohongshu.com/"),
    ("xiaohongshu.com", "https://www.xiaohongshu.com/"),
    ("bilivideo.com", "https://www.bilibili.com/"),
    ("bilibili.com", "https://www.bilibili.com/"),
    ("feigua.cn", "https://www.bilibili.com/"),
)


def infer_referer(url: str) -> str:
    host = (urlparse(url).hostname or "").lower()
    for suffix, referer in REFERER_RULES:
        if host == suffix or host.endswith("." + suffix):
            return referer
    return ""


def build_upstream_headers() -> dict:
    referer = (request.args.get("referer") or "").strip()
    url = (request.args.get("url") or "").strip()
    if not referer and url:
        referer = infer_referer(url)

    headers = {
        "User-Agent": DEFAULT_UA,
        "Accept": "*/*",
        "Accept-Encoding": "identity",
    }
    if referer:
        headers["Referer"] = referer
    range_header = request.headers.get("Range")
    if range_header:
        headers["Range"] = range_header
    return headers


@app.after_request
def add_cors(resp):
    resp.headers["Access-Control-Allow-Origin"] = "*"
    resp.headers["Access-Control-Allow-Methods"] = "GET, HEAD, OPTIONS"
    resp.headers["Access-Control-Allow-Headers"] = "Range, Content-Type"
    resp.headers["Access-Control-Expose-Headers"] = (
        "Content-Length, Content-Range, Accept-Ranges, Content-Type"
    )
    return resp


@app.route("/video/proxy", methods=["OPTIONS"])
def video_proxy_options():
    return ("", 204)


@app.route("/video/proxy", methods=["GET", "HEAD"])
def video_proxy():
    url = (request.args.get("url") or "").strip()
    if not url or not url.startswith(("http://", "https://")):
        return "invalid url", 400

    try:
        upstream = requests.request(
            method=request.method,
            url=url,
            headers=build_upstream_headers(),
            stream=True,
            timeout=60,
            allow_redirects=True,
        )
    except requests.RequestException as exc:
        return f"upstream error: {exc}", 502

    passthrough = (
        "Content-Type",
        "Content-Length",
        "Content-Range",
        "Accept-Ranges",
    )
    headers = {k: upstream.headers[k] for k in passthrough if k in upstream.headers}

    if request.method == "HEAD":
        upstream.close()
        return ("", upstream.status_code, headers)

    def generate():
        try:
            for chunk in upstream.iter_content(chunk_size=65536):
                if chunk:
                    yield chunk
        finally:
            upstream.close()

    return Response(
        stream_with_context(generate()),
        status=upstream.status_code,
        headers=headers,
    )


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5001, debug=False)
