<?php
namespace app\controller\api;

use app\exception\RepositoryException;
use app\model\Account;
use app\model\CouponMain;
use app\model\Score;
use app\repository\AccountRepository;
use app\repository\CouponRepository;
use app\validate\CouponRelease;
use app\validate\CouponUsingRule;
use think\Exception;
use think\facade\Config;
use think\facade\Db;
use think\facade\Log;

/**
 * 优惠卷相关
 * Class Coupon
 * @package app\controller\api
 */
class Coupon extends Base
{
    protected $noNeedLogin = [];

    /**
     * 我的优惠卷列表
     *
     * type in ['', 'notUsed', 'normal', 'used']
     */
    public function getCouponList()
    {
        $page       = $this->request->param('page/d', 1);
        $size       = $this->request->param('size/d', 10);
        $type       = $this->request->param('type', '');

        $page       = $page < 1 ? 1 : $page;
        $size       = $size < 1 ? 10 : $size;
        $accountCode    = $this->request->user['user_code'] ?? '';


        try {
            $whereMap   = [];
            $sortOrder  = ['received_time' => 'desc'];
            $fields     = [
                'id',
                'is_verificated as isVerificated',
                'money',
                'name as couponName',
                'business_code as businessCode',
                'end_time as endTime',
                'consumer_name as consumerName',
                'verificate_time as verificateTime',
                '(end_time > NOW()) as sort_weight'];

            $whereMap[] = ['consumer_code', '=', $accountCode];
            switch ($type) {
                case 'all':
                    // 全部持有优惠券
                    $sortOrder  = ['sort_weight' => 'desc', 'end_time' => 'asc'];
                    break;
                case 'notUsed':
                    // 未使用(包含已过期)
                    $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
                    $sortOrder  = ['sort_weight' => 'desc', 'end_time' => 'asc'];
                    break;
                case 'normal':
                    // 未使用且未过期
                    $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
                    $whereMap[] = ['end_time', '< TIME', date('Y-m-d H:i:s')];
                    break;
                case 'used':
                    // 已使用
                    $whereMap[] = ['is_verificated', '=', self::BOOL_TRUE];
                    $sortOrder  = ['verificate_time' => 'desc'];
                    break;
            }

            $res    = CouponRepository::getInstance()->findList($whereMap, $fields, $page, $size,function ($q){
                return $q->with(["couponMain","scoreModel"]);
            }, $sortOrder);

            $res['list'] ->each(function ($item){
                //重置优惠券名称
                if(isset($item->couponMain) && $item->couponMain){
                    $item->couponName =  $item->couponMain->name;
                }
                //是否已经打分过了
                if(isset($item->scoreModel) && $item->scoreModel){
                    $item->scored   =  true;
                    $item->score    =  $item->scoreModel->score;
                }else{
                    $item->scored   =  false;
                    $item->score    =  Score::COMMON_OFF;
                }

            });

            $res['list']    = multiTwoArrayKeysExcludeFilter($res['list']->toArray(), ['sort_weight']);
            return $this->json(0, 'success', $res);
        } catch (RepositoryException | \Exception $e) {
            return $this->json(5001, '优惠卷查询失败!');
        }
    }

