package com.dora.service.impl;

import com.dora.dto.ApiResponse;
import com.dora.dto.WithdrawDto;
import com.dora.entity.UserBalance;
import com.dora.entity.WithdrawRequest;
import com.dora.entity.User;
import com.dora.mapper.WithdrawRequestMapper;
import com.dora.mapper.UserBalanceMapper;
import com.dora.mapper.UserMapper;
import com.dora.service.AdminWithdrawService;
import com.dora.service.UserBalanceService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 管理员提现审核服务实现类
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class AdminWithdrawServiceImpl implements AdminWithdrawService {

    private final WithdrawRequestMapper withdrawRequestMapper;
    private final UserBalanceMapper userBalanceMapper;
    private final UserMapper userMapper;
    private final UserBalanceService userBalanceService;

    @Override
    @Transactional
    public ApiResponse<String> reviewWithdraw(Long adminId, WithdrawDto.AdminReviewRequest request) {
        try {
            // 1. 参数验证
            if (request.getWithdrawId() == null) {
                return ApiResponse.error(400, "提现申请ID不能为空");
            }
            
            if (request.getStatus() == null || (request.getStatus() != 1 && request.getStatus() != 2)) {
                return ApiResponse.error(400, "审核状态只能是1（通过）或2（拒绝）");
            }
            
            if (request.getStatus() == 2 && !StringUtils.hasText(request.getReason())) {
                return ApiResponse.error(400, "拒绝审核时必须填写拒绝原因");
            }

            // 审核通过时验证必填字段
            if (request.getStatus() == 1) {
                if (request.getActualAmount() == null || request.getActualAmount().compareTo(BigDecimal.ZERO) <= 0) {
                    return ApiResponse.error(400, "审核通过时必须填写实际到账金额");
                }
            }

            // 2. 查询提现申请
            WithdrawRequest withdrawRequest = withdrawRequestMapper.selectById(request.getWithdrawId());
            if (withdrawRequest == null) {
                return ApiResponse.error(404, "提现申请不存在");
            }

            // 3. 检查申请状态
            if (withdrawRequest.getStatus() != 0) {
                return ApiResponse.error(400, "该提现申请已经被审核过了");
            }

            // 4. 执行审核逻辑
            if (request.getStatus() == 1) {
                // 审核通过
                return approveWithdraw(withdrawRequest, request, adminId);
            } else {
                // 审核拒绝
                return rejectWithdraw(withdrawRequest, request.getReason(), adminId);
            }

        } catch (Exception e) {
            log.error("审核提现申请失败", e);
            return ApiResponse.error("审核提现申请失败：" + e.getMessage());
        }
    }

    /**
     * 审核通过提现申请
     */
    private ApiResponse<String> approveWithdraw(WithdrawRequest withdrawRequest, WithdrawDto.AdminReviewRequest request, Long adminId) {
        // 1. 验证冻结金额是否充足（审核通过应校验冻结金额是否覆盖本次提现金额）
        UserBalance userBalance = userBalanceService.getUserBalance(withdrawRequest.getUserId());
        BigDecimal frozen = userBalance.getFrozenAmount() == null ? BigDecimal.ZERO : userBalance.getFrozenAmount();

        if (frozen.compareTo(withdrawRequest.getAmount()) < 0) {
            return ApiResponse.error(400, "冻结金额不足，无法通过审核");
        }

        // 2. 从用户余额中扣除提现金额
        userBalanceService.decreaseBalance(
            withdrawRequest.getUserId(),
            withdrawRequest.getAmount(),
            "withdraw",
            withdrawRequest.getId(),
            "提现审核通过，扣除余额"
        );

        // 3. 解冻提现金额（因为已经实际扣除了）
        userBalanceService.unfreezeBalance(
            withdrawRequest.getUserId(),
            withdrawRequest.getAmount(),
            "withdraw",
            withdrawRequest.getId(),
            "提现审核通过，解冻冻结金额"
        );

        // 4. 更新提现申请状态（包含流水号等处理信息）
        int result = withdrawRequestMapper.updateWithProcessInfo(
            withdrawRequest.getId(), 
            1, 
            null,
            adminId,
            request.getTransactionNo(),
            request.getFeeAmount(),
            request.getActualAmount()
        );

        if (result > 0) {
            log.info("管理员{}审核通过提现申请{}，金额：{}", adminId, withdrawRequest.getId(), withdrawRequest.getAmount());
            return ApiResponse.success("审核通过成功");
        } else {
            return ApiResponse.error("更新提现申请状态失败");
        }
    }

    /**
     * 审核拒绝提现申请
     */
    private ApiResponse<String> rejectWithdraw(WithdrawRequest withdrawRequest, String reason, Long adminId) {
        // 1. 解冻用户余额
        userBalanceService.unfreezeBalance(
            withdrawRequest.getUserId(),
            withdrawRequest.getAmount(),
            "withdraw",
            withdrawRequest.getId(),
            "提现审核拒绝，解冻冻结金额"
        );

        // 2. 更新提现申请状态
        int result = withdrawRequestMapper.updateStatusWithReviewTime(
            withdrawRequest.getId(), 
            2, 
            reason,
            adminId
        );

        if (result > 0) {
            log.info("管理员{}审核拒绝提现申请{}，拒绝原因：{}", adminId, withdrawRequest.getId(), reason);
            return ApiResponse.success("审核拒绝成功");
        } else {
            return ApiResponse.error("更新提现申请状态失败");
        }
    }

    @Override
    public ApiResponse<WithdrawDto.AdminWithdrawListResponse> getWithdrawList(WithdrawDto.AdminWithdrawListRequest request) {
        try {
            int offset = (request.getPage() - 1) * request.getSize();
            
            // 1. 查询提现申请列表
            List<WithdrawRequest> withdrawRequests = withdrawRequestMapper.selectForAdmin(
                request.getStatus(),
                request.getUserId(),
                request.getAccountType(),
                offset,
                request.getSize()
            );

            // 2. 查询总数
            Long total = withdrawRequestMapper.countForAdmin(
                request.getStatus(),
                request.getUserId(),
                request.getAccountType()
            );

            // 3. 转换为DTO
            List<WithdrawDto.AdminWithdrawItem> items = withdrawRequests.stream()
                    .map(this::convertToAdminItem)
                    .collect(Collectors.toList());

            // 4. 构建响应
            WithdrawDto.AdminWithdrawListResponse response = new WithdrawDto.AdminWithdrawListResponse();
            response.setRecords(items);
            response.setTotal(total);
            response.setPage(request.getPage());
            response.setSize(request.getSize());

            return ApiResponse.success(response);

        } catch (Exception e) {
            log.error("获取提现申请列表失败", e);
            return ApiResponse.error("获取提现申请列表失败：" + e.getMessage());
        }
    }

    @Override
    public ApiResponse<WithdrawDto.AdminWithdrawItem> getWithdrawDetail(Long withdrawId) {
        try {
            // 1. 查询提现申请
            WithdrawRequest withdrawRequest = withdrawRequestMapper.selectById(withdrawId);
            if (withdrawRequest == null) {
                return ApiResponse.error(404, "提现申请不存在");
            }

            // 2. 转换为DTO
            WithdrawDto.AdminWithdrawItem item = convertToAdminItem(withdrawRequest);

            return ApiResponse.success(item);

        } catch (Exception e) {
            log.error("获取提现申请详情失败", e);
            return ApiResponse.error("获取提现申请详情失败：" + e.getMessage());
        }
    }

    @Override
    public ApiResponse<WithdrawDto.WithdrawStatusStats> getWithdrawStats() {
        try {
            WithdrawDto.WithdrawStatusStats stats = new WithdrawDto.WithdrawStatusStats();
            
            // 统计待审核
            stats.setPendingCount(withdrawRequestMapper.countByStatus(0));
            stats.setPendingAmount(withdrawRequestMapper.sumAmountByStatus(0));
            
            // 统计已通过
            stats.setApprovedCount(withdrawRequestMapper.countByStatus(1));
            stats.setApprovedAmount(withdrawRequestMapper.sumAmountByStatus(1));
            
            // 统计已拒绝
            stats.setRejectedCount(withdrawRequestMapper.countByStatus(2));
            stats.setRejectedAmount(withdrawRequestMapper.sumAmountByStatus(2));

            return ApiResponse.success(stats);

        } catch (Exception e) {
            log.error("获取提现审核统计失败", e);
            return ApiResponse.error("获取提现审核统计失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public ApiResponse<String> batchReviewWithdraw(Long adminId, List<Long> withdrawIds, Integer status, String reason) {
        try {
            // 1. 参数验证
            if (withdrawIds == null || withdrawIds.isEmpty()) {
                return ApiResponse.error(400, "提现申请ID列表不能为空");
            }
            
            if (status == null || (status != 1 && status != 2)) {
                return ApiResponse.error(400, "审核状态只能是1（通过）或2（拒绝）");
            }
            
            if (status == 2 && !StringUtils.hasText(reason)) {
                return ApiResponse.error(400, "批量拒绝时必须填写拒绝原因");
            }

            // 2. 逐个处理每个提现申请
            int successCount = 0;
            int failCount = 0;
            
            for (Long withdrawId : withdrawIds) {
                WithdrawDto.AdminReviewRequest request = new WithdrawDto.AdminReviewRequest();
                request.setWithdrawId(withdrawId);
                request.setStatus(status);
                request.setReason(reason);
                
                ApiResponse<String> result = reviewWithdraw(adminId, request);
                if (result.getCode() == 200) {
                    successCount++;
                } else {
                    failCount++;
                    log.warn("批量审核失败：提现申请ID={}，错误：{}", withdrawId, result.getMessage());
                }
            }

            String message = String.format("批量审核完成，成功：%d，失败：%d", successCount, failCount);
            log.info("管理员{}{}，{}", adminId, status == 1 ? "批量通过提现申请" : "批量拒绝提现申请", message);
            
            return ApiResponse.success(message);

        } catch (Exception e) {
            log.error("批量审核提现申请失败", e);
            return ApiResponse.error("批量审核提现申请失败：" + e.getMessage());
        }
    }

    /**
     * 转换为管理员查看的项目DTO
     */
    private WithdrawDto.AdminWithdrawItem convertToAdminItem(WithdrawRequest withdrawRequest) {
        WithdrawDto.AdminWithdrawItem item = new WithdrawDto.AdminWithdrawItem();
        
        // 基本信息
        item.setId(withdrawRequest.getId());
        item.setUserId(withdrawRequest.getUserId());
        item.setAmount(withdrawRequest.getAmount());
        item.setWithdrawType(withdrawRequest.getWithdrawType());
        item.setAccountType(withdrawRequest.getAccountType());
        item.setAccountTypeName(WithdrawDto.AccountType.getAccountTypeName(withdrawRequest.getAccountType()));
        item.setAccount(withdrawRequest.getAccount());
        item.setAccountName(withdrawRequest.getAccountName());
        item.setBankName(withdrawRequest.getBankName());
        item.setBankBranch(withdrawRequest.getBankBranch());
        item.setStatus(withdrawRequest.getStatus());
        item.setStatusName(WithdrawDto.WithdrawStatus.getStatusName(withdrawRequest.getStatus()));
        item.setReason(withdrawRequest.getReason());
        item.setReviewerId(withdrawRequest.getReviewerId());
        item.setTransactionNo(withdrawRequest.getTransactionNo());
        item.setFeeAmount(withdrawRequest.getFeeAmount());
        item.setActualAmount(withdrawRequest.getActualAmount());
        item.setProcessedAt(withdrawRequest.getProcessedAt());
        item.setCreateTime(withdrawRequest.getCreateTime());
        item.setReviewedAt(withdrawRequest.getReviewedAt());

        // 查询用户信息
        try {
            User user = userMapper.selectById(withdrawRequest.getUserId());
            if (user != null) {
                item.setUsername(user.getUsername());
                item.setPhone(user.getPhone());
                item.setIdNumber(user.getIdNumber());
            }

            // 查询用户余额信息
            UserBalance userBalance = userBalanceService.getUserBalance(withdrawRequest.getUserId());
            if (userBalance != null) {
                item.setUserBalance(userBalance.getBalance());
                item.setUserTotalIncome(userBalance.getTotalIncome());
            }
        } catch (Exception e) {
            log.warn("查询用户信息失败：userId={}", withdrawRequest.getUserId(), e);
        }

        return item;
    }
} 