<?php

namespace App\Services;

use App\Models\ActivityReward;
use App\Models\BalanceLog;
use App\Models\User;
use App\Models\Config;
use App\Models\WalletBonus;
use App\Models\Wallet;
use App\Models\Level;
use App\Models\RechargeChannelGroup;
use App\Models\UserLogin;

// 余额额变动记录
class BalanceLogService extends BaseService
{
    public static string $MODEL = BalanceLog::class;
    //后台充值可选择的类型
    public static array $manualRecharge = ['人工充值', '注册赠送', '优惠活动'];
    //需要计算回水的类型
    public static array $computeBackFlowChangeTypes = ['充值', '人工充值', '三方充值', '提现', '人工扣款', '三方提现'];
    //全部类型
    public static array $RW = [
        '充值', '人工充值', '三方充值', '注册赠送', '优惠活动',
        '提现', '人工扣款', '三方提现', 
        //'体彩投注','体彩退款','体彩和局退款','体彩中奖','体彩输半退款',
        '新澳门六合彩投注','新澳门六合彩退款','新澳门六合彩和局退款','新澳门六合彩中奖',
        '香港六合彩投注','香港六合彩退款','香港六合彩和局退款','香港六合彩中奖','加拿大28投注','极速28投注',
        '澳门六合彩投注','澳门六合彩退款','澳门六合彩和局退款','澳门六合彩中奖',
        '极速六合彩投注','极速六合彩退款','极速六合彩和局退款','极速六合彩中奖',
        '极速赛车投注','极速赛车退款','极速赛车和局退款','极速赛车中奖',
        '极速时时彩投注','极速时时彩退款','极速时时彩中奖',
        '极速飞艇投注','极速飞艇退款','极速飞艇中奖',
        '极速快3投注','极速快3退款','极速快3和局退款','极速快3中奖',
        'SG时时彩投注','SG时时彩退款','SG时时彩中奖',
        'SG飞艇投注','SG飞艇退款','SG飞艇中奖',
        'SG快3投注','SG快3退款','SG快3中奖',
        //'足球游戏投注','足球游戏退款','足球游戏中奖',
        '资产转移', '比比返', '返水', '回水', '笔笔返', '投注退分','充值返现','即充即送','老用户回归','余额宝转入','转出至余额宝','余额宝利息','流水解冻'
    ];

    public static function init($telegram, $data, $chatId, $firstName, $messageId, $callbackId): void
    {
        switch ($data) {
            case"todayFlowAlert":// 今日流水弹窗
                $alertText = BalanceLogService::getTodayFlowing($chatId)['text'];
                BalanceLogService::alertNotice($callbackId, $alertText);
                break;
            default:
                //流水列表，下一页
                $pattern = "/^FlowingHistoryPage@@\d+$/";
                if (preg_match($pattern, $data)) {
                    $page = preg_replace('/^FlowingHistoryPage@@/', '', $data);
                    $page = intval($page);
                    $returnMsg = BalanceLogService::getFlowingHistory($chatId, $messageId, $page);
                    $telegram->editMessageText($returnMsg);
                }
                break;
        }
    }


    /**
     * @description: 获取查询条件
     * @param {array} $search 查询内容
     * @return {array}
     */
    public static function getWhere(array $search = []): array
    {
        $where = [];
        if (isset($search['coin']) && !empty($search['coin'])) {
            $where[] = ['balance_logs.coin', '=', $search['coin']];
        }
        if (isset($search['net']) && !empty($search['net'])) {
            $where[] = ['balance_logs.net', '=', $search['net']];
        }
        if (isset($search['address']) && !empty($search['address'])) {
            $where[] = ['balance_logs.address', '=', $search['address']];
        }
        if (isset($search['id']) && !empty($search['id'])) {
            $where[] = ['balance_logs.id', '=', $search['id']];
        }
        if (isset($search['member_id']) && !empty($search['member_id'])) {
            $where[] = ['balance_logs.member_id', '=', $search['member_id']];
        }

        if (isset($search['type']) && !empty($search['type'])) {
            $where[] = ['balance_logs.type', '=', $search['type']];
        }
        
        if (isset($search['change_type']) && !empty($search['change_type'])) {
            $where[] = ['balance_logs.change_type', '=', $search['change_type']];
        }

        if (isset($search['start_time']) && !empty($search['start_time'])) {
            $where[] = ['balance_logs.created_at', '>=', "{$search['start_time']} 00:00:00"];
            $where[] = ['balance_logs.created_at', '<=', "{$search['end_time']} 23:59:59"];
        }
        if (isset($search['first_name']) && !empty($search['first_name'])) {
            $where[] = ['users.first_name', 'like', "%" . $search['first_name'] . "%"];
        }
        // 用户类型/注册来源：-1 tg用户，0 后台客服账号，1 真实用户，2 虚拟用户
        // 不能用 empty()，否则 from=0（后台客服）会被误判为空
        if (array_key_exists('from', $search) && $search['from'] !== null && $search['from'] !== '') {
            $where[] = ['users.from', '=', $search['from']];
        }

        return $where;
    }

