<?php

declare(strict_types=1);

namespace app\common\service;

use support\think\Db;

class AdminWalletService
{
    public static function ensureWallet(int $adminId): array
    {
        $wallet = Db::name('admin_wallet')->where('admin_id', $adminId)->find();
        if (is_array($wallet)) {
            return $wallet;
        }
        $now = time();
        Db::name('admin_wallet')->insert([
            'admin_id' => $adminId,
            'balance' => '0.00',
            'frozen_balance' => '0.00',
            'total_income' => '0.00',
            'total_withdraw' => '0.00',
            'create_time' => $now,
            'update_time' => $now,
        ]);
        return Db::name('admin_wallet')->where('admin_id', $adminId)->find() ?: [];
    }

    public static function creditCommission(
        int $adminId,
        ?int $channelId,
        string $amount,
        string $refType,
        int $refId,
        string $remark,
        ?int $operatorAdminId = null
    ): void
    {
        $wallet = self::ensureWallet($adminId);
        $before = strval($wallet['balance'] ?? '0.00');
        $after = bcadd($before, $amount, 2);
        $now = time();
        Db::name('admin_wallet')->where('admin_id', $adminId)->update([
            'balance' => $after,
            'total_income' => Db::raw('total_income + ' . $amount),
            'update_time' => $now,
        ]);
        Db::name('admin_wallet_record')->insert([
            'admin_id' => $adminId,
            'channel_id' => $channelId,
            'biz_type' => 'commission_income',
            'direction' => 1,
            'amount' => $amount,
            'balance_before' => $before,
            'balance_after' => $after,
            'ref_type' => $refType,
            'ref_id' => $refId,
            'idempotency_key' => 'commission_income_' . $adminId . '_' . $refId,
            'operator_admin_id' => $operatorAdminId,
            'remark' => $remark,
            'create_time' => $now,
        ]);
    }

    public static function applyWithdraw(
        int $adminId,
        int $channelId,
        string $withdrawCoin,
        string $receiveType,
        string $receiveAccount,
        string $idempotencyKey,
        string $remark
    ): array
    {
        $existing = Db::name('admin_withdraw_order')->where('idempotency_key', $idempotencyKey)->find();
        if (is_array($existing)) {
            $existAdminId = intval($existing['admin_id'] ?? 0);
            if ($existAdminId !== $adminId) {
                return ['ok' => false, 'msg' => __('Idempotency key conflict')];
            }
            return [
                'ok' => true,
                'order_id' => intval($existing['id'] ?? 0),
                'order_no' => strval($existing['order_no'] ?? ''),
                'idempotent_hit' => true,
            ];
        }

        $wallet = self::ensureWallet($adminId);
        $before = strval($wallet['balance'] ?? '0.00');
        if (bccomp($before, $withdrawCoin, 2) < 0) {
            return ['ok' => false, 'msg' => __('Insufficient wallet balance')];
        }
        $after = bcsub($before, $withdrawCoin, 2);
        $beforeFrozen = strval($wallet['frozen_balance'] ?? '0.00');
        $afterFrozen = bcadd($beforeFrozen, $withdrawCoin, 2);
        $now = time();
        $orderNo = 'AWD' . date('YmdHis') . str_pad(strval($adminId), 6, '0', STR_PAD_LEFT) . strval(random_int(1000, 9999));

        Db::name('admin_wallet')->where('admin_id', $adminId)->update([
            'balance' => $after,
            'frozen_balance' => $afterFrozen,
            'update_time' => $now,
        ]);
        $orderId = Db::name('admin_withdraw_order')->insertGetId([
            'order_no' => $orderNo,
            'admin_id' => $adminId,
            'channel_id' => $channelId > 0 ? $channelId : null,
            'amount' => $withdrawCoin,
            'actual_amount' => $withdrawCoin,
            'status' => 0,
            'receive_type' => $receiveType,
            'receive_account' => $receiveAccount,
            'idempotency_key' => $idempotencyKey,
            'review_admin_id' => null,
            'review_time' => null,
            'remark' => $remark,
            'create_time' => $now,
            'update_time' => $now,
        ]);
        Db::name('admin_wallet_record')->insert([
            'admin_id' => $adminId,
            'channel_id' => $channelId > 0 ? $channelId : null,
            'biz_type' => 'withdraw_freeze',
            'direction' => 2,
            'amount' => $withdrawCoin,
            'balance_before' => $before,
            'balance_after' => $after,
            'ref_type' => 'admin_withdraw_order',
            'ref_id' => $orderId,
            'idempotency_key' => 'admin_withdraw_freeze_' . $orderId,
            'operator_admin_id' => $adminId,
            'remark' => $remark !== '' ? $remark : '管理员提现申请冻结',
            'create_time' => $now,
        ]);

        return ['ok' => true, 'order_id' => $orderId, 'order_no' => $orderNo];
    }

