<?php

namespace app\traits\account;

use app\exception\ApiRedirectException;
use app\exception\RepositoryException;
use app\model\Account;
use app\model\AccountCoupon;
use app\model\AccountRecord;
use app\model\Coupon;
use app\model\Express;
use app\repository\AccountRepository;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\Model;
use think\Paginator;

/**
 * 优惠券相关
 *
 * Trait CouponTrait
 * @package app\traits\order
 */
trait CouponTrait
{
    /**
     * 领取优惠券
     *
     * @param int $accountId
     * @param int $couponId
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     * @throws RepositoryException
     * @throws ApiRedirectException
     */
    public function getCoupon(int $accountId, int $couponId)
    {

        if (!$coupon = Coupon::where('id', $couponId)->lock(true)->find()) {
            throw new RepositoryException('优惠券不存在或已下架');
        }

        if (!empty($coupon['deleted_at'])) {
            throw new RepositoryException('优惠券不存在或已下架');
        }

        if (!$account = Account::findById($accountId)) {
            throw new RepositoryException('请先登录');
        }

        if ($coupon['remain'] <= 0) {
            throw new RepositoryException('优惠券已领完');
        }

        if ($coupon['end_at'] <= date('Y-m-d H:i:s')) {
            throw new RepositoryException('优惠券已过期');
        }

        if (AccountCoupon::where('coupon_id', $couponId)->where('account_id', $accountId)->count() > 0) {
            throw new RepositoryException('您已领过此券');
        }

        if ($account['phone_active'] != Account::COMMON_ON) {
            throw new ApiRedirectException('请先完善账号资料');
        }

        AccountCoupon::create([
            'account_id' => $accountId,
            'coupon_id' => $couponId,
            'status' => AccountCoupon::STATUS_NORMAL,
            'is_taste' => (int)($coupon['type'] == Coupon::TYPE_TASTE),
            'created_at' => date('Y-m-d H:i:s'),
        ]);

        $coupon->inc('receive')->dec('remain')->update();
    }

    /**
     * 用户优惠券详情
     *
     * @param int $accountId
     * @param int $couponId
     */
    public function userCouponInfo(int $accountId, int $couponId)
    {
        return AccountCoupon::findOne(['account_id' => $accountId, 'coupon_id' => $couponId], [], function ($q) {
            return $q->with(["coupon"]);
        });
    }

    /**
     * 获取个人优惠券
     *
     * @param int $accountId
     * @param string $status 默认normal=未使用
     * @param int $page
     * @param int $size 0 不限 获取全部
     * @return AccountCoupon[]|array|Collection
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function couponList(string $status = AccountCoupon::STATUS_NORMAL, int $accountId = 0, int $page = 1, int $size = 0)
    {
        $normalList = AccountCoupon::with(['coupon'])->where('account_id', $accountId)
            ->where('status', AccountCoupon::STATUS_NORMAL)
            ->select();
        $expiredList = $normalList->where('end_at', '<', date('Y-m-d H:i:s'))->column('id');
        if (!empty($expiredList)) {
            AccountCoupon::whereIn('id', $expiredList)->update(['status' => AccountCoupon::STATUS_INVALID]);
        }

        if (in_array($status, AccountCoupon::statusList())) {
            // 待查询的优惠券ID列表
            $withIds = AccountCoupon::where('account_id', $accountId)
                ->when(!empty($status), function ($q) use ($status) {
                    $q->where('status', $status);
                })
                ->when($size > 0, function ($q) use ($page, $size) {
                    $q->page($page, $size);
                })
                ->order('created_at', 'desc')
                ->column('coupon_id');
            return Coupon::whereIn('id', $withIds)
                ->field('id,name,cover,type,condition,amount,begin_at,end_at')
                ->select();
        }

        if ($status == 'waiting') {
            //待领取 可领券的优惠券
            //排除所有领过优惠券
            $now = date('Y-m-d H:i:s');
            $hasIds = AccountCoupon::where('account_id', $accountId)->column('coupon_id');
            return Coupon::whereNotIn('id', $hasIds)
                ->whereNull('deleted_at')
                ->where('begin_at', '<', $now)
                ->where('end_at', '>', $now)
                ->where('remain', '>', 0)
                ->order('sort', 'desc')
                ->order('created_at', 'desc')
                ->field('id,name,cover,type,condition,amount,begin_at,end_at')
                ->select();
        }

        return new Collection();

    }

    /**
     * 检测并处理过期优惠券
     *
     * @param int $accountId
     */
    public function checkExpire(int $accountId)
    {
        $accountCouponList = AccountCoupon::where('account_id', $accountId)
            ->where('status', AccountCoupon::STATUS_NORMAL)
            ->column('coupon_id');
        $expiredList = Coupon::whereIn('id', $accountCouponList)
            ->where('end_at', '<=', date('Y-m-d H:i:s'))
            ->column('id');
        if (!empty($expiredList)) {
            AccountCoupon::where('account_id', $accountId)
                ->whereIn('coupon_id', $expiredList)
                ->save([
                    'status' => AccountCoupon::STATUS_INVALID,
                ]);
        }
    }

    /**
     * 创建一个体验券展示二维码
     *
     * @param int $accountId
     * @param int $couponId
     */
    public function createExperienceCouponQR($accountId, $couponId)
    {
        return md5($accountId . AccountCoupon::CODE_SALT . $couponId);
    }

    /**
     * 验证一个体验券展示二维码
     *
     * @param int $accountId
     * @param int $couponId
     * @param string $secret
     */
    public function checkExperienceCouponQR($accountId, $couponId, $secret)
    {
        return ($secret == md5($accountId . AccountCoupon::CODE_SALT . $couponId)) ? true : "秘钥核验失败";
    }


}