<?php
namespace app\controller\api;

use app\exception\RepositoryException;
use app\model\BusinessCircle;
use app\model\Category;
use app\model\Recharge as RechargeModel;
use app\repository\AccountRepository;
use app\repository\BusinessRepository;
use app\repository\CouponRepository;
use app\repository\DictionaryRepository;
use app\repository\RechargeRepository;
use app\service\wx\WechatPay;
use app\validate\BusinessValidate;
use think\Collection;
use think\Exception;
use think\facade\Db;
use think\exception\ValidateException;
use app\model\{Account, Business as BusinessModel, Account as AccountModel, CouponMain};
use think\response\Json;
use function EasyWeChat\Kernel\Support\generate_sign;

/**
 * 商家端:商家
 *
 * Class Business
 * @package app\controller\api
 */
class Business extends Base
{

    protected $noNeedLogin = [
        'couponDetail',
    ];
    /**
     * 商家认证注册
     *
     * 重新编辑注册则覆盖之前的审核信息,并重新进行审核
     */
    public function registerBusiness()
    {
        $params = [
            'business_license'=> $this->request->param('business_license', ''),
            'background'=> $this->request->param('background', ''),
            'business_name'=> $this->request->param('business_name', ''),
            'business_subtitle'=> $this->request->param('business_subtitle', ''),
            'province'=> $this->request->param('province', ''),
            'city'=> $this->request->param('city', ''),
            'county'=> $this->request->param('county', ''),
            'business_address' => $this->request->param('business_address', ''),
            'lat'=> $this->request->param('lat', ''),
            'lng'=> $this->request->param('lng', ''),
            'business_circle_id' => $this->request->param('business_circle_id/d', 0),
            'agency_code'   => $this->request->param('agency_code', ''),
            'type'=> $this->request->param('type/d', 0),
            'contact_name'=> $this->request->param('contact_name', ''),
            'contact_phone'=> $this->request->param('contact_phone', ''),
        ];

        $accountId  = $this->request->user['user_id'] ?? 0;


        try {
            $validate   = new BusinessValidate();
            $busRepo    = BusinessRepository::getInstance();
            $dicRepo    = DictionaryRepository::getInstance();
            $accountRepo    = AccountRepository::getInstance();

            $account = $accountRepo->findById($accountId);
            if (empty($account)) {
                throw new ValidateException('无效请求!');
            }
            if ($account->type !== Account::type_consumer) {
                throw new ValidateException('您已经是商家或者员工,不能认证');
            }

            if (!$validate->scene('apiRegister')->check($params)) {
                throw new ValidateException($validate->getError());
            }

            $businessCategory   = $dicRepo->findBusinessTypeById($params['type']);
            if (empty($businessCategory)) {
                throw new ValidateException('请选择正确的商家分类信息!');
            }

            if ($params['business_circle_id'] > 0) {
                $businessCircle = $dicRepo->findBusinessCircleById($params['business_circle_id']);
                if (empty($businessCircle)) {
                    throw new ValidateException('请选择正确的商圈信息!');
                }
                $params['business_circle']  = $businessCircle['name'];
            }

            if (!empty($params['agency_code'])) {
                $agencyBusiness = $busRepo->findOneByWhere(['code'=> $params['agency_code'], 'is_agency'=> self::BOOL_TRUE, 'state' => BusinessModel::state_on]);
                if (empty($agencyBusiness) || $agencyBusiness['is_delete'] == self::BOOL_TRUE) {
                    throw new ValidateException('没有相关的代理商记录!');
                } elseif ($agencyBusiness['enable'] == self::BOOL_TRUE) {
                    throw new ValidateException('该代理商已被封禁!');
                }

                $params['is_assign']            = 1;
            }

            $business = null;
            if (isset($account['business_code']) && !empty($account['business_code'])) {
                $business = $busRepo->findOneByWhere(['code'=> $account['business_code']]);
            }

            $params['create_time']          = date('Y-m-d H:i:s');
            $params['is_delete']            = 0;
            $params['state']                = BusinessModel::state_reviewing;
            $params['enable']               = 0;
            $params['total_recharge']       = 0;
            $params['balance']              = 0;
            $params['is_agency']            = 0;
            $params['type_name']            = $businessCategory['name'];

            if ($business) {
                if ($business['state'] == BusinessModel::state_reviewing) {
                    throw new ValidateException('商户认证审批中,请勿重复提交!');
                }

                // 更新审批信息,重新审批
                $params['update_time']  = date('Y-m-d H:i:s');
                $business->save($params);

            } else {
                // 添加审批记录
                $businessCode   = createUuid();
                $params['code'] = $businessCode;
                $business = $busRepo->create($params);
                if (!$business) {
                    throw new RepositoryException('服务器繁忙!商户认证申请提交失败!');
                }

                $account->save(['business_code' => $businessCode]);
            }

            $result = $busRepo->formatFrontBusinessInfo($business->toArray());
            return $this->json(0, 'success', $result);
        } catch (ValidateException $e) {
            return $this->json(4001, $e->getError());
        } catch (RepositoryException | \Exception $e) {
            return $this->json(5001, '服务器繁忙!商户认证申请提交失败!');
        }
    }