    public static function approveWithdraw(array $order, int $reviewAdminId, string $remark): void
    {
        $orderId = intval($order['id'] ?? 0);
        $adminId = intval($order['admin_id'] ?? 0);
        $amount = strval($order['amount'] ?? '0.00');
        $wallet = self::ensureWallet($adminId);
        $frozen = strval($wallet['frozen_balance'] ?? '0.00');
        $afterFrozen = bcsub($frozen, $amount, 2);
        $now = time();

        Db::name('admin_wallet')->where('admin_id', $adminId)->update([
            'frozen_balance' => $afterFrozen,
            'total_withdraw' => Db::raw('total_withdraw + ' . $amount),
            'update_time' => $now,
        ]);
        Db::name('admin_withdraw_order')->where('id', $orderId)->update([
            'status' => 1,
            'review_admin_id' => $reviewAdminId,
            'review_time' => $now,
            'remark' => $remark,
            'update_time' => $now,
        ]);
        Db::name('admin_wallet_record')->insert([
            'admin_id' => $adminId,
            'channel_id' => $order['channel_id'] ?? null,
            'biz_type' => 'withdraw_success',
            'direction' => 2,
            'amount' => $amount,
            'balance_before' => strval($wallet['balance'] ?? '0.00'),
            'balance_after' => strval($wallet['balance'] ?? '0.00'),
            'ref_type' => 'admin_withdraw_order',
            'ref_id' => $orderId,
            'idempotency_key' => 'admin_withdraw_success_' . $orderId,
            'operator_admin_id' => $reviewAdminId,
            'remark' => $remark !== '' ? $remark : '管理员提现审核通过',
            'create_time' => $now,
        ]);
    }

    public static function rejectWithdraw(array $order, int $reviewAdminId, string $remark): void
    {
        $orderId = intval($order['id'] ?? 0);
        $adminId = intval($order['admin_id'] ?? 0);
        $amount = strval($order['amount'] ?? '0.00');
        $wallet = self::ensureWallet($adminId);
        $before = strval($wallet['balance'] ?? '0.00');
        $after = bcadd($before, $amount, 2);
        $frozen = strval($wallet['frozen_balance'] ?? '0.00');
        $afterFrozen = bcsub($frozen, $amount, 2);
        $now = time();

        Db::name('admin_wallet')->where('admin_id', $adminId)->update([
            'balance' => $after,
            'frozen_balance' => $afterFrozen,
            'update_time' => $now,
        ]);
        Db::name('admin_withdraw_order')->where('id', $orderId)->update([
            'status' => 2,
            'review_admin_id' => $reviewAdminId,
            'review_time' => $now,
            'remark' => $remark,
            'update_time' => $now,
        ]);
        Db::name('admin_wallet_record')->insert([
            'admin_id' => $adminId,
            'channel_id' => $order['channel_id'] ?? null,
            'biz_type' => 'withdraw_refund',
            'direction' => 1,
            'amount' => $amount,
            'balance_before' => $before,
            'balance_after' => $after,
            'ref_type' => 'admin_withdraw_order',
            'ref_id' => $orderId,
            'idempotency_key' => 'admin_withdraw_refund_' . $orderId,
            'operator_admin_id' => $reviewAdminId,
            'remark' => $remark !== '' ? $remark : '管理员提现审核拒绝退回',
            'create_time' => $now,
        ]);
    }
}

