<?php

namespace App\Models;

use App\Command\Log;
use EasyWeChat\Factory;
use Illuminate\Support\Facades\DB;
use App\Models\Good as GoodModel;
use App\Models\GoodSku;
use Exception;
use NwVVVS\AdapayCore\AdaPay\Payment;
use App\Models\OrderGoods;
use App\Models\OrderInfo;
use App\Models\UserPointChangeRec;

class Adapay
{
    public const APP_ID = 'app_c383f483-3c2a-41b6-8d21-7f597dde4c50';

    public function __construct()
    {
        /**
         * 商户接入AdaPay SDK时需要设置的初始化参数
         * 设置配置从配置文件读取
         */
        \NwVVVS\AdapayCore\AdaPay::init(dirname(__FILE__) . "/../../config/merchantConfig.json", "test");
    }

    //支付
    public function pay($order_title, $order_sn, $order_amount, $openid)
    {
        $payment = new \NwVVVS\AdapaySdk\Payment();

        # 支付设置
        $payment_params = [
            "app_id" => Adapay::APP_ID,
            "order_no" => $order_sn,
            "pay_channel" => "wx_lite",
            "pay_mode" => "delay",
            "time_expire" => date('YmdHis', time() + 300),
            "pay_amt" => $order_amount,
            "goods_title" => $order_title,
            "goods_desc" => $order_title,
            "description" => "",
            "notify_url" => env('API_URL') . '/pay-notify',
            "expend" => [
                "open_id" => $openid
            ]
        ];

        # 发起支付
        $payment->create($payment_params);

        # 对支付结果进行处理
        Log::add('--调起支付--', $payment->result);
        if ($payment->isError()) {
            //失败处理
            throw new \Exception($payment->result['error_msg']);
        } else {
            //成功处理
            Log::add('--支付参数--', json_decode($payment->result['expend']['pay_info'], true));
            $item = json_decode($payment->result['expend']['pay_info'], true);
            $item['timestamp'] = $item['timeStamp'];
            return $item;
        }
    }

