<?php

namespace app\traits\order;

use app\exception\RepositoryException;
use app\model\OrderExpress;
use app\repository\OrderRepository;
use app\service\Kd100;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;

/**
 * 订单快递配送日志记录
 *
 * Trait ExpressLogTrait
 * @package app\traits\order
 */
trait ExpressLogTrait
{
    /**
     * 查询订单快递配送记录
     *
     * @param  string  $orderCoding  订单编号
     * @return Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getExpressLogsByOrderCoding(string $orderCoding = ''): Collection
    {
        return OrderExpress::where('coding', $orderCoding)->select();
    }


    /**
     * 根据订单物流单号查询配送记录
     * @param  string  $orderCoding  订单编号
     * @param  string  $com  快递公司编号,一律小写
     * @param  string  $nu  快递单号
     * @return array|Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function findExpressLogByNu(string $orderCoding, string $com, string $nu)
    {
        $whereMap = ['coding' => $orderCoding, 'nu' => $nu, 'com' => $com];
        return OrderExpress::where($whereMap)->find();
    }

    /**
     * 写入订单物流配送记录
     *
     * @param  string  $orderCoding  订单编号
     * @param  string  $com  快递公司编号,一律小写
     * @param  string  $nu  快递单号
     * @param  array  $data  快递100查询返回的数据
     * @throws RepositoryException
     */
    public function setExpressLog(string $orderCoding, string $com, string $nu, array $data)
    {
        try {
            if (empty($data)) {
                throw new RepositoryException('快递配送明细查询失败');
            }


            $state   = 0;
            $content = '';
            if (isset($data['result']) && $data['result'] === false) {
                throw new RepositoryException($data['message'] ?? '快递配送明细查询失败');
            } else {

                $state   = $data['state'] ?? 0;
                $content = json_encode($data['data'] ?? [], JSON_UNESCAPED_UNICODE);
            }

            $expr = $this->findExpressLogByNu($orderCoding, $com, $nu);
            if (empty($expr)) {
                OrderExpress::create([
                    'coding'     => $orderCoding,
                    'nu'         => $nu,
                    'com'        => $com,
                    'state'      => $state,
                    'content'    => $content,
                    'created_at' => date('Y-m-d H:i:s'),
                ]);

            } else {

                OrderExpress::updateById($expr['id'], [
                    'state'      => $state,
                    'content'    => $content,
                    'updated_at' => date('Y-m-d H:i:s'),
                ]);
            }

        } catch (\Exception $e) {
            OrderRepository::log('订单快递配送记录写入失败', $e, 'error', 'order');
            throw new RepositoryException('订单快递配送记录写入失败');

        } catch (RepositoryException $e) {
            throw $e;
        }
    }


    /**
     * 查询订单快递配送记录,并写入
     *
     * @param  string  $orderCoding
     * @param  string  $com
     * @param  string  $nu
     * @return array
     */
    public function handleOrderExpressLog(string $orderCoding, string $com, string $nu): array
    {
        $com = strtolower($com);

        $list        = [];
        $list['com'] = $com;
        $list['nu']  = $nu;

        try {
            $expressInfo = Kd100::query($com, $nu, true);
            if ($expressInfo) {
                $this->setExpressLog($orderCoding, $com, $nu, $expressInfo);
                if (isset($expressInfo['result']) && $expressInfo['result'] === false) {
                    $list['status']     = $expressInfo['returnCode'];
                    $list['state']      = 0;
                    $list['state_desc'] = $expressInfo['message'];
                    $list['data']       = [];
                } else {
                    $list['status']     = 200;
                    $list['state']      = $expressInfo['state'];
                    $list['state_desc'] = Kd100::state()[$expressInfo['state']] ?? '';
                    $list['data']       = $expressInfo['data'] ?? [];
                }
            }

            unset($expressInfo);
        } catch (RepositoryException | \Exception $e) {

        }

        return $list;
    }

}