"""Local development server with real integration-test routes.

Production must move this route behind the platform admin session and a
proper application server. PostgreSQL testing uses the optional psycopg driver.
"""

from __future__ import annotations

import base64
import hashlib
import hmac
import json
import os
import re
import shutil
import time
import uuid
from datetime import datetime, timezone
from http import HTTPStatus
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode, urlparse
from urllib.request import Request, urlopen

from integration_adapters import (
    IntegrationAdapterError,
    test_cos_connection,
    test_postgresql_connection,
)


ROOT = Path(__file__).resolve().parent
RUNTIME_CONFIG_PATH = ROOT / ".runtime-integrations.json"
DEFAULT_IDENTITY_ENDPOINT = (
    "https://ap-beijing.cloudmarket-apigw.com/"
    "service-18c38npd/idcard/VerifyIdcardv2"
)
ALLOWED_IDENTITY_HOST = "ap-beijing.cloudmarket-apigw.com"
ALLOWED_IDENTITY_PATH = "/service-18c38npd/idcard/VerifyIdcardv2"
ID_CARD_PATTERN = re.compile(r"^[0-9A-Za-z]{15,18}$")
MOCK_SESSION_ID = "mock-user-001"
IDENTITY_PROVIDER = "腾讯云市场 17684"
RUNTIME_PROVIDERS = {
    "database": {"PostgreSQL"},
    "storage": {"腾讯云 COS"},
    "identity": {IDENTITY_PROVIDER, "tencent-marketplace-17684"},
}


def utc_http_date() -> str:
    return datetime.now(timezone.utc).strftime("%a, %d %b %Y %H:%M:%S GMT")


def read_credentials(request_ref: str = "") -> tuple[str, str]:
    ref = os.environ.get("TENCENT_MARKET_IDENTITY_CREDENTIALS_FILE", "").strip() or request_ref.strip()
    if not ref:
        raise RuntimeError("未配置 TENCENT_MARKET_IDENTITY_CREDENTIALS_FILE")
    if not Path(ref).is_absolute():
        raise RuntimeError("实名认证服务端凭据引用必须是绝对路径")
    try:
        payload = json.loads(Path(ref).read_text(encoding="utf-8"))
    except FileNotFoundError as exc:
        raise RuntimeError("实名认证服务端凭据文件不存在") from exc
    except (OSError, json.JSONDecodeError) as exc:
        raise RuntimeError("实名认证服务端凭据文件不可读取") from exc
    secret_id = payload.get("secretId")
    secret_key = payload.get("secretKey")
    if not isinstance(secret_id, str) or not secret_id or not isinstance(secret_key, str) or not secret_key:
        raise RuntimeError("实名认证服务端凭据文件缺少 secretId 或 secretKey")
    return secret_id, secret_key


def load_runtime_config() -> dict[str, object]:
    try:
        payload = json.loads(RUNTIME_CONFIG_PATH.read_text(encoding="utf-8"))
    except (FileNotFoundError, OSError, json.JSONDecodeError):
        return {}
    return payload if isinstance(payload, dict) else {}


def save_runtime_service(service: str, value: dict[str, object]) -> None:
    current = load_runtime_config()
    current[service] = {
        "enabled": value.get("enabled") is True,
        "provider": str(value.get("provider") or "")[:120],
        "endpoint": str(value.get("endpoint") or "")[:300],
        "identifier": str(value.get("identifier") or "")[:120],
        # Only the server-side file reference is persisted; never accept secret material here.
        "secretRef": str(value.get("secretRef") or "")[:300],
    }
    temporary = RUNTIME_CONFIG_PATH.with_suffix(".tmp")
    temporary.write_text(json.dumps(current, ensure_ascii=False, indent=2), encoding="utf-8")
    os.replace(temporary, RUNTIME_CONFIG_PATH)


def build_v2_request(endpoint: str, real_name: str, id_card_no: str, secret_id: str, secret_key: str) -> Request:
    parsed = urlparse(endpoint)
    if parsed.scheme != "https" or parsed.netloc != ALLOWED_IDENTITY_HOST or parsed.path != ALLOWED_IDENTITY_PATH:
        raise RuntimeError("实名认证接口地址不在允许范围内")
    date_value = utc_http_date()
    signature = base64.b64encode(
        hmac.new(secret_key.encode("utf-8"), f"x-date: {date_value}".encode("utf-8"), hashlib.sha1).digest()
    ).decode("ascii")
    authorization = json.dumps(
        {"id": secret_id, "x-date": date_value, "signature": signature},
        ensure_ascii=False,
        separators=(",", ":"),
    )
    body = urlencode({"cardNo": id_card_no, "realName": real_name}).encode("utf-8")
    request = Request(endpoint, data=body, method="POST")
    request.add_header("Content-Type", "application/x-www-form-urlencoded")
    request.add_header("Authorization", authorization)
    request.add_header("request-id", str(uuid.uuid4()))
    return request