    //支付回调-分账--》改成冻结,7天后解冻分账
    public function payNotify($params = [])
    {

        $adapay_tools = new \NwVVVS\AdapaySdk\AdapayTools(); //验证签名
        $post_data = json_decode($params['data'], 1);
        $post_data_str = json_encode($post_data, JSON_UNESCAPED_UNICODE);
        $post_sign_str = isset($params['sign']) ? $params['sign'] : '';
        # 先校验签名和返回的数据的签名的数据是否一致
        $sign_flag = $adapay_tools->verifySign($post_data_str, $post_sign_str);

        if (!$sign_flag) {
            Log::add('支付签名验证失败', []);
            return false;
        }
        $message = $post_data;
        $order_no = $message['order_no'];
        $orderObj = OrderInfo::where(['order_sn' => $order_no])->first();
        if (!$orderObj) {
            Log::add('订单不存在', [$order_no]);
            return false;
        }
        //支付完成后通知
        if ($message['status'] == "succeeded" && $orderObj->pay_status == 0) {
            DB::beginTransaction();
            try {
                //更新订单
                if ($orderObj->pay_status == 0) {
                    $orderObj->order_status = 1;
                    $orderObj->pay_status = 1;
                    $orderObj->freeze_stat = $message['freeze_stat'];
                    if ($orderObj->save()) {

                        if ($orderObj->pay_type=1) {//纯现金支付才返积分
                            //创建直推分积分记录
                            $this->createPointRecordByOrder($orderObj->id);
                        }

                        //更新商品销量、库存
                        $this->updateGoodsStock($orderObj); 

                        // //更新商品销量、库存
                        // $goodsList = OrderGoods::where("order_id", $orderObj->id)->get();
                        // foreach ($goodsList as $item) {
                        //     //Log::add('--订单商品对象--', $item);
                        //     $gid = $item->goods_id;
                        //     $attr_id = $item->attr_id;
                        //     $mer_id = $item->merchant_id;
                        //     $goods_number = $item->goods_number;


                        //     //更新此商品支付状态
                        //     $item->is_pay = 1;
                        //     $item->save();

                        //     $goodsObj = GoodModel::find($gid);
                        //     //更新商品规格库存
                        //     $attrObj = GoodSku::find($attr_id);
                        //     $attr_stock = ($attrObj->stock - $goods_number) >= 0 ? $attrObj->stock - $goods_number : 0;
                        //     $attrObj->stock = $attr_stock;
                        //     $attrObj->save();
                        //     //更新商品sku
                        //     $skuArr = json_decode($goodsObj->sku, true);
                        //     if ($skuArr['sku']) {
                        //         foreach ($skuArr['sku'] as $kk => $vv) {
                        //             if (isset($vv['attr_sn']) && $vv['attr_sn'] == $attrObj->attr_sn) {
                        //                 $skuArr['sku'][$kk]['stock'] = $attr_stock;
                        //             }
                        //         }
                        //         $goodsObj->sku = json_encode($skuArr, JSON_UNESCAPED_UNICODE);
                        //         $goodsObj->save();
                        //     }
                        //     //商户规格库存
                        //     $mgsObj = MerchantGoodSku::where(['goods_id' => $gid, 'attr_id' => $attr_id, 'merchant_id' => $mer_id])->first();
                        //     if ($mer_id && $mgsObj) {
                        //         $changeStock = ($mgsObj->stock >= $goods_number) ? $mgsObj->stock - $goods_number : 0;
                        //         $mgsObj->stock = $changeStock;
                        //         $mgsObj->save();
                        //     }
                        // }
                    }
                }
                //支付记录
                // 创建新的PaymentRecord对象
                $pay_cord = new PaymentRecord();

                // 查询是否已存在相同order_sn的支付记录
                $cordLog = $pay_cord->where(['order_sn' => $message['order_no']])->first();

                // 如果不存在记录,则创建新记录
                if (!$cordLog) {
                    // 设置支付记录的各项属性
                    $pay_cord->order_sn = $message['order_no'];       // 订单号
                    $pay_cord->other_order = $message['out_trans_id']; // 外部交易ID
                    $pay_cord->payment_id = $message['id'];          // 支付ID
                    $pay_cord->party_order_id = $message['party_order_id']; // 合作方订单ID
                    $pay_cord->money = $message['real_amt'];         // 实际支付金额
                    $pay_cord->uid = $orderObj->user_id;             // 用户ID

                    // 保存支付记录到数据库
                    $pay_cord->save();
                }
                DB::commit();
            } catch (\Exception $e) {
                Log::add('付款回调失败', $e);
                DB::rollBack();
                return false;
            }
        }
        //解冻通知
        $freeze_stat = $message['freeze_stat'] ?? '';
        if ($message['status'] == "succeeded" && $orderObj->freeze_stat == 'FREEZE') {
            if ($freeze_stat != 'UNFREEZE') {
                return false;
            }
            $orderObj->freeze_stat = 'UNFREEZE';

            $orderObj->save();

            // 调用汇付接口分账-6天后在解冻分账--》【改到updateOrderStatusToDiv里面去了】
            //$this->handlePaymentConfirmAndDivide($order_no, $orderObj, $payment_confirm);
        }
        return  true;
    }

    //创建支付确认
    public function createPaymentConfirm($payment_params)
    {
        $payment = new \NwVVVS\AdapaySdk\PaymentConfirm();

        # 发起支付确认创建
        $payment->create($payment_params);

        # 对支付确认创建结果进行处理
        if ($payment->isError()) {
            //失败处理
            Log::add('支付确认返回结果,失败', $payment->result);
            throw new Exception($payment->result['error_msg']);
        } else {
            //成功处理
            Log::add('支付确认返回结果,成功', $payment->result);
            return $payment->result;
        }
    }

    //查询支付对象列表
    public function queryList($payment_params)
    {
        $payment = new \NwVVVS\AdapaySdk\Payment();

        $payment->queryList($payment_params);
        # 对支付结果进行处理
        if ($payment->isError()) {
            //失败处理
            echo "<pre>";
            print_r($payment->result);
        } else {
            //成功处理
            echo "<pre>";
            print_r($payment->result);
            die;
        }
    }