    /**
     * 领取优惠券
     * */
    public function receiveCoupon()
    {
        $accountId = $this->request->user['user_id'] ?? 0;
        $lat = input("lat/f",0);
        $lng =  input("lng/f",0);
        $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
            return $q->with(['business', 'parent']);
        });
        if(empty($account)){
            return $this->json(6001,"无效的用户");
        }

        if ($lat <= 0 || $lng <= 0) {
            return $this->json(4001, "请授权定位");
        }

        $couponMainId = input("couponId/d", 0);
        $couponMain = CouponMain::findOne(["id" => $couponMainId],[],function ($q){
            //执行领取 开启锁
            return $q->with("business")->lock(true);
        });

        //检查优惠券状态
        $checkCouponMainReceiveStatus = CouponRepository::getInstance()->checkCouponMainReceiveStatus($couponMain);
        if( $checkCouponMainReceiveStatus !== true ){
            return $checkCouponMainReceiveStatus;
        }

        try {
            //检查是否可以领取  0可领取 1已领取
           AccountRepository::getInstance()->getCouponReceiveStatusText($account->user_code,$couponMain);//领取状态
        }catch (RepositoryException $e){
            return $this->json(4001,$e->getMessage());
        }



        //检查通过 执行领取
        $time = time();
        Db::startTrans();
        try {
            //写入领取记录
            $data = [
                "coupon_id"     =>$couponMain->id,
                "name"          =>$couponMain->name,
                "type_id"          =>$couponMain->type,
                "type_name"          =>$couponMain->type_name,
                "business_code"          =>$couponMain->business_code,
                "business_name"          =>$couponMain->business?$couponMain->business->business_name:'',
                "consumer_code"          =>$account->user_code,
                "consumer_name"          =>$account->nick_name,
                "money"          => $couponMain->money,
                "content"          => createUuid(),//未知作用
                "received_time"          => date("Y-m-d H:i:s",$time),
                "lat"          => $lat,
                "lng"          => $lng,
                "end_time"          => date($couponMain->end_time . " 00:00:00"),
                "edition"          => couponMain::COMMON_ON,//版本  未知作用
                "is_verificated"          => couponMain::COMMON_OFF,//版本  未知作用
            ];
            CouponRepository::getInstance()->receiveCoupon($data);
            Db::commit();
            return $this->json();
        }catch (RepositoryException $e){
            Log::error("优惠券领取失败RepositoryException:".$e->getMessage());
            Db::rollback();
            return $this->json(5001,"领取失败");
        }catch (Exception $e){
            Log::error("优惠券领取失败:".$e->getMessage());
            Db::rollback();
            return $this->json(5001,"领取失败");
        }

    }

    /**
     * 发布优惠券
     * */
    public function add()
    {
        $accountId = $this->request->user['user_id'] ?? 0;
        $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
            return $q->with(['business'=>function($q){
                $q->lock(true);
            }, 'parent']);
        });
        if(empty($account)){
            return  $this->json(6001,"登录失效");
        }
        if ($account->type == Account::type_consumer) {
            return $this->json(4001, "您不是商家");
        }

        if (!isset($account->business) || empty($account->business)) {
            return $this->json(4001, "商家信息错误");
        }
        $data = input();

        Config::load("extra/distribution_proportion","distribution_proportion");
        $distributionProportion = config("distribution_proportion");

        $totalC = $distributionProportion['agency'] + $distributionProportion['admin'] + $distributionProportion['consumer'];
        if ($totalC != 100) {
            return $this->json(5002, "系统设置分配比例总和不等于100,不能发布");
        }

        //验证通过  不管是商家还是工作人员  都可以发布优惠券
        $couponMain = [
            "name"                  => $data['name'] ?? '',
            "business_code"         => $account->business->code,
            "money"                 => $data['money'] ?? 0,
            "type"                  => $data['type'] ?? 0,
            "count"                 => $data['count'] ?? 0,
            "type_name"             => $data['type_name'] ?? '',
            "start_time"            => $data['start_time'] ?? '',
            "end_time"              => $data['end_time'] ?? '',
            "deduction_money"       => $data['deduction_money'] ?? '',
            "image_url"             => $data['image_url'] ?? '',
            "intro"                 => $data['intro'] ?? '',
            "status"                => CouponMain::status_on,
            "on_shelf"              => CouponMain::on_shelf_off,//默认下架  后天审核上架
            "commission_agency"     => $distributionProportion['agency'],
            "commission_admin"      => $distributionProportion['admin'],
            "commission_consumer"   => $distributionProportion['consumer'],
        ];

        $usingRule = input("using_rule/a");

        $validate = new CouponRelease();
        if (!$validate->check($couponMain)) {
            return $this->json(4001, $validate->getError());
        }

        $usingRuleValidate = new CouponUsingRule();
        if (!$usingRuleValidate->check($usingRule)) {
            return $this->json(4001, $usingRuleValidate->getError());
        }
        //验证通过
        $couponMain['business_type']    = $account->business['type'];
        $couponMain['business_name']    = $account->business['business_name'];
        $couponMain['lng']              = $account->business['lng'];
        $couponMain['lat']              = $account->business['lat'];
        $couponMain['create_time']      = date("Y-m-d H:i:s");

        //保留两位小数
        $couponMain['money'] = floor($couponMain['money'] * 100) / 100;
        $totalMoney = $couponMain['money'] * $couponMain['count'];

        if ($account->business["balance"] < $totalMoney) {
            return $this->json(4001, '商家余额不足');
        }

        Db::startTrans();
        try {
            CouponRepository::getInstance()->releaseCouponMain($couponMain, $totalMoney, $usingRule);
            Db::commit();
            return $this->json();
        } catch (RepositoryException $e) {
            Db::rollback();
            return $this->json(5001, "发布失败" . $e->getMessage());
        } catch (\think\Exception $e) {
            Db::rollback();
            return $this->json(5002, "发布失败" . $e->getMessage());
        }
    }

    /**
     * 商家管理优惠券
     * */
    public function getPageList()
    {
        $accountId = $this->request->user['user_id'] ?? 0;
        $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
            return $q->with(['business', 'parent']);
        });
        if(empty($account)){
            return  $this->json(6001,"登录失效");
        }
        if ($account->type == Account::type_consumer) {
            return $this->json(4001, "您不是商家");
        }

        if (!isset($account->business) || empty($account->business)) {
            return $this->json(4001, "商家信息错误");
        }

        $page       = $this->request->param('page/d', 1);
        $size       = $this->request->param('rows/d', 10);
        $page       = $page < 1 ? 1 : $page;
        $size       = $size < 1 ? 10 : $size;
        $keyword    = $this->request->param('key/s',"");
        $businessCode    = $account->business_code;

        try {
            $whereMap   = [];
            $sortOrder  = ['sort' => 'desc'];
            $whereMap[] = ["business_code" ,"=", $businessCode ];
            if(!empty($keyword)){
                $whereMap[] = ["name" ,"like", "%{$keyword}%" ];
            }
            $res    = CouponRepository::getInstance(new CouponMain())->findList($whereMap, [], $page, $size,function ($q){
                return $q->with(["usingRule","couponType"]);
            }, $sortOrder);
            $time = time();
            $res['list'] ->each(function ($item) use($time){
                //已使用张数
                $item->usingCount = CouponRepository::getInstance()->getCouponMainUsingCount($item->id);
                if(strtotime($item->start_time) <= $time && strtotime($item->end_time) >= $time){
                    $item->conduct   = true;
                }else{
                    $item->conduct   = false;
                }

            });

            return $this->json(0, 'success', $res["list"]);
        } catch (RepositoryException | \Exception $e) {
            echo $e->getMessage();
            return $this->json(5001, '优惠卷查询失败!');
        }
    }

    /**
     * 优惠券的领取  使用记录列表
     * */
    public function getShopCouponList()
    {
        $accountId = $this->request->user['user_id'] ?? 0;
        $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
            return $q->with(['business', 'parent']);
        });
        if(empty($account)){
            return  $this->json(6001,"登录失效");
        }
        if ($account->type == Account::type_consumer) {
            return $this->json(4001, "您不是商家");
        }

        if (!isset($account->business) || empty($account->business)) {
            return $this->json(4001, "商家信息错误");
        }

        $couponMainId  = input("couponId/d");

        $couponMain = CouponMain::findById($couponMainId);

        if(empty($couponMain)){
            return $this->json(4001, "优惠券不存在");
        }
        if($couponMain->business_code != $account->business->code){
            return $this->json(4001, "优惠券参数信息错误");
        }

        $page       = $this->request->param('page/d', 1);
        $size       = $this->request->param('rows/d', 10);
        $type       = $this->request->param('type/s', 10);
        $page       = $page < 1 ? 1 : $page;
        $size       = $size < 1 ? 10 : $size;
        $sortOrder      = ["id"=>"desc"];
        $whereMap = [
            ["coupon_id","=",$couponMainId]
        ];
        switch ($type) {
            case 'all':
                // 全部持有优惠券
                $sortOrder  = [ 'end_time' => 'asc'];
                break;
            case 'notUsed':
                // 未使用(包含已过期)
                $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
                $sortOrder  = ['end_time' => 'asc'];
                break;
            case 'normal':
                // 未使用且未过期
                $whereMap[] = ['is_verificated', '=', self::BOOL_FALSE];
                $whereMap[] = ['end_time', '< TIME', date('Y-m-d H:i:s')];
                break;
            case 'used':
                // 已使用
                $whereMap[] = ['is_verificated', '=', self::BOOL_TRUE];
                $sortOrder  = ['verificate_time' => 'desc'];
                break;
        }
        $field = ["is_verificated","received_time","verificate_time","consumer_code"];
        $data  = CouponRepository::getInstance()->findList($whereMap,$field,$page,$size,function($q){
            return $q->with(["account"=>function($q){
                $q->field(["nick_name","avatar_url","gender","user_code"]);
            }]);
        },$sortOrder);

        //未使用
        $data["allNum"]     = $data["total"];
        $data["unUsedNum"]  = CouponRepository::getInstance()->getModel()->where(['is_verificated' => self::BOOL_FALSE,"coupon_id"=>$couponMainId])->count();
        $data["usedNum"]    = CouponRepository::getInstance()->getModel()->where(['is_verificated' => self::BOOL_TRUE ,"coupon_id"=>$couponMainId])->count();

        return $this->json(0,"success",$data);


    }
}