<?php
/**
 *
 * @author：llbjj
 * @DateTime：2023/4/11 10:34
 * @Description：
 *
 */

namespace Application\Service\Baidu;

use Application\Common\Com;
use Application\Service\BaseService;
use Application\Service\Exceptions\InvalidArgumentException;
use Application\Service\Extension\Laminas;
use Application\Service\Extension\Uploader\adapter\Oss;
use Gumlet\ImageResizeException;
use Laminas\Stdlib\ArrayUtils;
use Psr\Container\ContainerInterface;

/**
 *
 * Class Ocr
 * @package Application\Service\Baidu
 *
 * @property $ocrClient
 */
class Ocr extends BaseService
{
    protected OcrClient $ocrClient;
    public function __construct(ContainerInterface $container)
    {
        parent::__construct($container);
        $this->_initOcr();
    }

    private function _getFileContent($data) :string
    {
        $imageFile = $data['annex_path'] ?? '';
        $bucket = $data['bucket'] ?? 'etracing';
        $style = $data['style'] ?? 'ocr';

        $fileUpLoader = new Oss(Laminas::$app->getConfig()['image_uploader'], $bucket);

        // style => ['iphone' => 最不清楚的, 'sample' => 还挺清楚的, 'origin' => 原图, 'thumb' => 高度为100的缩略图]
        $imageFile = $fileUpLoader->getSignUrl($imageFile, $style);

        [$imageContent] = file_get_contents($imageFile);

        return $imageContent;
    }

    /**
     * Notes:
     * User: llbjj
     * DateTime: 2023/8/14 13:28
     *
     * @param $data
     * @return array
     */
    public function basicGeneral($data) : array
    {
        $imageContent = self::_getFileContent($data);

        $ocrApi = 'basicGeneral';
        $ocrResult = $this->ocrClient->{$ocrApi}($imageContent, [
            'detect_direction' => "true" // 检测图片朝向
        ]);

        if(!isset($ocrResult['words_result'])) return [];
        if(empty($ocrResult['words_result'])) return [];

        return ['table' => array_column($ocrResult['words_result'], 'words')];
    }

    public function medicalReport(array $data): array
    {
        $imageContent = self::_getFileContent($data);

        $ocrResult = $this->ocrClient->medicalReport($imageContent);
        if(empty($ocrResult)) return [];
        if(!$ocrResult['Item_row_num']) return [];

        $date = array_flip(array_intersect(array_column($ocrResult['words_result']['CommonData'], 'word_name'), ['时间']));
        $dateKey = $date['时间'];
        $date = $ocrResult['words_result']['CommonData'][$dateKey]['word'];

        return $this->_formatMedicalReportResult($ocrResult['words_result']['Item'], $date);
    }

    /**
     * Notes: 自定义OCR识别
     * User: llbjj
     * DateTime: 2023/5/5 14:47
     *
     * @param array $data
     * @return array
     * @throws ImageResizeException
     * @throws UserException
     */
    public function custom(array $data): array
    {
        $templateId = $data['templateId'] ?? 0;
        $classifierId = $data['classifierId'] ?? 0;

        $imageContent = self::_getFileContent($data);

        if($templateId) {
            $ocrOptions = [
                'templateSign' => $templateId
            ];
        }else {
            if(!$classifierId) {
                return [];
            }

            $ocrOptions = [
                'classifierId' => $classifierId
            ];
        }

        $ocrResult = $this->ocrClient->custom($imageContent, $ocrOptions);

        if($ocrResult['error_code']) return [];

        return $ocrResult['data']['ret'] ? $this->_formatOcrCustomWordsResult($ocrResult['data']['ret']) : [];
    }

    private function _formatMedicalReportResult(array $ocrDatas, string $date = ''): array
    {
        $result['table'] = [];
        if(empty($ocrDatas)) return $result;
        $ocrHeader = (include __DIR__ . '/Config/Config.php')['ocrHeader'];
        $_ocrHeader = array_flip($ocrHeader);
        foreach($ocrDatas AS &$ocrData) {
            $word_name_arr = array_column($ocrData, 'word_name');

            $word_name_arr = array_intersect($word_name_arr, $ocrHeader);
            $_result = [
                'date' => $date
            ];
            foreach($word_name_arr as $key => $val) {
                if($val === '项目名称') $_result[$_ocrHeader[$val]] .= $ocrData[$key]['word'];
                else if($val === '项目代号') $_result[$_ocrHeader['项目名称']] = $ocrData[$key]['word'];
                else $_result[$_ocrHeader[$val]] = $ocrData[$key]['word'];
            }

            $result['table'][] = $_result;
        }
        return $result;
    }

    private function _formatOcrCustomWordsResult(array $ocrDatas, Bool $isMedicalTable = false): array
    {
        $result = [];
        $_result = [];
        if(empty($ocrDatas)) return $result;
        foreach($ocrDatas as &$ocrData) {
            $arrKey = $ocrData['word_name'];
            $arrKeyArr = explode('#', $arrKey);

            if(count($arrKeyArr) === 1) $_result[$arrKey] = $ocrData['word'];
            else {
                $row = $arrKeyArr[1];
                $key = $arrKeyArr[2];
                if(mb_strpos($arrKeyArr[2], '-1') !== false) {
                    $row = 100 + $row;
                    $key = mb_substr($arrKeyArr[2], 0, -2);
                }
                if($key === 'other' and !$isMedicalTable) continue;


                if(in_array($key, ['item_name'])) {
                    $preg = '/[0-9]*/';
                    $ocrData['word'] = preg_replace($preg, '', $ocrData['word'], 1);
                }
                $ocrData['word'] = str_ireplace(' ', '', $ocrData['word']);
                $result[$arrKeyArr[0]][$row][$key] = $ocrData['word'];
                if(!empty(array_filter(array_values($result[$arrKeyArr[0]][$row])))) {
                    $result[$arrKeyArr[0]][$row] = ArrayUtils::merge($result[$arrKeyArr[0]][$row], $_result);
                }else {
                    unset($result[$arrKeyArr[0]][$row]);
                }
            }
        }
        if(!empty($result['table'])) ksort($result['table']);

        return $result;
    }

    private function _initOcr() {
        $baiduConfig = $this->LocalService()->config['baidu'];

        $this->ocrClient = new OcrClient($baiduConfig['app_id'], $baiduConfig['api_key'], $baiduConfig['aecret_key']);
    }
}