"""腾讯云 OCR：通用印刷体、身份证、营业执照识别。"""
from __future__ import annotations

import base64
from pathlib import Path

from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.ocr.v20181119 import models, ocr_client

from app.core.config import settings
from app.core.logger import get_logger
from app.core.response import AppError

logger = get_logger(__name__)


def _client() -> ocr_client.OcrClient:
    cred = credential.Credential(settings.tencent_secret_id, settings.tencent_secret_key)
    hp = HttpProfile()
    hp.endpoint = "ocr.tencentcloudapi.com"
    cp = ClientProfile()
    cp.httpProfile = hp
    return ocr_client.OcrClient(cred, settings.tencent_region, cp)


def _check_credentials() -> None:
    if not settings.tencent_secret_id or not settings.tencent_secret_key:
        raise AppError("未配置腾讯云 OCR 凭据（TENCENT_SECRET_ID/TENCENT_SECRET_KEY）")


def _to_base64(image_path: str | Path) -> str:
    image_path = Path(image_path)
    if not image_path.exists():
        raise AppError(f"图片不存在: {image_path}")
    return base64.b64encode(image_path.read_bytes()).decode()


def recognize_text(image_path: str | Path) -> list[str]:
    """通用印刷体识别，返回识别出的文字行列表。"""
    _check_credentials()
    logger.debug("OCR 识别: %s", Path(image_path).name)
    req = models.GeneralBasicOCRRequest()
    req.ImageBase64 = _to_base64(image_path)
    try:
        resp = _client().GeneralBasicOCR(req)
    except TencentCloudSDKException as exc:
        raise AppError(f"OCR 识别失败: {exc}") from exc
    return [item.DetectedText for item in resp.TextDetections]


def recognize_general_accurate(image_path: str | Path) -> list[str]:
    """通用印刷体识别（高精度版 GeneralAccurateOCR），返回文字行列表。"""
    _check_credentials()
    logger.debug("OCR 识别: %s", Path(image_path).name)
    req = models.GeneralAccurateOCRRequest()
    req.ImageBase64 = _to_base64(image_path)
    try:
        resp = _client().GeneralAccurateOCR(req)
    except TencentCloudSDKException as exc:
        raise AppError(f"OCR 识别失败: {exc}") from exc
    return [item.DetectedText for item in resp.TextDetections]


def recognize_idcard(image_path: str | Path, card_side: str | None = None) -> dict:
    """身份证识别，返回结构化字段。"""
    _check_credentials()
    logger.debug("OCR 识别: %s", Path(image_path).name)
    req = models.IDCardOCRRequest()
    req.ImageBase64 = _to_base64(image_path)
    if card_side:
        req.CardSide = card_side
    try:
        resp = _client().IDCardOCR(req)
    except TencentCloudSDKException as exc:
        raise AppError(f"身份证识别失败: {exc}") from exc
    return {
        "name": resp.Name,
        "sex": resp.Sex,
        "nation": resp.Nation,
        "birth": resp.Birth,
        "address": resp.Address,
        "id_num": resp.IdNum,
        "authority": resp.Authority,
        "valid_date": resp.ValidDate,
    }


def recognize_passport(image_path: str | Path) -> dict:
    """护照识别，返回结构化字段。"""
    _check_credentials()
    logger.debug("OCR 识别: %s", Path(image_path).name)
    req = models.PassportOCRRequest()
    req.ImageBase64 = _to_base64(image_path)
    try:
        resp = _client().PassportOCR(req)
    except TencentCloudSDKException as exc:
        raise AppError(f"护照识别失败: {exc}") from exc
    return {
        "passport_no": resp.PassportNo,
        "name": resp.Name,
        "nationality": resp.Nationality,
        "sex": resp.Sex,
        "date_of_birth": resp.DateOfBirth,
        "date_of_expiration": resp.DateOfExpiration,
        "issue_authority": resp.IssueAuthority,
    }


def recognize_biz_license(image_path: str | Path) -> dict:
    """营业执照识别，返回结构化字段。"""
    _check_credentials()
    logger.debug("OCR 识别: %s", Path(image_path).name)
    req = models.BizLicenseOCRRequest()
    req.ImageBase64 = _to_base64(image_path)
    try:
        resp = _client().BizLicenseOCR(req)
    except TencentCloudSDKException as exc:
        raise AppError(f"营业执照识别失败: {exc}") from exc
    return {
        "reg_num": resp.RegNum,
        "name": resp.Name,
        "capital": resp.Capital,
        "person": resp.Person,
        "address": resp.Address,
        "business": resp.Business,
        "type": resp.Type,
        "period": resp.Period,
    }