def call_identity_provider(endpoint: str, real_name: str, id_card_no: str, credentials_ref: str = "") -> dict[str, object]:
    secret_id, secret_key = read_credentials(credentials_ref)
    request = build_v2_request(endpoint, real_name, id_card_no, secret_id, secret_key)
    request_id = request.get_header("Request-id") or ""
    try:
        with urlopen(request, timeout=5) as response:
            raw = response.read(64 * 1024)
            http_status = response.status
    except HTTPError as exc:
        if exc.code in (408, 429) or exc.code >= 500:
            return {"ok": False, "code": "RETRYABLE_ERROR", "message": "供应商暂时不可用，请稍后重试"}
        if exc.code in (401, 403):
            return {"ok": False, "code": "REJECTED", "message": "供应商凭据无效或无权调用"}
        return {"ok": False, "code": "REJECTED", "message": f"供应商返回 HTTP {exc.code}"}
    except (TimeoutError, URLError):
        return {"ok": False, "code": "RETRYABLE_ERROR", "message": "供应商连接超时，请稍后重试"}
    except OSError:
        return {"ok": False, "code": "RETRYABLE_ERROR", "message": "实名认证服务网络连接失败"}

    try:
        payload = json.loads(raw.decode("utf-8"))
    except (UnicodeDecodeError, json.JSONDecodeError):
        return {"ok": False, "code": "REJECTED", "message": "供应商返回格式无法识别"}
    if http_status >= 500:
        return {"ok": False, "code": "RETRYABLE_ERROR", "message": "供应商暂时不可用，请稍后重试"}
    error_code = payload.get("error_code")
    result = payload.get("result") if isinstance(payload.get("result"), dict) else {}
    if error_code == 0 and result.get("isok") is True:
        return {"ok": True, "status": "VERIFIED", "message": "真实连接通过，实名匹配", "requestId": request_id}
    if error_code == 0 and result.get("isok") is False:
        return {"ok": True, "status": "MISMATCH", "message": "接口已响应，但姓名与身份证号不匹配", "requestId": request_id}
    if error_code == 206501:
        return {"ok": True, "status": "NO_RECORD", "message": "接口已响应，但供应商库中无此记录", "requestId": request_id}
    return {"ok": False, "code": "REJECTED", "message": "供应商返回未识别的业务错误", "requestId": request_id}