    /**
     * @description: 查询单条数据
     * @param array $search
     * @return \App\Models\Coin|null
     */
    public static function findOne(array $search): ?BalanceLog
    {
        return static::model()::where(static::getWhere($search))->first();
    }

    /**
     * @description: 查询所有数据
     * @param array $search
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public static function findAll(array $search = [])
    {
        return static::model()::where(static::getWhere($search))->get();
    }

    /**
     * @description: 分页查询
     * @param array $search
     * @return array
     */
    public static function paginate(array $search = []): array
    {

        $limit = isset($search['limit']) ? $search['limit'] : 15;
        $paginator = static::model()::where(static::getWhere($search))
            ->when(isset($search['change_types']) && !empty($search['change_types']), function ($query) use ($search) {
                return $query->whereIn('change_type', $search['change_types']);
            })
            ->orderBy('updated_at', 'desc')
            ->paginate($limit);
        return ['total' => $paginator->total(), 'data' => $paginator->items()];
    }

    /**
     * @description: 生成资金变动日志
     * @param {*} $memberId
     * @param {*} $amount
     * @param {*} $before_balance
     * @param {*} $after_balance
     * @param {*} $change_type
     * @param {*} $related_id
     * @param {*} $remark
     * @return {*}
     */
    public static function addLog($memberId, $amount, $before_balance, $after_balance, $change_type, $related_id, $remark, $room_id = null)
    {
        //回水相关
        if (in_array($change_type, static::$computeBackFlowChangeTypes)) {
            BackflowService::updateOrCreate((string)$memberId, floatval($amount));
        }
        
        $data = [];
        $data['member_id'] = $memberId;
        $data['amount'] = $amount;
        $data['before_balance'] = $before_balance;
        $data['after_balance'] = $after_balance;
        $data['change_type'] = $change_type;
        $data['related_id'] = $related_id;
        $data['remark'] = $remark;
        if ($room_id) $data['room_id'] = $room_id;
        $result = static::$MODEL::create($data);

        //充值返现活动仅限前台用户充值，后台人工充值不触发活动赠送
        if ( in_array($change_type, ['充值','三方充值'])) {
            $user = User::where('member_id', $memberId)->first();
            if ($user->from == 1) {
                //充值更新用户等级
                $total_recharge = self::getTotalRecharge($memberId);
                $total_recharge = bcadd($total_recharge, $amount, 2);
                $level = self::calculateLevel($total_recharge);
                if ($level > $user->level) {
                    $user->level = $level;
                    $user->save();
                }

                $remark_amount = bcadd($amount, 0, 2);
                //返现比例(给邀请人返现)
                $rate = Config::where('field', 'recharge_rate')->first()->val ?? 0;
                $add_amount = bcmul($amount, $rate/100, 2);
                if ($add_amount > 0) {
                    //被邀请人每次充值，都给邀请人返现，直接可用余额
                    $agent_user_code = $user->agent_user_code;
                    if (!empty($agent_user_code)) {
                        $agent_member_id = User::where('user_code', $agent_user_code)->value('member_id');
                        if (!empty($agent_member_id)) {
                            $balanceData = WalletService::updateBalance($agent_member_id, $add_amount);
                            BalanceLogService::addLog($agent_member_id, $add_amount, $balanceData['before_balance'], $balanceData['after_balance'], '充值返现', $related_id, '被邀请人：'.$memberId."充值金额为：{$remark_amount}");
                        }
                    }
                }

                //用户活动
                $activity_type = RechargeChannelGroup::getActivityType($user->recharge_channel_group_id);
                if ($activity_type) {
                    $walletInfo = Wallet::where('member_id', $memberId)->first();
                    if (in_array('recharge', $activity_type)) {
                        //即充即送-返彩活动
                        $bonusAmount = self::calculateRechargeBonus($amount,$memberId, $related_id);
                        if ($bonusAmount > 0) {
                            static::$MODEL::create([
                                'type' => 2,
                                'member_id' => $memberId,
                                'amount' => $bonusAmount,
                                'before_balance' => $walletInfo->frozen_balance,
                                'after_balance' => bcadd($walletInfo->frozen_balance, $bonusAmount, 2),
                                'change_type' => '即充即送',
                                'frozen_status' => 1,
                                'related_id' => $related_id,
                                'remark' => '充值金额为：'.$remark_amount,
                            ]);
                            $walletInfo->frozen_balance = bcadd($walletInfo->frozen_balance, $bonusAmount, 2);
                        }
                    }

                    if (in_array('old_user', $activity_type)) {
                        //老用户回归-返彩活动
                        $bonusAmount = self::calculateUserReturnRechargeBonus($amount,$memberId, $level, $related_id);
                        
                        if ($bonusAmount > 0) {
                            static::$MODEL::create([
                                'type' => 2,
                                'member_id' => $memberId,
                                'amount' => $bonusAmount,
                                'before_balance' => $walletInfo->frozen_balance,
                                'after_balance' => bcadd($walletInfo->frozen_balance, $bonusAmount, 2),
                                'change_type' => '老用户回归',
                                'frozen_status' => 1,
                                'related_id' => $related_id,
                                'remark' => '充值金额为：'.$remark_amount,
                            ]);
                            $walletInfo->frozen_balance = bcadd($walletInfo->frozen_balance, $bonusAmount, 2);
                        }
                    }
                    
                    $walletInfo->save();
                }
            }
        }
        
        return $result;
    }

