#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""platform.ciyuanfun.cn · 导入解析 SDK 示例（P167 二期下沉）

接口：POST /api/v1/org/import/extract   （Bearer Token，不是开放平台 HMAC 通道）
能力：图片 OCR / 音视频转写 / 扫描件 PDF 单页识别

限额：图片 10MB / 视频 50MB / 音频 20MB / 视频时长 600s / 每用户每日 30 次 / 单用户 1 并发
依赖：仅标准库（urllib），无需 pip install

用法：
    export CIYUAN_TOKEN=<登录拿到的 access_token>
    python3 import_extract_demo.py cover.png
    python3 import_extract_demo.py clip.mp4
    python3 import_extract_demo.py scan_p1.jpg

错误码（HTTP 非 200 时 body.code）：
    415 UNSUPPORTED_TYPE   文件类型不支持（后端按 magic bytes 判定，不认扩展名）
    413 TOO_LARGE          超过体积上限
    400 NO_AUDIO           视频里没有可用音轨
    400 USE_FRONTEND_PDF   PDF 请走前端 pdf.js 渲染后逐页上传
    429 BUSY               上一单还在处理
    429 RATE_LIMIT         当日 30 次额度用完
"""

import json
import os
import sys
import urllib.request
import uuid


BASE = "https://platform.ciyuanfun.cn"
PATH = "/api/v1/org/import/extract"


def _multipart(field, filename, data, boundary):
    """手工拼 multipart/form-data，避免引入 requests 依赖。"""
    head = (
        "--%s\r\n"
        'Content-Disposition: form-data; name="%s"; filename="%s"\r\n'
        "Content-Type: application/octet-stream\r\n\r\n" % (boundary, field, filename)
    ).encode("utf-8")
    tail = ("\r\n--%s--\r\n" % boundary).encode("utf-8")
    return head + data + tail


def extract(file_path, token=None, base=BASE, timeout=180):
    """上传单个文件做 AI 解析。

    返回 dict：
      成功         {'success': True, 'kind': 'image|video|audio', 'text': '...', 'chars': 79}
      无人声       {'success': True, 'noSpeech': True, 'message': '...'}
      失败         {'success': False, 'status': 413, 'code': 'TOO_LARGE', 'error': '...'}
    """
    token = token or os.environ.get("CIYUAN_TOKEN", "")
    if not token:
        raise RuntimeError("缺少 token：设置环境变量 CIYUAN_TOKEN，或传 token= 参数")

    with open(file_path, "rb") as f:
        data = f.read()

    boundary = "----CiyuanBoundary" + uuid.uuid4().hex
    body = _multipart("file", os.path.basename(file_path), data, boundary)

    req = urllib.request.Request(base + PATH, data=body, method="POST")
    req.add_header("Authorization", "Bearer " + token)
    req.add_header("Content-Type", "multipart/form-data; boundary=" + boundary)

    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode("utf-8", "replace"))
    except urllib.error.HTTPError as e:
        raw = e.read().decode("utf-8", "replace")
        try:
            payload = json.loads(raw)
        except Exception:
            payload = {"error": raw[:200]}
        payload["success"] = False
        payload["status"] = e.code
        return payload


def extract_many(paths, **kw):
    """逐个解析。注意服务端 limit 是「单用户 1 并发」，故这里串行。"""
    out = []
    for p in paths:
        out.append((p, extract(p, **kw)))
    return out


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(__doc__)
        sys.exit(2)

    for path, res in extract_many(sys.argv[1:]):
        print("=" * 60)
        print("文件:", path)
        if res.get("success"):
            if res.get("noSpeech"):
                print("结果: 未识别到人声 —", res.get("message", ""))
            else:
                print("类型:", res.get("kind"), "| 字数:", res.get("chars"))
                print("文本:")
                print(res.get("text", ""))
        else:
            print("失败: HTTP %s %s — %s" % (
                res.get("status"), res.get("code", ""), res.get("error", "")))