class Handler(SimpleHTTPRequestHandler):
    server_version = "BetterTaskDev/1.0"

    def log_message(self, format: str, *args: object) -> None:
        # Never log request bodies, identity data, authorization headers, or provider responses.
        super().log_message(format, *args)

    def _json(self, status: int, payload: dict[str, object]) -> None:
        data = json.dumps(payload, ensure_ascii=False).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json; charset=utf-8")
        self.send_header("Cache-Control", "no-store")
        self.send_header("Content-Length", str(len(data)))
        self.end_headers()
        self.wfile.write(data)

    def do_POST(self) -> None:  # noqa: N802
        request_path = urlparse(self.path).path
        if request_path == "/api/identity-verifications":
            self._handle_identity_verification()
            return
        if request_path == "/api/admin/integration-config":
            self._handle_integration_config()
            return
        if request_path != "/api/admin/integration-tests":
            self._json(HTTPStatus.NOT_FOUND, {"ok": False, "code": "NOT_FOUND", "message": "接口不存在"})
            return
        self._handle_integration_test()

    def _read_json_body(self, max_bytes: int = 16 * 1024) -> dict[str, object] | None:
        try:
            content_length = int(self.headers.get("Content-Length", "0"))
        except ValueError:
            content_length = 0
        if content_length <= 0 or content_length > max_bytes:
            return None
        try:
            body = json.loads(self.rfile.read(content_length).decode("utf-8"))
        except (UnicodeDecodeError, json.JSONDecodeError):
            return None
        return body if isinstance(body, dict) else None

    def _handle_integration_test(self) -> None:
        body = self._read_json_body()
        if body is None:
            self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "INVALID_BODY", "message": "请求数据无效"})
            return
        service = body.get("service")
        provider = body.get("provider")
        endpoint = body.get("endpoint") if isinstance(body.get("endpoint"), str) else ""
        identifier = body.get("identifier") if isinstance(body.get("identifier"), str) else ""
        secret_ref = body.get("secretRef") if isinstance(body.get("secretRef"), str) else ""

        try:
            if service == "database" and provider == "PostgreSQL":
                result = test_postgresql_connection(endpoint, identifier, secret_ref)
            elif service == "storage" and provider == "腾讯云 COS":
                result = test_cos_connection(identifier, endpoint, secret_ref)
            elif service == "identity" and provider == IDENTITY_PROVIDER:
                real_name = body.get("realName")
                id_card_no = body.get("idCardNo")
                if not isinstance(real_name, str) or not real_name.strip() or len(real_name.strip()) > 50:
                    self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "INVALID_TEST_NAME", "message": "请填写有效的测试姓名"})
                    return
                if not isinstance(id_card_no, str) or not ID_CARD_PATTERN.fullmatch(id_card_no.strip()):
                    self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "INVALID_TEST_CARD", "message": "请填写有效的测试身份证号"})
                    return
                identity_endpoint = os.environ.get("TENCENT_MARKET_IDENTITY_API_URL", DEFAULT_IDENTITY_ENDPOINT)
                result = call_identity_provider(
                    identity_endpoint,
                    real_name.strip(),
                    id_card_no.strip(),
                    secret_ref,
                )
            else:
                self._json(
                    HTTPStatus.NOT_IMPLEMENTED,
                    {"ok": False, "code": "ADAPTER_NOT_IMPLEMENTED", "message": "该供应商暂未提供真实网络测试适配器"},
                )
                return
        except IntegrationAdapterError as exc:
            self._json(exc.http_status, {"ok": False, "code": exc.code, "message": exc.message})
            return
        except RuntimeError as exc:
            self._json(HTTPStatus.SERVICE_UNAVAILABLE, {"ok": False, "code": "CONFIG_MISSING", "message": str(exc)})
            return
        self._json(HTTPStatus.OK if result.get("ok") else HTTPStatus.BAD_GATEWAY, result)

    def _handle_identity_verification(self) -> None:
        # This mock session gate is only for the local preview flow. Production must use the app Session.
        if self.headers.get("X-BetterTask-Mock-Session") != MOCK_SESSION_ID:
            self._json(HTTPStatus.UNAUTHORIZED, {"success": False, "code": "UNAUTHORIZED", "message": "请先登录"})
            return
        body = self._read_json_body()
        if body is None:
            self._json(HTTPStatus.BAD_REQUEST, {"success": False, "code": "INVALID_BODY", "message": "请求数据无效"})
            return
        real_name = body.get("realName")
        id_card_no = body.get("idCardNo")
        consent_version = body.get("consentVersion")
        if not isinstance(real_name, str) or not real_name.strip() or len(real_name.strip()) > 50:
            self._json(HTTPStatus.BAD_REQUEST, {"success": False, "code": "INVALID_NAME", "message": "请填写有效的真实姓名"})
            return
        if not isinstance(id_card_no, str) or not ID_CARD_PATTERN.fullmatch(id_card_no.strip()):
            self._json(HTTPStatus.BAD_REQUEST, {"success": False, "code": "INVALID_CARD", "message": "请填写有效的身份证号"})
            return
        if consent_version != "identity-v1":
            self._json(HTTPStatus.BAD_REQUEST, {"success": False, "code": "CONSENT_REQUIRED", "message": "请先同意实名认证授权"})
            return
        runtime_identity = load_runtime_config().get("identity")
        runtime_identity = runtime_identity if isinstance(runtime_identity, dict) else {}
        endpoint = os.environ.get("TENCENT_MARKET_IDENTITY_API_URL", "").strip() or str(runtime_identity.get("endpoint") or DEFAULT_IDENTITY_ENDPOINT)
        secret_ref = str(runtime_identity.get("secretRef") or "")
        try:
            result = call_identity_provider(endpoint, real_name.strip(), id_card_no.strip(), secret_ref)
        except RuntimeError as exc:
            self._json(HTTPStatus.SERVICE_UNAVAILABLE, {"success": False, "code": "CONFIG_MISSING", "message": str(exc)})
            return
        status = result.get("status")
        if status in {"VERIFIED", "MISMATCH", "NO_RECORD"}:
            self._json(HTTPStatus.OK, {"success": True, "data": {
                "verificationId": str(uuid.uuid4()),
                "status": status,
                "verifiedAt": datetime.now(timezone.utc).isoformat() if status == "VERIFIED" else None,
            }})
            return
        self._json(HTTPStatus.BAD_GATEWAY, {"success": False, "code": result.get("code", "IDENTITY_PROVIDER_ERROR"), "message": result.get("message", "实名认证服务暂不可用")})

    def _handle_integration_config(self) -> None:
        body = self._read_json_body()
        if body is None or body.get("service") not in RUNTIME_PROVIDERS:
            self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "INVALID_CONFIG", "message": "接口配置数据无效"})
            return
        service = str(body.get("service"))
        provider = body.get("provider")
        secret_ref = body.get("secretRef")
        enabled = body.get("enabled") is True
        if not isinstance(provider, str) or provider not in RUNTIME_PROVIDERS[service]:
            self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "INVALID_PROVIDER", "message": "供应商配置无效或暂未实现"})
            return
        if enabled and (not isinstance(body.get("identifier"), str) or not str(body.get("identifier")).strip()):
            self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "MISSING_IDENTIFIER", "message": "请填写服务标识"})
            return
        if enabled and (not isinstance(body.get("endpoint"), str) or not str(body.get("endpoint")).strip()):
            self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "MISSING_ENDPOINT", "message": "请填写接口地址"})
            return
        if enabled and (not isinstance(secret_ref, str) or not secret_ref.strip()):
            self._json(HTTPStatus.BAD_REQUEST, {"ok": False, "code": "MISSING_CREDENTIAL_REF", "message": "请填写服务端凭据文件引用"})
            return
        try:
            save_runtime_service(service, body)
        except OSError:
            self._json(HTTPStatus.INTERNAL_SERVER_ERROR, {"ok": False, "code": "CONFIG_SAVE_FAILED", "message": "服务端无法保存接口配置"})
            return
        service_names = {"database": "数据库", "storage": "COS 存储", "identity": "实名接口"}
        self._json(HTTPStatus.OK, {"ok": True, "message": f"{service_names[service]}配置已同步到服务端"})


    def do_GET(self) -> None:  # noqa: N802
        request_path = urlparse(self.path).path
        if request_path == "/api/admin/server-health":
            self._handle_server_health()
            return
        super().do_GET()

    def _handle_server_health(self) -> None:
        """Return local development metrics for the admin health board."""
        try:
            disk = shutil.disk_usage(ROOT)
            disk_percent = round((disk.used / disk.total) * 100, 1) if disk.total else None
            disk_detail = f"{disk.free // (1024 ** 3)} GB free"
        except OSError:
            disk_percent = None
            disk_detail = "unavailable"
        try:
            load = round(os.getloadavg()[0], 2)
        except (AttributeError, OSError):
            load = 0
        try:
            state_size = RUNTIME_CONFIG_PATH.stat().st_size if RUNTIME_CONFIG_PATH.exists() else 0
        except OSError:
            state_size = 0
        disk_status = "critical" if isinstance(disk_percent, (int, float)) and disk_percent >= 90 else "warning" if isinstance(disk_percent, (int, float)) and disk_percent >= 80 else "normal"
        metrics = {
            "cpu": {"value": 0, "unit": "%", "status": "normal", "detail": "local development server"},
            "memory": {"value": 0, "unit": "%", "status": "normal", "detail": "host monitoring required"},
            "disk": {"value": disk_percent, "unit": "%", "status": disk_status, "detail": disk_detail},
            "load": {"value": load, "unit": "", "status": "normal", "detail": "1 minute load average"},
            "uptime": {"value": int(time.monotonic()), "unit": "s", "status": "normal", "detail": "process uptime"},
            "queue": {"value": 0, "unit": "items", "status": "normal", "detail": f"runtime config {state_size} bytes"},
        }
        self._json(HTTPStatus.OK, {"ok": True, "source": "local-dev-server", "updatedAt": datetime.now(timezone.utc).isoformat(), "metrics": metrics})


def main() -> None:
    os.chdir(ROOT)
    port = int(os.environ.get("PORT", "5520"))
    server = ThreadingHTTPServer(("127.0.0.1", port), Handler)
    print(f"BetterTask dev server listening on http://127.0.0.1:{port}")
    server.serve_forever()


if __name__ == "__main__":
    main()
