<?php

namespace App\Servers;

use App\Models\DrugReportInfo;
use App\Models\DrugReportAss;
use App\Models\DrugReport;
use App\Servers\Aliyun\Oss;
use App\Servers\QueryDrugReportService;
use Carbon\Carbon;
use App\Facades\Servers\Logs\Log;

use GuzzleHttp\Client;

class SyncDrugReportService
{
    /** @var string 查询上游企业的待签收药检报告信息 */
    const QUERY_DRUG_REPORT = 'querydrugreport';

    /** @var string 查询上传报告信息接口 */
    const QUERY_SEAL_DRUG_REPORT = 'querysealdrugreport';

    /** @var string 一张网报告操作日志 */
    const DRUG_REPORT_OPT_HISTORY = 'drugreport.opt.history';
    /** @var string 查询上游出库单 */
    const QUERY_DRUG_REPORT_ASS = 'querydrugreportass';

    /** @var Log */
    protected $log;

    /** @var QueryDrugReportService */
    protected $queryDrugReportService;
    protected   $time;



    /**
     * 分批次同步数据
     * @param string $source
     * @param bool $isFull
     * @param string $startTime
     * @param string $endTime
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function syncDrugReport(string $source, bool $isFull, string $startTime, string $endTime = '', int $page = 1, int $pageSize = 20,$isSeal=1)
    {
        $isFull     = true;
        $total = 0;
        Log::error('syncDrug','开始全量同步：');
        $time     = time();
        $oldEndTime = $endTime;
        if (empty($endTime)) {
            $endTime = Carbon::parse($startTime)->copy()->endOfMonth()->toDateTimeString();
        }
        $this->queryDrugReportService = new QueryDrugReportService();
        $count  = 0;
        do {
            $month = Carbon::parse($startTime)->copy()->format('Ym');
            try {
                if (Carbon::parse($startTime)->isFuture()) {
                    Log::error('syncDrug','时间大于当前时间，同步终止：');
                    break;
                }
                sleep(1);
                // 分批次拉取数据
                $data = $this->queryDrugReport($source, $startTime, $endTime, $page, $pageSize, $isSeal);
                $total_num = $data['total_num'];
                $data = $data['data'];
                if ($page == 1){
                    $count += $total_num;
                }
                if (empty($data)) {
                    if ($isFull) {
                        $next = Carbon::parse($startTime)->copy()->addMonth();
                        $startTime = $next->startOfMonth()->toDateTimeString();
                        $endTime = $next->endOfMonth()->toDateTimeString();
                        $page = 1;
                        continue;
                    }
                    break;
                }
                var_dump($startTime,$endTime,$count,$total_num,$page);
                // 处理并保存数据
                $saveCount = $this->saveDrugReport($source, $data, $isSeal);
                $total += $saveCount;

                // 检查是否还有更多数据
                if (count($data) <> $pageSize) {
                    if ($isFull) {
                        $next = Carbon::parse($startTime)->copy()->addMonth();
                        $startTime = $next->startOfMonth()->toDateTimeString();
                        $endTime = $next->endOfMonth()->toDateTimeString();
                        $page = 1;
                        continue;
                    }
                    break;
                }

                $page++;

            } catch (\Exception $e) {
//                continue;
                break;
            }
        } while (true);

        return ['total'=>$total,'count'=>$count];
    }

    /**
     * 查询药检报告数据
     * @param string $source
     * @param string $startTime
     * @param string $endTime
     * @param int $page
     * @param int $pageSize
     * @return array
     * @throws \Exception
     */
    protected function queryDrugReport(string $source, string $startTime, string $endTime = '', int $page = 1, int $pageSize = 20, $isSeal=1): array
    {
        if (self::QUERY_DRUG_REPORT == $source) {
            return $this->queryDrugReportService->queryDrugReport($startTime, $endTime, $page, $pageSize);
        }

        if (self::QUERY_SEAL_DRUG_REPORT == $source) {
            return $this->queryDrugReportService->querySealDrugReport($startTime, $endTime, $page, $pageSize,$isSeal);
        }

        if (self::DRUG_REPORT_OPT_HISTORY == $source) {
            $startDate = Carbon::parse($startTime)->copy()->toDateString();
            $endDate = Carbon::parse($endTime)->copy()->toDateString();
            return $this->queryDrugReportService->drugReportOptHistory($startDate, $endDate, $page, $pageSize);
        }
        if (self::QUERY_DRUG_REPORT_ASS == $source) {
            //$startDate = Carbon::parse($startTime)->copy()->toDateString();
            //$endDate = Carbon::parse($endTime)->copy()->toDateString();
            return $this->queryDrugReportService->querydrugreportass($startTime, $endTime, $page, $pageSize);
        }
        return [];
    }

