<?php
// +----------------------------------------------------------------------
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
// +----------------------------------------------------------------------
// | Author: 萤火科技 <admin@yiovo.com>
// +----------------------------------------------------------------------
declare (strict_types=1);

namespace app\api\model;

use app\api\model\OrderGoods as OrderGoodsModel;
use app\api\service\User as UserService;
use app\common\enum\order\refund\AuditStatus as AuditStatusEnum;
use app\common\enum\order\refund\RefundStatus as RefundStatusEnum;
use app\common\enum\order\refund\RefundType as RefundTypeEnum;
use app\common\model\OrderRefund as OrderRefundModel;
use cores\exception\BaseException;

/**
 * 售后单模型
 * Class OrderRefund
 * @package app\api\model
 */
class OrderRefund extends OrderRefundModel
{
    /**
     * 隐藏字段
     * @var array
     */
    protected $hidden = [
        'store_id',
        'update_time'
    ];

    /**
     * 追加字段
     * @var array
     */
    protected $append = [
        'state_text',   // 售后单状态文字描述
    ];

    /**
     * 售后单状态文字描述
     * @param $value
     * @param $data
     * @return string
     */
    public function getStateTextAttr($value, $data): string
    {
        // 已完成
        if ($data['status'] == RefundStatusEnum::COMPLETED) {
            $text = [RefundTypeEnum::RETURN => '已同意退货并已退款', RefundTypeEnum::EXCHANGE => '已同意换货', RefundTypeEnum::RETURNPRICE => '已同意退款'];
            return $text[$data['type']];
        }
        // 已取消
        if ($data['status'] == RefundStatusEnum::CANCELLED) {
            return '已取消';
        }
        // 已拒绝
        if ($data['status'] == RefundStatusEnum::REJECTED) {
            // return '已拒绝';
            if ($data['type'] == RefundTypeEnum::RETURN) {
                return '已拒绝退货退款';
            } elseif ($data['type'] == RefundTypeEnum::EXCHANGE) {
                return '已拒绝换货';
            } else {
                return '已拒绝退款';
            }
        }
        // 进行中
        if ($data['status'] == RefundStatusEnum::NORMAL) {
            if ($data['audit_status'] == AuditStatusEnum::WAIT) {
                return '等待审核中';
            }
            if ($data['type'] == RefundTypeEnum::RETURN) {
                return $data['is_user_send'] ? '已发货,待平台确认' : '已同意退货,请及时发货';
            }
        }
        return $value;
    }

    /**
     * 获取用户售后单列表
     * @param int $state 售后单状态
     * @return \think\Paginator
     * @throws BaseException
     * @throws \think\db\exception\DbException
     */
    public function getList(int $state = -1): \think\Paginator
    {
        // 检索查询条件
        $filter = [];
        // 售后单状态
        $state > -1 && $filter[] = ['status', '=', $state];
        // 当前用户ID
        $userId = UserService::getCurrentLoginUserId();
        // 查询列表记录
        return $this->with(['orderGoods.image'])
            ->where($filter)
            ->where('user_id', '=', $userId)
            ->order(['create_time' => 'desc'])
            ->paginate(15);
    }

    /**
     * 获取当前用户的售后单详情
     * @param int $orderRefundId 售后单ID
     * @param bool $isWith 是否关联
     * @return static|null
     * @throws BaseException
     */
    public static function getDetail(int $orderRefundId, bool $isWith = false): ?self
    {
        // 关联查询
        $with = $isWith ? ['orderGoods' => ['image'], 'images.file', 'address', 'express'] : [];
        // 获取记录
        $detail = static::detail([
            'user_id' => UserService::getCurrentLoginUserId(),
            'order_refund_id' => $orderRefundId
        ], $with);
        empty($detail) && throwError('未找到该售后单');
        return $detail;
    }

    /**
     * 获取当前用户的售后单数量(进行中的)
     * @return int
     * @throws BaseException
     */
    public static function getCountByUnderway($dealer_order_ids = []): int
    {
        $userId = UserService::getCurrentLoginUserId();
        $query = (new static)->where('user_id', '=', $userId);
        if ($dealer_order_ids) {
            $query->whereIn('order_id', $dealer_order_ids);
        }
        return $query->where('status', '=', 0)
            ->count();
    }