    /**
     * 获取用户累计充值金额
     */
    public static function getTotalRecharge($memberId): float
    {
        return static::$MODEL::where('member_id', $memberId)->where('type',1)->whereIn('change_type', ['充值','人工充值', '三方充值'])->sum('amount');
    }

    /**
     * 根据历史累计充值金额计算等级
     * @param float $totalAmount 历史累计充值金额
     * @return int 等级(1-5)
     */
    public static function calculateLevel(float $totalAmount): int
    {
        $levelList = Level::orderBy('recharge', 'desc')->get()->toArray();
        foreach ($levelList as $item) {
            if ($totalAmount >= $item['recharge']) {
                return $item['level'];
            }
        }
        return 0; 
    }

    /**
     * @description: 获取今日流水
     * @param int $memberId
     * @param string|null $date
     * @return {*}
     */
    public static function getTodayFlowing($memberId, $date = null)
    {
        if (!$date) {
            $date = date('Y-m-d');
        }
        $startTime = date('Y-m-d H:i:s', strtotime($date . ' 00:00:00'));
        $endTime = date('Y-m-d H:i:s', strtotime($date . ' 23:59:59'));


        $flow = static::model()::where('member_id', $memberId)
            ->whereBetween('created_at', [$startTime, $endTime])
            ->where('change_type', '投注')
            ->sum('amount');
        $refund = static::model()::where('member_id', $memberId)
            ->whereBetween('created_at', [$startTime, $endTime])
            ->where('change_type', '返水')
            ->sum('amount');

        $profit = static::model()::where('member_id', $memberId)
            ->whereBetween('created_at', [$startTime, $endTime])
            ->where('change_type', '中奖') //嬴正数 输负数
            ->sum('amount');

        $walletInfo = WalletService::model()::where('member_id', $memberId)->first();
        $text = '';
        $text .= "当日流水: " . number_format((0 - $flow), 2) . "\n";
        $text .= "返水额度: " . number_format($refund, 2) . "\n";
        $text .= "当日盈亏: " . number_format(($profit + $refund + $flow), 2) . "\n";
        $text .= "余额: " . number_format($walletInfo['available_balance'], 2) . "\n";
        return [
            'chat_id' => $memberId,
            'text' => $text
        ];
    }

    public static function getFlowingHistory($memberId, $messageId = null, $page = 1, $limit = 5)
    {
        $dateTime = date('Y-m-d 00:00:00');
        $list = [];
        for ($i = 0; $i < $limit; $i++) {
            $newIndex = ($page - 1) * $limit + $i;
            $date = date('Y-m-d', strtotime($dateTime . " -{$newIndex} day"));
            $startTime = date('Y-m-d H:i:s', strtotime($date . ' 00:00:00'));
            $endTime = date('Y-m-d H:i:s', strtotime($date . ' 23:59:59'));


            $flow = static::model()::where('member_id', $memberId)
                ->whereBetween('created_at', [$startTime, $endTime])
                ->where('change_type', '投注')
                ->sum('amount');
            $refund = static::model()::where('member_id', $memberId)
                ->whereBetween('created_at', [$startTime, $endTime])
                ->where('change_type', '返水')
                ->sum('amount');

            $profit = static::model()::where('member_id', $memberId)
                ->whereBetween('created_at', [$startTime, $endTime])
                ->where('change_type', '中奖') //嬴正数 输负数
                ->sum('amount');

            $list[] = [
                'date' => $date,
                'flow' => number_format($flow, 2),
                'refund' => number_format($refund, 2),
                'profit' => number_format(($profit + $refund + $flow), 2)
            ];
        }
        // $startTime = date('Y-m-d H:i:s',strtotime($date . ' 00:00:00'));
        // $endTime = date('Y-m-d H:i:s',strtotime($date . ' 23:59:59'));


        // $list = static::model()::where('member_id', $memberId)
        //     ->whereBetween('created_at', [$startTime, $endTime])
        //     ->orderBy('created_at', 'desc')
        //     ->get();

        $text = lang("流水历史") . " \n";
        foreach ($list as $item) {
            $text .= "---------------------\n";
            $text .= lang("日期") . "： {$item['date']} \n";
            $text .= lang("流水") . "： {$item['flow']} \n";
            $text .= lang("返水") . "： {$item['refund']} \n";
            $text .= lang("盈利") . "： {$item['profit']} \n";
        }

        $keyboard = [[
            ['text' => "👇" . lang("下一页"), 'callback_data' => "FlowingHistoryPage@@" . ($page + 1)]
        ]];
        if ($page > 1) {
            array_unshift($keyboard[0], ['text' => "👆" . lang("上一页"), 'callback_data' => "FlowingHistoryPage@@" . ($page - 1)]);
        }
        return [
            'chat_id' => $memberId,
            'text' => $text,
            'message_id' => $messageId,
            'reply_markup' => json_encode(['inline_keyboard' => $keyboard]),
        ];
    }