    //退款
    public function refund($order_sn, $refund_no)
    {
        #初始化退款对象
        $payment = new \NwVVVS\AdapaySdk\PaymentReverse();

        $payLog = PaymentRecord::where('order_sn', $order_sn)->first();

        $payment_params = array(
            # 支付对象ID
            "payment_id" => $payLog->payment_id,
            # 商户app_id
            "app_id" => Adapay::APP_ID,
            # 撤销订单号
            "order_no" => $refund_no,
            # 撤销金额
            "reverse_amt" => $payLog->money,
            # 通知地址
            "notify_url" => env('API_URL') . '/refund-notify',
            # 撤销原因
            "reason" => "取消订单",
            # 扩展域
            "expand" => "",
            # 设备信息
            "device_info" => "",
        );
        # 发起支付撤销
        $payment->create($payment_params);
        # 对支付撤销结果进行处理
        if ($payment->isError()) {
            //失败处理
            Log::add('撤销失败', $payment->result);
            $msg = isset($payment->result['error_msg']) ? $payment->result['error_msg'] : '撤销失败';
            throw new \Exception($msg);
        }
        $result = $payment->result;
        Log::add('撤销成功', $result);

        //系统订单信息
        $orderObj = OrderInfo::where("order_sn", $order_sn)->first();

        //退款记录
        $refund_cord = new RefundRecord();
        $cordLog = $refund_cord->where(['refund_no' => $result['order_no']])->first();
        if (!$cordLog) {
            $refund_cord->order_sn = $order_sn;
            $refund_cord->refund_no = $result['order_no'];
            $refund_cord->payment_id = $result['id'];
            $refund_cord->money = $result['reverse_amt'];
            $refund_cord->uid = $orderObj->user_id;
            $refund_cord->save();
        }
        return true;
    }

    //退款回调
    public function refundNotify($params)
    {
        $adapay_tools = new \NwVVVS\AdapaySdk\AdapayTools();
        $post_data = json_decode($params['data'], 1);
        $post_data_str = json_encode($post_data, JSON_UNESCAPED_UNICODE);
        $post_sign_str = isset($params['sign']) ? $params['sign'] : '';
        # 先校验签名和返回的数据的签名的数据是否一致
        $sign_flag = $adapay_tools->verifySign($post_data_str, $post_sign_str);

        if (!$sign_flag) {
            //Log::add('退款签名验证失败', []);
            //return false;
        }
        $message = $post_data;
        $recordObj = RefundRecord::where(['refund_no' => $message['order_no'], 'payment_id' => $message['id']])->first();
        if (!$recordObj) {
            Log::add('退单记录不存在', [$message['order_no']]);
            return false;
        }
        if ($message['status'] == 'succeeded') {
            $recordObj->status = 1;
            $recordObj->save();
            return true;
        }
        return false;
    }

    //创建个人用户
    public function createMember($uid, $phone)
    {
        $member = new \NwVVVS\AdapaySdk\Member();
        $member_params = array(
            # app_id
            "app_id" => Adapay::APP_ID,
            # 用户id
            "member_id" => "mm_" . $uid,
            # 用户手机号
            "tel_no" => $phone,
        );
        # 创建
        $member->create($member_params);

        # 对创建用户对象结果进行处理
        if ($member->isError()) {
            //失败处理
            Log::add('创建用户失败-' . $uid, $member->result);
            return $member->result;
        } else {
            //成功处理
            Log::add('创建用户成功', $member->result);
            return $member->result;
        }
    }
    //创建企业用户
    public function createCompany($member_params)
    {

        $member = new \NwVVVS\AdapaySdk\CorpMember();

        # 创建企业用户
        $member->create($member_params);
        # 对创建企业用户结果进行处理
        if ($member->isError()) {
            //失败处理
            return $member->result;
        } else {
            //成功处理
            return $member->result;
        }
    }

    //创建结算对象
    public function createMemberSettleAccount($account_params)
    {
        $account = new \NwVVVS\AdapaySdk\SettleAccount();

        # 创建结算账户
        $account->create($account_params);
        # 对创建结算账户结果进行处理
        if ($account->isError()) {
            //失败处理
            Log::add('创建用户结算账户失败', $account->result);
            return $account->result;
        } else {
            //成功处理
            Log::add('创建用户结算账户成功', $account->result);
            return $account->result;
        }
    }


    //删除结算账户
    public function deleteSettleAccount($account_params)
    {
        $account = new \NwVVVS\AdapaySdk\SettleAccount();

        # 结算账户
        $account->delete($account_params);

        # 对删除结算账户结果进行处理
        if ($account->isError()) {
            //失败处理
            return $account->result;
        } else {
            //成功处理
            return $account->result;
        }
    }

    //查询账户余额
    public function queryBalance($account_params)
    {
        $account = new \NwVVVS\AdapaySdk\SettleAccount();
        # 查询账户余额
        $account->balance($account_params);
        # 对查询账户余额结果进行处理
        if ($account->isError()) {
            //失败处理
            return $account->result;
        } else {
            //成功处理
            return $account->result;
        }
    }