    /**
     * 处理并保存批次数据
     * @param string $source
     * @param array $data
     * @return int
     */
    protected function saveDrugReport(string $source, array $data, $isSeal=1)
    {
        try {
            if (self::DRUG_REPORT_OPT_HISTORY == $source) {
                return $this->processDrugReportOptHistory($data);
            }
            if (self::QUERY_DRUG_REPORT_ASS == $source) {
                $data   = $this->correctDrugReportAss($data);
                try {
                    $DrugReport = new DrugReport();
                    $a      = $DrugReport::query()->insert($data);
                    if (!$a){
                        Log::error('syncDrug','添加数据失败:'.$a,$data);
                    }
                }catch (\Throwable $exception){
                    Log::error('syncDrug','添加数据失败',$data);
                    dd($exception->getMessage());
                }
                return count($data);
            }
            if (self::QUERY_SEAL_DRUG_REPORT == $source) {
                $data   = $this->correctSealDrugReport($data,$isSeal);
                try {
                    $DrugReport = new DrugReportInfo();
                    $a      = $DrugReport::query()->insert($data);
                    if (!$a){
                        Log::error('syncDrug','添加数据失败:'.$a,$data);
                    }
                }catch (\Throwable $exception){
                    Log::error('syncDrug','添加数据失败',$data);
                    dd($exception->getMessage());
                }
                return count($data);
            }
            return DrugReportInfo::bulkUpsert($data);
        } catch (\Throwable $e) {
            Log::error('syncDrug','添加数据失败:'.$e->getMessage(),$data);
            return 0;
        }
    }

    /**
     * 处理【待签收】医药报告批次数据
     * @param array $data
     * @return array
     */
    protected function correctDrugReport(array $data): array
    {
        return array_map(function ($item) {
            return [
                'report_id' => $item['drug_report_id'] ?? '',
                'batch_no' => $item['produce_batch_no'] ?? '',
                'drug_id' => $item['drug_id'] ?? '',
                'physic_name' => $item['physic_name'] ?? '',
                'pkg_spec' => $item['pkg_spec'] ?? '',
                'prepn_spec' => $item['prepn_spec'] ?? '',
                'prepn_type_desc' => $item['prepn_type_desc'] ?? '',
                'bill_type' => $item['bill_type'] ?? 0,
                'bill_id' => $item['bill_id'] ?? '',
                'bill_detail_id' => $item['bill_detail_id'] ?? '',
                'bill_time' => $item['bill_time'] ?? '',
                'bill_code' => $item['bill_code'] ?? '',
                'produce_date' => $item['produce_date'] ?? '',
                'produce_ent_id' => $item['produce_ent_id'] ?? '',
                'produce_ent_name' => $item['produce_ent_name'] ?? '',
                'ass_ref_ent_id' => $item['ass_ref_ent_id'] ?? '',
                'from_ref_ent_id' => $item['from_ref_ent_id'] ?? '',
                'from_ent_name' => $item['from_ent_name'] ?? '',
                'report_url' => $item['sealed_report_url'] ?? '',
//                'file_name' => $item['file_name'] ?? '',
                'report_sign_status' => $item['drug_report_sign_status'] ?? '',
                'raw_data' => json_encode($item ?? [], JSON_UNESCAPED_UNICODE),
            ];
        }, $data);
    }