    /**
     * 获取当前账号所属商家的信息
     * 适用范围:商户账号 或 商户员工账号
     */
    public function getMyBusinessInfo()
    {
        $accountId = $this->request->user['user_id'] ?? 0;

        try {
            $account    = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
                return $q->with(['business', 'parent']);
            });
            if (empty($account)) {
                return $this->json(4004, '无效请求!');
            }

            $result = [];
            if ($account['type'] == AccountModel::type_staff) {
                // 员工账号
                $businessCode   = $account['parent']['business_code'] ?? '';
                if (!empty($businessCode)) {
                    $business = BusinessRepository::getInstance()->findOneByWhere(['code' => $businessCode]);
                    if ($business) {
                        $result = $business->toArray();
                    }
                }

                $result = arrayKeysExcludeFilter($result, ['pay_account', 'total_recharge']);

            } elseif(!empty($account['business'])) {
                // 商户认证信息
                $result     = $account['business']->toArray();
            }

            if (count($result)) {
                $result     = DictionaryRepository::getInstance()->parseAreaText($result);
            }

            $result = arrayKeysExcludeFilter($result, ['update_time']);
            return $this->json(0, 'success', $result);
        } catch (\Exception $e) {
            return $this->json(5001, '商家信息查询失败!');
        }
    }

    /**
     * 获取商家信息(已认证通过的商户)
     * @return Json
     */
    public function getBusinessInfo()
    {
        $businessCode   = $this->request->param('businessCode/s', '');

        $busRepo        = BusinessRepository::getInstance();
        try {
            $business   = $busRepo->findOneByWhere(['code' => $businessCode, 'state' => BusinessModel::state_on]);
            if (empty($business)) {
                return $this->json(4004, '没有相关的商户!');
            }

            $list       = $business->toArray();
            $list       = DictionaryRepository::getInstance()->parseAreaText($list);
            $disableFields = ['is_delete', 'update_time', 'total_recharge', 'balance', 'is_assign', 'agency_code',
                'reason', 'pay_account', 'business_license'
            ];
            $result     = arrayKeysExcludeFilter($list, $disableFields);
            return $this->json(0, 'success', $result);
        } catch (\Exception $e) {
            return $this->json(5004, '商家信息查询失败!');
        }
    }


    /**
     * 获取商家类型
     * */
    public function getBusinessTypeList()
    {
        $data = Category::getList();
        return $this->json(1,"ok",$data);
    }
    /**
     * 获取商家类型
     * */
    public function getBusinessCircle()
    {
        $data = BusinessCircle::getList();
        return $this->json(1,"ok",$data);
    }

    /**
     * 商家优惠券详情
     * */
    public function couponDetail()
    {
        $accountId = $this->request->user['user_id'] ?? 0;
        $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
            return $q->with(['business', 'parent']);
        });

        $couponMainId = input("id/d");
        $couponMain = CouponMain::findOne(["id"=>$couponMainId]);
        if(empty($couponMain)){
            return $this->json(4001,"优惠券不存在");
        }
        if(!$business = BusinessRepository::getInstance()->findOneByWhere(["code"=>$couponMain["business_code"]])){
            return $this->json(4001,"优惠券商家信息不存在");
        }

        $list       = $business->toArray();
        $list       = DictionaryRepository::getInstance()->parseAreaText($list);

        $data       = [];

        $data["businessAddress"]        = $list['province_text'] . $list['city_text'] . $list['county_text'] . $business['business_address'];
        $data["businessName"]           = $list['business_name'];
        $data["count"]                  = $couponMain->count;
        $data["couponName"]             = $couponMain->name;
        $data["deductionMoney"]         = $couponMain->deduction_money;
        $data["startTime"]              = $couponMain->start_time;
        $data["endTime"]                = $couponMain->end_time;
        $data["id"]                     = $couponMain->id;
        $data["imageUrl"]               = $this->request->domain(). $couponMain->image_url;
        $data["intro"]                  = $couponMain->intro;//简介
        $data["lat"]                    = $couponMain->lat;
        $data["lng"]                    = $couponMain->lng;
        $data["money"]                  = $couponMain->money;
        $data["usingRule"]              = DictionaryRepository::getInstance()->getUsingRuleByCouponMainId($couponMain->id);
        $data["punishRule"]             = '';//处罚规则 已取消

        //未登录可以领取 0可领取 1已领取
        if (empty($account)) {
            $data["receiveStatus"]  = CouponMain::COMMON_OFF;//领取状态
        }else{
            $data["receiveStatus"]  = AccountRepository::getInstance()->getCouponReceiveStatus($account->user_code,$couponMain);//领取状态
        }
        $data["receivedCount"] =  $couponMain->received_count;//已领取数量
        $data["typeName"] =  $couponMain->type_name;

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



    /**
     * 检查是有已经有商家审核了
     * */
    public function checkAuth()
    {
        $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 (isset($account->business) && !empty($account->business) && in_array($account->business->state, [BusinessModel::state_off, BusinessModel::state_reviewing,])) {
            if ($account->business->state == BusinessModel::state_off) {
                return $this->json(4001, "认证被退回,请重新填写资料:" . $account->business->reason,["business"=>$account->business]);
            }
            return $this->json(4001, " 正在认证中请耐心等待",["business"=>$account->business]);
        }

        //检查有没有加入一个商家的申请
        //TODO....

        return $this->json();
    }


    /**
     * 充值
     * */
    public function recharge()
    {
        $accountId  = $this->request->user['user_id'] ?? 0;
        $money      = input("money/f",1);
        $account = AccountRepository::getInstance()->findById($accountId, [], function ($q) {
            return $q->with(['business', 'parent']);
        });
        if(empty($account)||empty($account->business)){
            return  $this->json(6001,"登录失效");
        }
        if ($money <= 0) {
            return  $this->json(4001,"充值金额有误");
        }
        $money = floor($money*100)/100;
        Db::startTrans();
        try {

            //创建充值订单
            if (!$order = RechargeRepository::getInstance()->createOrder($account->business_code, $account->open_id,$money)) {
                throw new RepositoryException('订单创建失败,请稍后重试');
            }
            //生成支付
            $time = time();
            $res = WechatPay::getInstance()->order->unify([
                'body' => '商家充值',
                'openid' => $account->open_id,
                'out_trade_no' => $order->order_num,
                'total_fee' => $money * 100,
                'trade_type' => 'JSAPI',
                'timeStamp' => $time,
                'product_id' => $order->id,
                'sign_type' => "MD5",
                'notify_url' => $this->request->domain() . "/api/recharge/notify.html",
            ]);

            if (!isset($res['prepay_id'])) {
                throw new RepositoryException('订单创建失败,请稍后重试');
            }
            $payData = [
                "appId" =>config("wechat.applets_appId"),
                "timeStamp" =>$time."",
                'nonceStr'  => randomStr(0,16),
                'package'   => 'prepay_id='.$res['prepay_id'],
                "signType"  =>'MD5',
            ];

            $payData['sign'] = generate_sign($payData, config("wechat.key"));
            $payData['order_num'] = $order->order_num;

            Db::commit();
            return $this->json(0, "success", [
                "payData" => $payData
            ]);

        }catch (RepositoryException $e){
            Db::rollback();
            return  $this->json(4001,"发起充值失败");
        }catch (Exception $e){
            echo $e->getMessage();
            Db::rollback();
            return  $this->json(5001,"发起充值失败");
        }

    }

}