    // //手动分账修复错误数据--【转移到:OrderDivideRecordController::manualDivide】
    // public function queryBalance($account_params)
    // {
    //     $account = new \NwVVVS\AdapaySdk\SettleAccount();
    //     # 查询账户余额
    //     $account->balance($account_params);
    //     # 对查询账户余额结果进行处理
    //     if ($account->isError()) {
    //         //失败处理
    //         return $account->result;
    //     } else {
    //         //成功处理
    //         return $account->result;
    //     }
    // }














































    /**
     * 处理支付确认和分账逻辑
     * @param string $order_no 订单号
     * @param OrderInfo $orderObj 订单对象
     * @param \NwVVVS\AdapaySdk\PaymentConfirm $payment_confirm 支付确认对象
     * @return bool 处理结果
     * @throws Exception 处理失败时抛出异常
     */
    public static function handlePaymentConfirmAndDivide($order_no, $order_id)
    {
        $payment_confirm = new \NwVVVS\AdapaySdk\PaymentConfirm(); //支付确认
        //交易记录
        $prObj = PaymentRecord::where('order_sn', $order_no)->first();
        # 支付确认参数设置
        $payment_params = array(
            "payment_id" => $prObj->payment_id,
            "order_no" => 'payconfirm_' . date("YmdHis") . rand(100000, 999999),
            "confirm_amt" => $prObj->money,
            "description" => "",
            "div_members" => "" //分账参数列表 默认是数组List
        );

        DB::beginTransaction();
        try {
            //分账列表
            $divResult = OrderDivideRecord::divide($order_id, $payment_params['order_no']); //返回分账参数列表
            $payment_params['div_members'] = $divResult['div_members'];
            $payment_params['confirm_amt'] = $divResult['confirm_amt'];
            Log::add('发起分账支付确认-向汇付' . $order_no, $payment_params);

            # 发起支付确认创建
            $payment_confirm->create($payment_params);
            # 对支付确认创建结果进行处理
            if ($payment_confirm->isError()) {
                //失败处理
                Log::add('支付确认失败', $payment_confirm->result);
                $result = $payment_confirm->result;
                throw new Exception($result['error_msg']);
            } else {
                //成功处理
                Log::add('支付确认成功', $payment_confirm->result);
                $result = $payment_confirm->result;
                if ($result['status'] == 'succeeded') {
                    Log::add('分账成功', ['order_sn' => $order_no]);
                    //写入支付确认信息
                    (new HfPayconfirm())->add($payment_params, $result['fee_amt']);
                }
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::add('支付确认对象失败', $e->getMessage());
            DB::rollBack();
            return false;
        }
    }







    /**
     * 根据订单ID生成积分记录
     * @param int $order_id 订单ID
     * @return bool 处理结果
     * @throws Exception 处理失败时抛出异常
     * 
     * 功能说明:
     * 1. 根据订单ID获取订单信息
     * 2. 获取订单关联的用户信息
     * 3. 获取用户的直推和间推关系
     * 4. 为相关用户创建积分记录
     * 
     * 使用示例:
     * Adapay::createPointRecordByOrder(123);
     * 
     * 注意事项:
     * 1. 需要先创建UserPointRec模型类
     * 2. 积分计算逻辑需要根据业务需求调整
     */
    public static function createPointRecordByOrder($order_id)
    {
        DB::beginTransaction();
        try {
            // 获取订单信息
            $orderObj = OrderInfo::find($order_id);
            if (!$orderObj) {
                throw new Exception('订单不存在');
            }

            // 获取用户信息
            $userObj = User::find($orderObj->user_id);
            if (!$userObj) {
                throw new Exception('用户不存在');
            }

            // 获取直推和间推用户
            $spuid = $userObj->spuid; // 直推用户ID
            $second_spuid = $userObj->second_spuid; // 间推用户ID

            //获取订单商品积分
            $goodsObjList = DB::select('
                        SELECT 
                            log.id,
                            log.goods_id,
                            loi.order_amount,
                            log.goods_price,
                            log.goods_number,
                            lg.first_commission,
                            lg.second_commission,
                            -- 计算总的一级佣金
                            (log.goods_number*log.goods_price * lg.first_commission)/100 AS total_first_commission,
                            -- 计算总的二级佣金
                            (log.goods_number*log.goods_price *  lg.second_commission)/100 AS total_second_commission
                        FROM 
                            li_order_goods log 
                        LEFT JOIN 
                            li_order_info loi ON loi.id = log.order_id
                        LEFT JOIN 
                            li_goods lg ON lg.id = log.goods_id 
                        WHERE 
                            loi.pay_type=1 and log.order_id = ?;
            ', [$order_id]);

            if (!$goodsObjList) {
                Log::add('积分记录创建失败', [
                    'error' => '搜索为空',
                    'order_id' => $order_id
                ]);
            }

            // 购物车结算会有多个商品,多笔分佣,遍历商品列表,为每个商品创建积分记录
            foreach ($goodsObjList as $goodsObj) {
                //判断直推是否存在
                if ($spuid) {
                    // 计算直推用户的积分
                    $total_first_commission = $goodsObj->total_first_commission;
                    // 为直推用户创建积分记录
                    UserPointChangeRec::pointChangeRecord($spuid, $total_first_commission, 1, 1, 3, $order_id); // 
                }

                //判断间推是否存在
                if ($second_spuid) {
                    // 计算间推用户的积分
                    $total_second_commission = $goodsObj->total_second_commission;
                    // 为间推用户创建积分记录
                    UserPointChangeRec::pointChangeRecord($second_spuid, $total_second_commission, 1, 2, 3, $order_id); // 
                }
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::add('积分记录创建失败', [
                'error' => $e->getMessage(),
                'order_id' => $order_id
            ]);
            DB::rollBack();
            return false;
        }
    }



    /**
     * 根据订单对象更新商品库存
     * 
     * 功能说明:
     * 1. 根据订单对象获取订单商品列表
     * 2. 遍历订单商品,更新商品规格库存、商品SKU库存和商户规格库存
     * 
     * 参数说明:
     * @param OrderInfo $orderObj 订单对象
     * 
     * 返回值说明:
     * @return bool 更新成功返回true,失败返回false
     * 
     * 异常说明:
     * @throws Exception 当订单对象无效或商品不存在时抛出异常
     * 
     * 使用示例:
     * $order = OrderInfo::find(123);
     * Adapay::updateGoodsStock($order);
     * 
     * 注意事项:
     * 1. 需要在事务中调用此方法
     * 2. 会同时更新商品规格库存、商品SKU和商户规格库存
     */
    public static function updateGoodsStock($orderObj)
    {
        if (!$orderObj || !$orderObj->id) {
            throw new Exception('订单对象无效');
        }

        $orderGoods = OrderGoods::where('order_id', $orderObj->id)->get();
        if ($orderGoods->isEmpty()) {
            throw new Exception('订单商品不存在');
        }

        foreach ($orderGoods as $item) {
            $goodsObj = GoodModel::find($item->goods_id);
            if (!$goodsObj) {
                Log::add('商品不存在', ['goods_id' => $item->goods_id]);
                continue;
            }

            //更新商品规格库存
            $attrObj = GoodSku::find($item->attr_id);
            if (!$attrObj) {
                Log::add('商品规格不存在', ['attr_id' => $item->attr_id]);
                continue;
            }

            $attr_stock = ($attrObj->stock - $item->goods_number) >= 0 ? $attrObj->stock - $item->goods_number : 0;
            $attrObj->stock = $attr_stock;
            $attrObj->save();

            //更新商品sku
            $skuArr = json_decode($goodsObj->sku, true);
            if ($skuArr['sku']) {
                foreach ($skuArr['sku'] as $kk => $vv) {
                    if (isset($vv['attr_sn']) && $vv['attr_sn'] == $attrObj->attr_sn) {
                        $skuArr['sku'][$kk]['stock'] = $attr_stock;
                    }
                }
                $goodsObj->sku = json_encode($skuArr, JSON_UNESCAPED_UNICODE);
                $goodsObj->save();
            }

            //商户规格库存
            $mgsObj = MerchantGoodSku::where([
                'goods_id' => $item->goods_id,
                'attr_id' => $item->attr_id,
                'merchant_id' => $orderObj->merchant_id
            ])->first();

            if ($orderObj->merchant_id && $mgsObj) {
                $changeStock = ($mgsObj->stock >= $item->goods_number) ? $mgsObj->stock - $item->goods_number : 0;
                $mgsObj->stock = $changeStock;
                $mgsObj->save();
            }
        }

        return true;
    }
}