    /**
     * 计算充值的返现金额
     * @param float $amount 充值金额（人民币）
     */
    public static function calculateRechargeBonus($amount,$memberId, $related_id = null)
    {
        $activity = ActivityReward::where('lang','zh')->where('type',3)->where('status',1)->where('start_time', '<', time())->where('end_time', '>', time())->first();
        if (!$activity) {
            return false;
        }
        $params = $activity->params ? json_decode($activity->params, true) : [];
        if (!$params || empty($params['reward_ratio'])) {
            return false;
        }
        // 规则1：单笔最低金额
        if (isset($params['min_recharge_amount']) && $amount < $params['min_recharge_amount']) {
            return false;
        }

        // 规则2：必须是每日前几笔充值
        if (!empty($params['reward_limit_count'])) {
            //今日已充值数
            $dailyOrder = static::model()::where('member_id', $memberId)
                ->whereBetween('created_at', [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')])
                ->whereIn('change_type', ['充值','三方充值'])
                ->count();
            if ($dailyOrder > $params['reward_limit_count']) {
                return false;
            }
        }

        // 规则3：返彩比例，不超过单笔最高10000元
        $rate = bcdiv($params['reward_ratio'], 100, 6); // 0.5%
        $maxBonus = $params['max_reward_amount'] ?? 10000;  // 单笔最高上限
        $calculatedBonus = bcmul($amount, $rate, 2); // 保留两位小数
        $bonusAmount = min($calculatedBonus, $maxBonus);

        //倍率流水
        $need_flow = !empty($params['reward_turnover_ratio']) ? bcmul($bonusAmount, $params['reward_turnover_ratio'], 2) : $bonusAmount;
        
        //返彩流水
        WalletBonus::addData($memberId, 1, $bonusAmount, $activity->id, $related_id, $need_flow);

        return $bonusAmount;
    }

    /**
     * 计算老用户回归当日的充值返现金额
     * @param float $amount 充值金额（人民币）
     */
    public static function calculateUserReturnRechargeBonus($amount,$memberId, $level, $related_id = null)
    {
        $activity = ActivityReward::where('lang','zh')->where('type',4)->where('status',1)->where('start_time', '<', time())->where('end_time', '>', time())->first();
        if (!$activity) {
            return false;
        }
        $params = $activity->params ? json_decode($activity->params, true) : [];
        if (!$params || empty($params['no_login_days']) || empty($params['reward_rules'])) {
            return false;
        }

        // 规则1：单笔最低金额
        if (isset($params['min_amount']) && $amount < $params['min_amount']) {
            return false;
        }

        // 规则2：多少天未登录
        $noLoginDays = UserLogin::getNotLoginDays($memberId);
        
        if ($noLoginDays < $params['no_login_days']) {
            return false;
        }
        
        foreach($params['reward_rules'] as $rule) {
            if (isset($rule['start_level']) && isset($rule['end_level'])) {
                if ($level >= $rule['start_level'] && $level <= $rule['end_level']) {
                    $bonusAmount = $rule['bonus'];
                    //倍率流水
                    $need_flow = !empty($rule['turnover_rate']) ? bcmul($bonusAmount, $rule['turnover_rate'], 2) : $bonusAmount;
                    break;
                }
            }
        }
        if (!isset($bonusAmount)) {
            return false;
        }
        
        //返彩流水
        WalletBonus::addData($memberId, 3, $bonusAmount, $activity->id, $related_id, $need_flow);

        return $bonusAmount;
    }

}
