package com.heyu.api.controller.car;

import com.heyu.api.baidu.handle.financial.BTrainTicketHandle;
import com.heyu.api.baidu.request.financial.BTrainTicketRequest;
import com.heyu.api.baidu.response.financial.BTrainTicketResp;
import com.heyu.api.controller.BaseController;
import com.heyu.api.data.annotation.NotIntercept;
import com.heyu.api.data.utils.ApiR;
import com.heyu.api.data.utils.R;
import com.heyu.api.request.car.TrainTicketRecognizeRequest;
import com.heyu.api.resp.car.RecognizeTrainTicketResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftrain_ticket&method=post
 *
 * 火车票识别（百度OCR）
 *
 * 支持识别各类火车票的全部字段，包括车票号码、乘车日期时间、出发站、到达站、车次号、席别、座位号、
 * 乘车人姓名、票价等信息。
 */
@Slf4j
@RestController
@RequestMapping("/train/ticket")
@NotIntercept
public class RecognizeTrainTicketController extends BaseController {

    @Autowired
    private BTrainTicketHandle bTrainTicketHandle;

    @PostMapping("/recognize")
    public R recognize(@RequestBody TrainTicketRecognizeRequest request) {
        long start = System.currentTimeMillis();

        if (request == null) {
            return R.error("请求参数不能为空");
        }
        if (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl())) {
            return R.error("imageBase64和imageUrl不能同时为空");
        }
        log.info("火车票识别-参数校验耗时:{}ms", System.currentTimeMillis() - start);

        long t1 = System.currentTimeMillis();
        BTrainTicketRequest bRequest = toBaiduRequest(request);
        log.info("火车票识别-构建百度请求耗时:{}ms", System.currentTimeMillis() - t1);

        long t2 = System.currentTimeMillis();
        ApiR<BTrainTicketResp> apiR = bTrainTicketHandle.handle(bRequest);
        long baiduCost = System.currentTimeMillis() - t2;
        log.info("火车票识别-调用百度OCR接口耗时:{}ms", baiduCost);

        if (apiR == null || !apiR.isSuccess() || apiR.getData() == null) {
            return R.error(thirdError(apiR));
        }

        long t3 = System.currentTimeMillis();
        BTrainTicketResp bResp = apiR.getData();
        BTrainTicketResp.WordsResultDTO wordsResult = bResp.getWordsResult();
        if (wordsResult == null) {
            log.info("火车票识别-未识别到火车票信息, 耗时:{}ms", System.currentTimeMillis() - start);
            return R.error("未识别到火车票信息");
        }

        RecognizeTrainTicketResp resp = toResp(wordsResult);
        log.info("火车票识别-结果映射耗时:{}ms", System.currentTimeMillis() - t3);

        log.info("火车票识别-总耗时:{}ms, 其中第三方(百度OCR):{}ms", System.currentTimeMillis() - start, baiduCost);
        return R.ok().setData(resp);
    }

    private BTrainTicketRequest toBaiduRequest(TrainTicketRecognizeRequest request) {
        BTrainTicketRequest bRequest = new BTrainTicketRequest();
        if (isNotBlank(request.getImageBase64())) {
            bRequest.setImageBase64(encodeParam(request.getImageBase64()));
        }
        if (isNotBlank(request.getImageUrl())) {
            bRequest.setImageUrl(encodeParam(request.getImageUrl()));
        }
        return bRequest;
    }

    private RecognizeTrainTicketResp toResp(BTrainTicketResp.WordsResultDTO words) {
        RecognizeTrainTicketResp resp = new RecognizeTrainTicketResp();

        resp.setName(words.getName());
        resp.setNumber(words.getTrainNum());
        resp.setDepartureStation(words.getStartingStation());
        resp.setDestination(words.getDestinationStation());
        resp.setLevel(words.getSeatCategory());
        resp.setSeat(words.getSeatNum());

        // 日期和时间合并：百度返回独立date和time字段，合并为"2017年08月05日 22:09开"格式
        StringBuilder dateTime = new StringBuilder();
        if (isNotBlank(words.getDate())) {
            dateTime.append(words.getDate());
        }
        if (isNotBlank(words.getTime())) {
            if (dateTime.length() > 0) {
                dateTime.append(" ");
            }
            dateTime.append(words.getTime());
        }
        resp.setDate(dateTime.length() > 0 ? dateTime.toString() : null);

        // 票价：百度返回字符串，转为Float
        if (isNotBlank(words.getTicketRates())) {
            try {
                resp.setPrice(Float.parseFloat(words.getTicketRates()));
            } catch (NumberFormatException e) {
                log.warn("票价解析失败:{}", words.getTicketRates());
                resp.setPrice(null);
            }
        }

        return resp;
    }

    private String encodeParam(String value) {
        try {
            return URLEncoder.encode(value, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("URL编码失败:{}", value, e);
            return value;
        }
    }

    private boolean isNotBlank(String value) {
        return value != null && value.trim().length() > 0;
    }
}
