package shop.alien.store.util.ali.ocr.strategy;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ocr_api20210707.Client;
import com.aliyun.ocr_api20210707.models.*;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import shop.alien.entity.result.R;
import shop.alien.entity.store.OcrImageUpload;
import shop.alien.entity.store.StoreImg;
import shop.alien.store.service.StoreImgService;
import shop.alien.store.util.ali.ocr.AbstractOcrStrategy;
import shop.alien.util.common.constant.OcrTypeEnum;

import java.util.Date;
import java.util.Map;

/**
 * 营业执照OCR识别策略
 *
 * @author lyx
 * @date 2025/11/18
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class BusinessLicenseOcrStrategy extends AbstractOcrStrategy {

    private final StoreImgService storeImgService;

    @Override
    public R recognize(String imageId) throws Exception {

        // 从数据库中获取图片URL
        StoreImg storeImage = storeImgService.getById(imageId);
        String imageUrl = storeImage.getImgUrl();
        return recognizeUrl(imageUrl);
    }

    @Override
    public R recognizeUrl(String imageUrl) throws Exception {
        Client client = createOcrClient();
        RecognizeBusinessLicenseRequest request = new RecognizeBusinessLicenseRequest()
                .setUrl(imageUrl);

        try {
            RecognizeBusinessLicenseResponse response = client.recognizeBusinessLicenseWithOptions(
                    request, new RuntimeOptions());
            RecognizeBusinessLicenseResponseBody body = response.getBody();

            if (body == null || body.getData() == null) {
                throw new Exception("OCR识别返回结果为空");
            }

            JSONObject jsonObject = JSONObject.parseObject(body.getData());
            log.info("营业执照OCR识别成功: {}", jsonObject.getJSONObject("data"));
            return R.data(jsonObject.getJSONObject("data"));

        } catch (TeaException error) {
            handleOcrException(error, "营业执照识别失败");
            return R.fail("营业执照识别失败");
        } catch (Exception error) {
            handleOcrException(error, "营业执照识别异常");
            return R.fail("营业执照识别异常");
        }
    }

    @Override
    public R recognizeParams(Map<String, String> params) throws Exception {
        String[] imageUrls = params.get("imageUrls").split(",");
        JSONArray resultArray = new JSONArray();
        for (String imageUrl : imageUrls) {
            Client client = createOcrClient();
            RecognizeBusinessLicenseRequest request = new RecognizeBusinessLicenseRequest()
                    .setUrl(imageUrl); // 默认识别正面，可根据需要修改为 "back" 识别反面
            try {
                RecognizeBusinessLicenseResponse response = client.recognizeBusinessLicenseWithOptions(
                        request, new RuntimeOptions());
                RecognizeBusinessLicenseResponseBody body = response.getBody();

                if (body == null || body.getData() == null) {
                    throw new Exception("OCR识别返回结果为空");
                }
                JSONObject jsonObject = JSONObject.parseObject(body.getData());
                log.info("营业执照OCR识别成功: {}", jsonObject.getJSONObject("data"));
                // 保存OCR图片上传记录
                OcrImageUpload ocrImageUpload = new OcrImageUpload();
                ocrImageUpload.setUserId(params.get("userId"));
                ocrImageUpload.setStoreId(params.get("storeId"));
                ocrImageUpload.setStoreUserId(params.get("storeUserId"));
                ocrImageUpload.setImageUrl(imageUrl);
                ocrImageUpload.setOcrResult(jsonObject.getJSONObject("data").toJSONString());
                ocrImageUpload.setOcrType(OcrTypeEnum.BUSINESS_LICENSE.getCode());
                ocrImageUpload.setCreateTime(new Date());
                ocrImageUpload.setUpdateTime(new Date());
                super.saveOcrImage(ocrImageUpload);
                resultArray.add(jsonObject.getJSONObject("data"));
            } catch (TeaException error) {
                handleOcrException(error, "营业执照识别失败");
                return R.fail("营业执照识别失败");
            } catch (Exception error) {
                handleOcrException(error, "营业执照识别异常");
                return R.fail("营业执照识别异常");
            }
        }
        return R.data(resultArray);
    }

    @Override
    public R recognizeByBase64(String imageBase64) throws Exception {
        Client client = createOcrClient();
        // 将Base64字符串转换为字节数组，然后创建InputStream
        byte[] imageBytes = java.util.Base64.getDecoder().decode(imageBase64);
        java.io.InputStream imageInputStream = new java.io.ByteArrayInputStream(imageBytes);

        RecognizeBusinessLicenseRequest request = new RecognizeBusinessLicenseRequest()
                .setBody(imageInputStream);

        try {
            RecognizeBusinessLicenseResponse response = client.recognizeBusinessLicenseWithOptions(
                    request, new RuntimeOptions());
            RecognizeBusinessLicenseResponseBody body = response.getBody();

            if (body == null || body.getData() == null) {
                throw new Exception("OCR识别返回结果为空");
            }

            JSONObject jsonObject = JSONObject.parseObject(body.getData());
            log.info("营业执照OCR识别成功: {}", jsonObject.getJSONObject("data"));
            return R.data(jsonObject.getJSONObject("data"));

        } catch (TeaException error) {
            handleOcrException(error, "营业执照识别失败");
            return R.fail("营业执照识别失败");
        } catch (Exception error) {
            handleOcrException(error, "营业执照识别异常");
            return R.fail("营业执照识别异常");
        } finally {
            // 关闭流
            if (imageInputStream != null) {
                try {
                    imageInputStream.close();
                } catch (java.io.IOException e) {
                    log.warn("关闭输入流失败", e);
                }
            }
        }
    }

    @Override
    public String getType() {
        return OcrTypeEnum.BUSINESS_LICENSE.getCode();
    }
}