    /**
     * 处理【已签收】医药报告批次数据
     * @param array $data
     * @return array
     */
   /* protected function correctSealDrugReport(array $data): array
    {
        return array_map(function ($item) {
            return [
                'report_v2_id' => $item['drug_report_v2_id'] ?? '',
                'report_name' => $item['drug_report_name'] ?? '',
                'report_no' => $item['report_no'] ?? '',
                'report_date' => $item['report_date'] ?? '',
                'batch_no' => $item['batch_no'] ?? '',
                'drug_id' => $item['drug_ent_base_info_id'] ?? '',
                'physic_name' => $item['physic_name'] ?? '',
                'prod_code' => $item['prod_code'] ?? '',
                'pkg_spec' => $item['pkg_spec'] ?? '',
                'prepn_spec' => $item['prepn_spec'] ?? '',
                'pkg_ratio_list' => json_encode($item['pkg_ratio_list'] ?? [], JSON_UNESCAPED_UNICODE),
                'seal_report_url' => $item['sealed_report_url'] ?? '',
                'seal_raw_data' => json_encode($item ?? [], JSON_UNESCAPED_UNICODE),
            ];
        }, $data);
    }*/

    /**
     * 处理医药报告操作批次数据
     * @param array $data
     * @return int
     */
    protected function processDrugReportOptHistory(array $data): int
    {
        $count = 0;

        foreach ($data as $item) {
            try {
                // 操作类型（insertReport：新增报告、deleteReport：删除报告、sealReport：报告签章、updateReport：报告更新）
                $optType = $item['opt_type'];

                $drugReportInfo = DrugReportInfo::query()->where([
                    'batch_no' => $item['batch_no'],
                    'drug_id' => $item['drug_id'],
                ])->first();

                if (empty($drugReportInfo)) {
                    $drugReportInfo = DrugReportInfo::create([
                        'batch_no' => $item['batch_no'],
                        'drug_id' => $item['drug_id'],
                        'report_v2_id' => $item['report_v2_id'],
                        'report_date' => $item['report_date'],
                        'report_name' => $item['report_name'],
                        'report_no' => $item['report_no'],
                    ]);
                }

                switch ($optType) {
                    case "deleteReport":
                        $drugReportInfo->delete();
                        break;
                    case "sealReport":
                        $optTime = Carbon::parse($item['opt_time']);
                        $updateTime = Carbon::parse($drugReportInfo->update_time);
                        if ($optTime->gt($updateTime)) {
                            $drugReportInfo->is_sign = 1;
                            $drugReportInfo->is_seal = 1;
                            $drugReportInfo->sync_seal_opt = 1;
                        }
                        break;
                }

                $drugReportInfo->opt_raw_data = json_encode($item, JSON_UNESCAPED_UNICODE);
                $drugReportInfo->save();

                $count ++;
            } catch (\Exception $e) {
                log::info("保存数据项失败");
                continue;
            }
        }

        return $count;
    }
    /**
     * 处理【上游出库单】医药报告批次数据
     * @param array $data
     * @return array
     */
    public function correctDrugReportAss(array $data): array
    {
        $this->time = time();
        $list = [];
        foreach ($data as $item) {
            if (!empty($item['sealed_report_url'])) {
                $fileName = $item['physic_name'] . '_' . str_replace('/', '', $item['pkg_spec']) . '_' . $item['produce_batch_no'];
                $fileName               = uniqid($fileName.'_').'.pdf';
                try {
                    //上传报告pdf到oss
                    $Oss = new Oss();
                    $client = new Client(); // GuzzleHttp的客户端实例
                    $response = $client->get($item['sealed_report_url']); // 下载文件
                    $body = $response->getBody(); // 获取响应体
                    $content = (string)$body; // 转换为字符串内容
                    // 上传文件到OSS
                    $ossPath = 'path/' . date('Y') . '/' . date('m') . '/' . $fileName;
                    $res = $Oss->putObject($ossPath, $content);
                    $item['sealed_report_url'] = $res;
                    $item['file_name'] = $fileName;
                } catch (\Throwable $th) {
                    var_dump('上传oss报表失败:' . $th->getMessage());
                    Log::error('syncDrug/oss', '上传oss报表失败:' . $th->getMessage(), $item);
                }
            }
            $list[] = [
                'bill_id' => $item['bill_id'] ?? '',//单据ID
                'batch_no' => $item['produce_batch_no'] ?? '',//批号
                'drug_id' => $item['drug_id'] ?? '',//	药品ID
                'bill_type' => $item['bill_type'] ?? 0,//单据类型
                'bill_detail_id' => $item['bill_detail_id'] ?? '',//	单据明细ID
                'bill_time' => strtotime($item['bill_time']) ?? '',//单据时间
                'pkg_spec' => $item['pkg_spec'] ?? '',//包装
                'prepn_spec' => $item['prepn_spec'] ?? '',//制剂
                'physic_name' => $item['physic_name'] ?? '',//药品名
                'prepn_type_desc' => $item['prepn_type_desc'] ?? '',//剂型
                'drug_report_sign_status' => $item['drug_report_sign_status'] ?? '',//报告状态(0 ：待发送 2：待签收 3：已签收 4：已拒绝 7:对方已签收(更正待处理) 13:对方已拒绝(更正待签收))
                'bill_code' => $item['bill_code'] ?? '',//单据编码
                'produce_date' => strtotime($item['produce_date']) ?? '',//	生产日期
                'produce_ent_id' => $item['produce_ent_id'] ?? '',//生产企业ID
                'ass_ref_ent_id' => $item['ass_ref_ent_id'] ?? '',//委托企业
                'report_name' => $item['file_name'] ?? '',//报告名称
                'seal_report_url' => $item['sealed_report_url'] ?? '',//签章URL
                'from_ref_ent_id' => $item['from_ref_ent_id'] ?? '',//发货企业id
                'from_ent_name' => $item['from_ent_name'] ?? '',//发货企业名称
                'crt_date' => strtotime($item['crt_date']) ?? '',//单据上传日期
                'signed_time' => strtotime($item['signed_time']) ?? '',//签收时间
                'seal_status' => $item['seal_status'] ?? '',//盖章状态 0:待盖章 5:已盖章 6:同批号已盖章
                'report_id' => $item['drug_report_id'] ?? '',//报告ID
                'produce_ent_name' => $item['produce_ent_name'] ?? '',//生产企业
                'create_time' => $this->time,
                'update_time' => $this->time,
            ];
        }
        return  $list;
    }
    /**
     * 处理【本企业上传】医药报告批次数据
     * @param array $data
     * @return array
     */
    public function correctSealDrugReport(array $data,$isSeal=1): array
    {
        $this->time = time();
        $list = [];
        foreach ($data as $item) {
            if (!empty($item['sealed_report_url'])) {
                try {
                    $fileName = $item['drug_name'] . '_' . str_replace('/', '', $item['pkg_spec']) . '_' . $item['batch_no'];
                    $fileName               = uniqid($fileName.'_').'.pdf';
                    //上传报告pdf到oss
                    $Oss = new Oss();
                    $client = new Client(); // GuzzleHttp的客户端实例
                    $response = $client->get($item['sealed_report_url']); // 下载文件
                    $body = $response->getBody(); // 获取响应体
                    $content = (string)$body; // 转换为字符串内容
                    // 上传文件到OSS
                    $ossPath = 'local/' . date('Y') . '/' . date('m') . '/' . $fileName;
                    $res = $Oss->putObject($ossPath, $content);
                    $item['sealed_report_url'] = $res;
                    $item['file_name'] = $fileName;
                } catch (\Throwable $th) {
                    var_dump('上传oss报表失败:' . $th->getMessage());
                    Log::error('syncDrug/oss', '上传oss报表失败:' . $th->getMessage(), $item);
                }
            }
            $list[] =  [
                'report_id' => $item['report_id'] ?? '',
                'report_v2_id' => $item['drug_report_v2_id'] ?? '',
                'report_name' => $item['file_name'] ?? '',
                'report_no' => $item['report_no'] ?? '',
                'report_date' => $item['report_date'] ?? '',
                'batch_no' => $item['batch_no'] ?? '',
                'drug_id' => $item['drug_ent_base_info_id'] ?? '',
                'physic_name' => $item['drug_name'] ?? '',
                'prod_code' => $item['prod_code'] ?? '',
                'pkg_spec' => $item['pkg_spec'] ?? '',
                'prepn_spec' => $item['prepn_spec'] ?? '',
                'seal_report_url' => $item['sealed_report_url'] ?? '',
                'is_seal'       => $isSeal,
                'create_time'=>$this->time,
                'update_time'=>$this->time,
            ];
        }
        return  $list;
    }
}
