<?php

namespace App\Services\Client;

use App\Models\AgentConfig;
use App\Models\AgentInfo;
use App\Models\CoachConfig;
use App\Models\CoachSchedule;
use App\Models\CoachUser;
use App\Models\Coupon;
use App\Models\MemberUser;
use App\Models\Order;
use App\Models\OrderGrabRecord;
use App\Models\OrderRecord;
use App\Models\Project;
use App\Models\SysConfig;
use App\Models\User;
use App\Models\WalletRefundRecord;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class OrderService
{
    protected AgentService $agentService;

    protected ProjectService $projectService;

    public function __construct(
        AgentService $agentService,
        ProjectService $projectService
    ) {
        $this->agentService = $agentService;
        $this->projectService = $projectService;
    }

    /**
     * 订单初始化
     */
    public function initialize($userId, $data)
    {
        $user = MemberUser::find($userId);

        if (! $user) {
            throw new Exception('用户不存在');
        }

        if ($user->state != 'enable') {
            throw new Exception('用户状态异常');
        }

        // 查询用户钱包
        $wallet = $user->wallet;

        // 查询默认地址
        $address = $user->address;

        $areaCode = $address ? $address->area_code : $data['area_code'];

        // 查询技师数据
        $coach = CoachUser::where('state', 'enable')
            ->whereHas('info', function ($query) {
                $query->where('state', 'approved');
            })
            ->whereHas('real', function ($query) {
                $query->where('state', 'approved');
            })
            ->whereHas('qual', function ($query) {
                $query->where('state', 'approved');
            })
            ->with(['info:id,nickname,avatar,gender'])
            ->find($data['coach_id']);

        if (! $coach) {
            throw new Exception('技师不存在');
        }

        // 查询技师排班
        // $schedule = CoachSchedule::where('coach_id', $coachId)
        //     ->where('date', date('Y-m-d'))
        //     ->first();

        // // 查询用户优惠券
        // $coupons = Coupon::where('user_id', $userId)
        //     ->where('state', 'enable')
        //     ->where('expire_time', '>', now())
        //     ->get();

        // 获取项目详情
        $project = $this->projectService->getProjectDetail($data['project_id'], $areaCode);

        // 计算订单金额
        $amounts = $this->calculateOrderAmount($userId, $address?->id, $data['coach_id'], $data['project_id'], $project?->agent_id);

        return [
            'wallet' => $wallet,
            'coach' => $coach,
            'project' => $project,
            'address' => $address,
            // 'schedule' => $schedule,
            'amounts' => $amounts,
            // 'coupons' => $coupons
        ];
    }

    /**
     * 创建订单
     */
    public function createOrder($userId, array $data)
    {
        try {
            return DB::transaction(function () use ($userId, $data) {
                // 1. 参数校验
                $user = MemberUser::where('id', $userId)
                    ->where('state', 'enable')
                    ->firstOrFail();

                $address = $user->addresses()
                    ->where('id', $data['address_id'])
                    ->firstOrFail();

                // 查询技师及其认证状态
                $coach = CoachUser::where('id', $data['coach_id'])
                    ->where('state', 'enable')
                    ->whereHas('info', function ($query) {
                        $query->where('state', 'approved');
                    })
                    ->whereHas('qual', function ($query) {
                        $query->where('state', 'approved');
                    })
                    ->whereHas('real', function ($query) {
                        $query->where('state', 'approved');
                    })
                    ->firstOrFail();

                $project = Project::where('id', $data['project_id'])
                    ->where('state', 'enable')
                    ->firstOrFail();

                // 2. 创建订单
                $orderType = isset($data['order_id']) ? 'add_time' : 'normal';

                // 计算订单金额
                $amounts = $this->calculateOrderAmount(
                    $userId,
                    $data['address_id'],
                    $data['coach_id'],
                    $data['project_id'],
                    $project->agent_id,
                    $data['use_balance'] ?? false
                );

                $order = new Order;
                $order->user_id = $userId;
                $order->project_id = $data['project_id'];
                $order->coach_id = $data['coach_id'];
                $order->type = $orderType;
                $order->state = 'wait_pay';
                $order->source = 'platform';
                $order->total_amount = $amounts['total_amount'];
                $order->balance_amount = $amounts['balance_amount'];
                $order->pay_amount = $amounts['pay_amount'];
                $order->project_amount = $amounts['project_amount'];
                $order->traffic_amount = $orderType == 'add_time' ? 0 : $amounts['delivery_fee'];
                $order->payment_type = ($data['use_balance'] && $amounts['pay_amount'] == 0) ? 'balance' : null;
                $order->service_time = $data['service_time'];

                // 从用户地址获取位置信息
                $order->longitude = $address->longitude; // 经度
                $order->latitude = $address->latitude;   // 纬度
                $order->location = $address->location;   // 定位地址
                $order->address = $address->address;     // 详细地址
                $order->area_code = $address->area_code; // 行政区划代码

                $order->save();

                // 3. 创建订单记录
                OrderRecord::create([
                    'order_id' => $order->id,
                    'object_id' => $userId,
                    'object_type' => MemberUser::class,
                    'state' => $orderType == 'add_time' ? 'add_time' : 'create',
                    'remark' => $orderType == 'add_time' ? '加钟订单' : '创建订单',
                ]);

                // 4. 余额支付处理
                if ($order->payment_type == 'balance') {
                    $order->state = 'wait_receive';
                    $order->save();

                    // 创建订单支付记录
                    OrderRecord::create([
                        'order_id' => $order->id,
                        'object_id' => $userId,
                        'object_type' => MemberUser::class,
                        'state' => 'pay',
                        'remark' => '余额支付',
                    ]);

                    // 扣除用户钱包总余额
                    $user->wallet->decrement('total_balance', $order->balance_amount);
                    // 扣除用户钱包可用余额
                    $user->wallet->decrement('available_balance', $order->balance_amount);
                    $user->wallet->save();

                    // 创建技师排班
                    // CoachSchedule::create([
                    //     'coach_id' => $data['coach_id'],
                    //     'date' => date('Y-m-d'),
                    //     'state' => 'busy',
                    // ]);

                    // TODO: 发送抢单通知
                }

                return [
                    'order_id' => $order->id,
                    'payment_type' => $order->payment_type,
                ];
            });
        } catch (Exception $e) {
            Log::error('创建订单失败:', [
                'message' => $e->getMessage(),
                'user_id' => $userId,
                'data' => $data,
            ]);
            throw $e;
        }
    }

    /**
     * 取消订单
     */
    public function cancelOrder($userId, $orderId)
    {
        return DB::transaction(function () use ($userId, $orderId) {
            try {
                $user = MemberUser::where('id', $userId)->firstOrFail();
                $order = $user->orders()->find($orderId);

                if (! $order) {
                    throw new Exception('订单不存在');
                }

                // 判断订单状态
                if ($order->state == 'wait_receive') { // 已接单
                    // 扣除20%费用
                    $deductAmount = ($order->payment_amount + $order->balance_amount - $order->traffic_amount) * 0.2;
                    $this->handleRefund($user, $order, $deductAmount, false);
                } elseif ($order->state == 'on_the_way') { // 已出发
                    // 扣除50%费用并扣除路费
                    $deductAmount = ($order->payment_amount + $order->balance_amount - $order->traffic_amount) * 0.5;
                    $this->handleRefund($user, $order, $deductAmount, true);
                } elseif ($order->state == 'wait_pay') {
                    // 待支付状态直接取消,无需退款
                } else {
                    throw new Exception('当前订单状态不允许取消');
                }

                // 添加订单取消记录
                OrderRecord::create([
                    'order_id' => $orderId,
                    'object_id' => $userId,
                    'object_type' => MemberUser::class,
                    'state' => 'cancel',
                    'remark' => '用户取消订单',
                ]);

                // 修改订单状态
                $order->state = 'cancel';
                $order->save();

                return ['message' => '订单已取消'];
            } catch (Exception $e) {
                Log::error('取消订单失败:', [
                    'message' => $e->getMessage(),
                    'user_id' => $userId,
                    'order_id' => $orderId,
                ]);
                throw $e;
            }
        });
    }

    /**
     * 处理退款
     */
    private function handleRefund($user, $order, $deductAmount, $deductTrafficFee)
    {
        // 计算实际退款金额
        $refundAmount = $order->payment_amount + $order->balance_amount;
        if ($deductTrafficFee) {
            $refundAmount -= $order->traffic_amount;
            // 记录技师路费收入
            // ...
        }
        $refundAmount -= $deductAmount;

        // 优先从余额支付金额中扣除
        $balanceRefund = min($order->balance_amount, $refundAmount);
        if ($balanceRefund > 0) {

            // 添加钱包退款记录
            $refundRecord = $user->wallet->refundRecords()->create([
                'refund_method' => 'balance',
                'total_refund_amount' => $order->payment_amount + $order->balance_amount,
                'actual_refund_amount' => '0.00',
                'wallet_balance_refund_amount' => $balanceRefund,
                'recharge_balance_refund_amount' => '0.00',
                'remark' => '订单取消退还余额',
                'order_id' => $order->id,
            ]);

            // 添加钱包交易记录
            $user->wallet->transRecords()->create([
                'amount' => $balanceRefund,
                'owner_type' => $refundRecord::class,
                'owner_id' => $refundRecord->id,
                'remark' => '订单取消退还余额',
                'trans_type' => 'income',
                'storage_type' => 'balance',
                'amount' => $balanceRefund,
                'before_balance' => $user->wallet->total_balance,
                'after_balance' => $user->wallet->total_balance + $balanceRefund,
                'before_recharge_balance' => '0.00',
                'after_recharge_balance' => '0.00',
                'trans_time' => now(),
                'state' => 'success',
            ]);

            $user->wallet->increment('total_balance', $balanceRefund);
            $user->wallet->increment('available_balance', $balanceRefund);
            $user->wallet->save();
        }

        // 剩余退款金额从支付金额中退还
        $paymentRefund = $refundAmount - $balanceRefund;
        if ($paymentRefund > 0) {

            // 添加钱包退款记录
            $refundRecord = $user->wallet->refundRecords()->create([
                'refund_method' => 'balance',
                'total_refund_amount' => $order->payment_amount + $order->balance_amount,
                'actual_refund_amount' => '0.00',
                'wallet_balance_refund_amount' => $balanceRefund,
                'recharge_balance_refund_amount' => '0.00',
                'remark' => '订单取消退还余额',
                'order_id' => $order->id,
            ]);

            // 添加钱包交易记录
            $user->wallet->transRecords()->create([
                'amount' => $balanceRefund,
                'owner_type' => $refundRecord::class,
                'owner_id' => $refundRecord->id,
                'remark' => '订单取消退还余额',
                'trans_type' => 'income',
                'storage_type' => 'balance',
                'amount' => $balanceRefund,
                'before_balance' => $user->wallet->total_balance,
                'after_balance' => $user->wallet->total_balance + $balanceRefund,
                'before_recharge_balance' => '0.00',
                'after_recharge_balance' => '0.00',
                'trans_time' => now(),
                'state' => 'success',
            ]);

            $user->wallet->increment('total_balance', $paymentRefund);
            $user->wallet->increment('available_balance', $paymentRefund);
            $user->wallet->save();
        }

        // 记录平台收入
        if ($deductAmount > 0) {
            // TODO: 添加平台收入记录
            // PlatformIncome::create([...]);
        }
    }

    /**
     * 结束订单
     */
    public function finishOrder($userId, $orderId)
    {
        return DB::transaction(function () use ($userId, $orderId) {
            try {
                // 1. 参数校验
                $order = Order::where('user_id', $userId)
                    ->where('id', $orderId)
                    ->where('state', 'service_ing') // 订单状态必须是服务中
                    ->firstOrFail();

                if (! $order) {
                    throw new Exception('订单不能结束');
                }

                // 2. 创建订单历史记录
                OrderRecord::create([
                    'order_id' => $orderId,
                    'object_id' => $userId,
                    'object_type' => MemberUser::class,
                    'state' => 'finish',
                    'remark' => '服务完成',
                ]);

                // 3. 修改订单状态为服务结束
                $order->state = 'service_end';
                $order->save();

                return ['message' => '订单已完成'];
            } catch (Exception $e) {
                Log::error('结束订单失败:', [
                    'message' => $e->getMessage(),
                    'user_id' => $userId,
                    'order_id' => $orderId,
                ]);
                throw $e;
            }
        });
    }

    /**
     * 确认技师离开
     */
    public function confirmLeave($userId, $orderId)
    {
        return DB::transaction(function () use ($userId, $orderId) {
            try {
                // 1. 参数校验
                $order = Order::where('user_id', $userId)
                    ->where('id', $orderId)
                    ->where('state', 'service_end') // 订单状态必须是服务结束
                    ->firstOrFail();

                if (! $order) {
                    throw new Exception('订单不能撤离');
                }

                // 2. 添加订单撤离记录
                OrderRecord::create([
                    'order_id' => $orderId,
                    'object_id' => $userId,
                    'object_type' => MemberUser::class,
                    'state' => 'leave',
                    'remark' => '技师已离开',
                ]);

                // 3. 修改订单状态为撤离
                $order->state = 'leave';
                $order->save();

                return ['message' => '已确认技师离开'];
            } catch (Exception $e) {
                Log::error('确认技师离开失败:', [
                    'message' => $e->getMessage(),
                    'user_id' => $userId,
                    'order_id' => $orderId,
                ]);
                throw $e;
            }
        });
    }

    /**
     * 获取订单列表
     */
    public function getOrderList($user_id)
    {
        $user = MemberUser::find($user_id);

        return $user->orders()
            ->with([
                'coach.info:id,nickname,avatar,gender',
            ])
            ->orderBy('created_at', 'desc')
            ->paginate(10);
    }

    /**
     * 获取订单详情
     */
    public function getOrderDetail($userId, $orderId)
    {
        $user = MemberUser::find($userId);

        return $user->orders()->with([
            'coach.info:id,nickname,avatar,gender',
            'records' => function ($query) {
                $query->orderBy('created_at', 'asc');
            },
        ])
            ->firstOrFail();
    }

    /**
     * 订单退款
     */
    public function refundOrder($orderId)
    {
        $userId = Auth::id();

        return DB::transaction(function () use ($orderId, $userId) {
            // 查询并锁定订单
            $order = Order::where('id', $orderId)
                ->where('user_id', $userId)
                ->where('state', 'pending')
                ->lockForUpdate()
                ->firstOrFail();

            // 更新订单状态
            $order->state = 'refunded';
            $order->save();

            // 添加订单记录
            OrderRecord::create([
                'order_id' => $orderId,
                'object_id' => $userId,
                'object_type' => 'user',
                'state' => 'refund',
                'remark' => '订单退款',
            ]);

            // 创建退款记录
            WalletRefundRecord::create([
                'order_id' => $orderId,
                'user_id' => $userId,
                'amount' => $order->total_amount,
                'state' => 'success',
            ]);

            return ['message' => '退款成功'];
        });
    }

    /**
     * 获取代理商配置
     */
    public function getAgentConfig($agentId)
    {
        $agent = AgentInfo::where('id', $agentId)
            ->where('state', 'enable')
            ->firstOrFail();

        // $config = AgentConfig::where('agent_id', $agentId)->firstOrFail();

        return [
            // 'min_distance' => $config->min_distance,
            // 'min_fee' => $config->min_fee,
            // 'per_km_fee' => $config->per_km_fee
        ];
    }

    /**
     * 获取技师配置
     */
    public function getCoachConfig($coachId)
    {
        $coach = CoachUser::where('id', $coachId)
            ->where('state', 'enable')
            ->where('auth_state', 'passed')
            ->firstOrFail();

        // $config = CoachConfig::where('coach_id', $coachId)->firstOrFail();

        return [
            // 'delivery_fee_type' => $config->delivery_fee_type,
            // 'charge_delivery_fee' => $config->charge_delivery_fee
        ];
    }

    /**
     * 计算路费金额
     */
    public function calculateDeliveryFee($coachId, $projectId, $agentId, $distance)
    {

        // 查询技师数据
        $coach = CoachUser::where('state', 'enable')
            ->whereHas('info', function ($query) {
                $query->where('state', 'approved');
            })
            ->whereHas('real', function ($query) {
                $query->where('state', 'approved');
            })
            ->whereHas('qual', function ($query) {
                $query->where('state', 'approved');
            })
            ->find($coachId);

        if (! $coach) {
            throw new Exception('技师不存在');
        }

        // 查询技师项目
        $coachProject = $coach->projects()
            ->where('state', 'enable')
            ->where('project_id', $projectId)
            ->first();
        if (! $coachProject) {
            throw new Exception('项目不存在');
        }

        // 技师免收路费
        if ($coachProject->traffic_fee_type == 'free') {
            return 0;
        }

        // 查询代理商
        $agent = AgentInfo::where('state', 'enable')->find($agentId);
        if ($agent) {
            $agentProject = $agent->projects()
                ->where('state', 'enable')
                ->where('project_id', $projectId)
                ->first();

            if (! $agentProject) {
                throw new Exception('代理商项目不存在');
            }
            $config = $agent->projectConfig;

        } else {
            // 系统配置
            $config = SysConfig::where('key', 'delivery_fee')->firstOrFail();
            dd('暂停处理');
        }

        $fee = 0;
        if ($distance <= $config->min_distance) {
            $fee = $config->min_fee;
        } else {
            $extraDistance = $distance - $config->min_distance;
            $fee = $config->min_fee + ($extraDistance * $config->per_km_fee);
        }

        return $coachProject->delivery_fee_type == 'round_trip' ? $fee * 2 : $fee;
    }

    /**
     * 计算订单金额
     */
    public function calculateOrderAmount($userId, $addressId, $coachId, $projectId, $agentId, $useBalance = false)
    {
        // 参数校验
        $user = MemberUser::find($userId);
        if (! $user) {
            throw new Exception('用户不存在');
        }

        if ($user->state != 'enable') {
            throw new Exception('用户状态异常');
        }

        // 查询地址
        $address = $user->address()->find($addressId);

        // 查询技师数据
        $coach = CoachUser::where('state', 'enable')
            ->whereHas('info', function ($query) {
                $query->where('state', 'approved');
            })
            ->whereHas('real', function ($query) {
                $query->where('state', 'approved');
            })
            ->whereHas('qual', function ($query) {
                $query->where('state', 'approved');
            })
            ->with(['info:id,nickname,avatar,gender'])
            ->find($coachId);

        if (! $coach) {
            throw new Exception('技师不存在');
        }

        // 查询技师项目
        $coachProject = $coach->projects()
            ->where('state', 'enable')
            ->where('project_id', $projectId)
            ->first();
        if (! $coachProject) {
            throw new Exception('项目不存在');
        }

        // 查询项目
        $project = $coachProject->basicInfo;

        if (! $project) {
            throw new Exception('项目不存在');
        }

        if ($project->state != 'enable') {
            throw new Exception('项目状态异常');
        }

        // 查询代理商
        $agent = AgentInfo::where('state', 'enable')->find($agentId);
        if ($agent) {
            $agentProject = $agent->projects()
                ->where('state', 'enable')
                ->where('project_id', $projectId)
                ->first();

            if (! $agentProject) {
                throw new Exception('代理商项目不在');
            }

            $project->price = $agentProject->price;
            $project->duration = $agentProject->duration;
            $project->distance = $address->distance;
        }

        // 计算金额
        $projectAmount = $project->price;
        $deliveryFee = $this->calculateDeliveryFee($coachId, $projectId, $agentId, $address?->distance);
        // $tipAmount = request()->has('order_id') ? Order::find(request()->input('order_id'))->tip_amount : 0;

        $couponAmount = 0;
        if (request()->has('coupon_id')) {
            // $coupon = Coupon::where('id', request()->input('coupon_id'))
            //     ->where('state', 'enable')
            //     ->firstOrFail();
            // $couponAmount = $coupon->amount;
        }

        $totalAmount = $projectAmount + $deliveryFee - $couponAmount;

        $balanceAmount = 0;
        $payAmount = $totalAmount;

        if ($useBalance) {
            $wallet = $user->wallet;
            if ($wallet && $wallet->available_balance >= $totalAmount) {
                $balanceAmount = $totalAmount;
                $payAmount = 0;
            } elseif ($wallet) {
                $balanceAmount = $wallet->available_balance;
                $payAmount = $totalAmount - $balanceAmount;
            }
        }

        return [
            'total_amount' => $totalAmount,
            'balance_amount' => $balanceAmount,
            'pay_amount' => $payAmount,
            'coupon_amount' => $couponAmount,
            // 'tip_amount' => $tipAmount,
            'project_amount' => $projectAmount,
            'delivery_fee' => $deliveryFee,
        ];
    }

    /**
     * 加钟
     */
    public function addTime($userId, $orderId)
    {
        $order = Order::where('id', $orderId)
            ->where('user_id', $userId)
            ->firstOrFail();

        return $this->createOrder($userId, $order->project_id, $order->address_id, $order->coach_id, 0, $orderId);
    }

    /**
     * 指定技师
     */
    public function assignCoach($userId, $orderId, $coachId)
    {
        return DB::transaction(function () use ($userId, $orderId, $coachId) {
            // 参数校验
            $user = MemberUser::where('id', $userId)
                ->where('state', 'enable')
                ->firstOrFail();

            $order = Order::where('id', $orderId)
                ->where('user_id', $userId)
                ->whereIn('state', [0, 1, 6])
                ->firstOrFail();

            $coach = CoachUser::where('id', $coachId)
                ->where('state', 'enable')
                ->where('auth_state', 'passed')
                ->firstOrFail();

            // $schedule = CoachSchedule::where('coach_id', $coachId)
            //     ->where('date', date('Y-m-d'))
            //     ->where('state', 'free')
            //     ->firstOrFail();

            // 修改订单
            $order->coach_id = $coachId;
            if ($order->state == 'created') {
                $amounts = $this->calculateOrderAmount($userId, $order->address_id, $coachId, $order->project_id, $order->agent_id, $order->payment_type == 'balance');

                $order->total_amount = $amounts['total_amount'];
                $order->balance_amount = $amounts['balance_amount'];
                $order->pay_amount = $amounts['pay_amount'];
                $order->coupon_amount = $amounts['coupon_amount'];
                // $order->tip_amount = $amounts['tip_amount'];
                $order->project_amount = $amounts['project_amount'];
                $order->delivery_fee = $amounts['delivery_fee'];

                if ($order->payment_type == 'balance') {
                    $order->state = 'paid';
                }
            }
            if ($order->state == 'paid') {
                $order->state = 'assigned';
            }
            $order->save();

            // 创建订单历史
            OrderRecord::create([
                'order_id' => $order->id,
                'type' => 'assigned',
                'user_id' => $userId,
                'coach_id' => $coachId,
            ]);

            OrderRecord::create([
                'order_id' => $order->id,
                'type' => 'accepted',
                'user_id' => $userId,
                'coach_id' => $coachId,
                'remark' => '抢单成功',
            ]);

            // 更新抢单池
            OrderGrabRecord::where('order_id', $orderId)
                ->update(['state' => 'success', 'coach_id' => $coachId]);

            // 更新排班
            // $schedule->state = 'busy';
            // $schedule->save();

            return true;
        });
    }
}