    /**
     * 订单商品详情
     * @param int $orderGoodsId
     * @return OrderGoods|array|null
     * @throws BaseException
     */
    public function getRefundGoods(int $orderGoodsId)
    {
        $goods = OrderGoodsModel::detail($orderGoodsId);
        if (isset($goods['refund']) && !empty($goods['refund'])) {
            //是否已经同意
            if (!empty($goods['refund']['audit_status']) && $goods['refund']['audit_status'] == AuditStatusEnum::REVIEWED) {
                throwError('当前商品已申请售后');
            }
        }
        return $goods;
    }

    /**
     * 用户发货
     * @param array $data
     * @return bool|false
     */
    public function delivery(array $data): bool
    {
        if (
            $this['type'] != RefundTypeEnum::RETURN
            || $this['audit_status'] != AuditStatusEnum::REVIEWED
            || $this['is_user_send'] != 0
        ) {
            $this->error = '当前售后单不合法,不允许该操作';
            return false;
        }
        if ($data['expressId'] <= 0) {
            $this->error = '请选择物流公司';
            return false;
        }
        if (empty($data['expressNo'])) {
            $this->error = '请填写物流单号';
            return false;
        }
        return $this->save([
            'is_user_send' => 1,
            'send_time' => time(),
            'express_id' => (int)$data['expressId'],
            'express_no' => $data['expressNo'],
        ]);
    }

    /**
     * 新增售后单记录
     * @param int $orderGoodsId 订单商品ID
     * @param array $data 用户提交的表单数据
     * @return mixed
     * @throws BaseException
     */
    public function apply(int $orderGoodsId, array $data)
    {
        // 订单商品详情
        $goods = $this->getRefundGoods($orderGoodsId);
        if (!empty($goods['refund']) && !empty($goods['refund']['audit_status']) != AuditStatusEnum::REVIEWED) {
            if (empty($goods['refund']['order_refund_id'])) {
                throwError('当前记录数据异常');
            }
            return $this->transaction(function () use ($orderGoodsId, $data, $goods) {
                $order_refund_id = $goods['refund']['order_refund_id'];
                //更新售后单记录
                $this->where(['order_refund_id' => $order_refund_id])->update([
                    'type' => $data['type'],
                    'apply_desc' => $data['content'],
                    'audit_status' => AuditStatusEnum::WAIT,
                    'status' => 0,
                ]);
                // 记录凭证图片关系
                if (!empty($data['images'])) {
                    (new OrderRefundImage)->where(['order_refund_id' => $order_refund_id])->delete();
                    $this->saveImages((int)$this['order_refund_id'], explode(",", $data['images']));
                }
                return true;
            });
        }
        return $this->transaction(function () use ($orderGoodsId, $data, $goods) {
            // 新增售后单记录
            $this->save([
                'order_goods_id' => $orderGoodsId,
                'order_id' => $goods['order_id'],
                'user_id' => UserService::getCurrentLoginUserId(),
                'type' => $data['type'],
                'apply_desc' => $data['content'],
                'audit_status' => AuditStatusEnum::WAIT,
                'status' => 0,
                'store_id' => self::$storeId
            ]);
            // 记录凭证图片关系
            if (!empty($data['images'])) {
                $this->saveImages((int)$this['order_refund_id'], explode(",", $data['images']));
            }
            return true;
        });
    }

    /**
     * 记录售后单图片
     * @param int $orderRefundId 售后单ID
     * @param array $images 图片列表
     * @return void
     */
    private function saveImages(int $orderRefundId, array $images): void
    {
        // 生成评价图片数据
        $data = [];
        foreach ($images as $imageId) {
            $data[] = [
                'order_refund_id' => $orderRefundId,
                'image_id' => $imageId,
                'store_id' => self::$storeId
            ];
        }
        !empty($data) && (new OrderRefundImage)->addAll($data) !== false;
    }
}