package com.gxwebsoft.shop.controller;

import cn.hutool.core.util.StrUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.ShopDealerUser;
import com.gxwebsoft.shop.service.ShopDealerUserService;
import com.gxwebsoft.shop.service.ShopDealerWithdrawService;
import com.gxwebsoft.shop.entity.ShopDealerWithdraw;
import com.gxwebsoft.shop.param.ShopDealerWithdrawParam;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.common.core.web.BatchParam;
import com.gxwebsoft.common.core.annotation.OperationLog;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.payment.exception.PaymentException;
import com.gxwebsoft.payment.service.WxTransferService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 分销商提现明细表控制器
 *
 * @author 科技小王子
 * @since 2025-08-11 23:51:41
 */
@Tag(name = "分销商提现明细表管理")
@RestController
@RequestMapping("/api/shop/shop-dealer-withdraw")
public class ShopDealerWithdrawController extends BaseController {
    @Resource
    private ShopDealerWithdrawService shopDealerWithdrawService;
    @Resource
    private ShopDealerUserService shopDealerUserService;
    @Resource
    private WxTransferService wxTransferService;

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:list')")
    @Operation(summary = "分页查询分销商提现明细表")
    @GetMapping("/page")
    public ApiResult<PageResult<ShopDealerWithdraw>> page(ShopDealerWithdrawParam param) {
        // 使用关联查询
        return success(shopDealerWithdrawService.pageRel(param));
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:list')")
    @Operation(summary = "查询全部分销商提现明细表")
    @GetMapping()
    public ApiResult<List<ShopDealerWithdraw>> list(ShopDealerWithdrawParam param) {
        // 使用关联查询
        return success(shopDealerWithdrawService.listRel(param));
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:list')")
    @Operation(summary = "根据id查询分销商提现明细表")
    @GetMapping("/{id}")
    public ApiResult<ShopDealerWithdraw> get(@PathVariable("id") Integer id) {
        // 使用关联查询
        return success(shopDealerWithdrawService.getByIdRel(id));
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:save')")
    @Transactional(rollbackFor = {Exception.class})
    @Operation(summary = "添加分销商提现明细表")
    @PostMapping()
    public ApiResult<?> save(@RequestBody ShopDealerWithdraw shopDealerWithdraw) {
        try {
            // 记录当前登录用户id
            User loginUser = getLoginUser();
            if (loginUser == null) {
                return fail("未登录或登录已失效");
            }

            if (shopDealerWithdraw.getMoney() == null || shopDealerWithdraw.getMoney().compareTo(java.math.BigDecimal.ZERO) <= 0) {
                return fail("提现金额必须大于0");
            }

            Integer tenantId = shopDealerWithdraw.getTenantId() != null ? shopDealerWithdraw.getTenantId() : getTenantId();
            if (tenantId == null) {
                return fail("tenantId为空，无法发起提现");
            }

            shopDealerWithdraw.setTenantId(tenantId);
            shopDealerWithdraw.setUserId(loginUser.getUserId());

            Integer payType = shopDealerWithdraw.getPayType();
            if (payType == null) {
                return fail("提现方式不能为空");
            }

            // 资金安全：用户申请后统一进入“待审核(10)”，审核通过后再由用户主动领取
            shopDealerWithdraw.setApplyStatus(10);
            shopDealerWithdraw.setAuditTime(null);

            if(shopDealerWithdraw.getTenantId().equals(10584)){
              // 1.如果体现金额小于等于50，则可以自动审核通过
              if (shopDealerWithdraw.getMoney().compareTo(java.math.BigDecimal.valueOf(50)) <= 0) {
                shopDealerWithdraw.setApplyStatus(20);
                shopDealerWithdraw.setAuditTime(LocalDateTime.now());
              }
              // 2.如果提现金额大于50，小于1000，则需要人工审核
              shopDealerWithdraw.setApplyStatus(10);
              shopDealerWithdraw.setAuditTime(null);
              // 3.如果金额大于1000，小于10000，则除了财务审核还需要农总审核

              // 4.如果金额大于10000，则需要财务、农总、明、钟四个人审核

            }

            final ShopDealerUser dealerUser = shopDealerUserService.getByUserIdRel(loginUser.getUserId());
            if (dealerUser == null) {
                return fail("分销商信息不存在");
            }
            if (dealerUser.getMoney() == null || dealerUser.getMoney().compareTo(shopDealerWithdraw.getMoney()) < 0) {
                return fail("可提现佣金不足");
            }

            if (!shopDealerWithdrawService.save(shopDealerWithdraw)) {
                return fail("添加失败");
            }

            // 扣除提现金额
            dealerUser.setMoney(dealerUser.getMoney().subtract(shopDealerWithdraw.getMoney()));
            if (!shopDealerUserService.updateById(dealerUser)) {
                throw PaymentException.systemError("扣减可提现佣金失败", null);
            }

            return success("添加成功");
        } catch (PaymentException e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return fail(e.getMessage());
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return fail("添加失败");
        }
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:update')")
    @Transactional(rollbackFor = {Exception.class})
    @Operation(summary = "修改分销商提现明细表")
    @PutMapping()
    public ApiResult<?> update(@RequestBody ShopDealerWithdraw shopDealerWithdraw) {
        if (shopDealerWithdraw.getId() == null) {
            return fail("id不能为空");
        }

        // 以DB原数据为准，避免前端未传字段导致逻辑判断错误/金额被篡改等问题
        ShopDealerWithdraw db = shopDealerWithdrawService.getByIdRel(shopDealerWithdraw.getId());
        if (db == null) {
            return fail("提现记录不存在");
        }

        // 防御：前端未传字段时，避免被 updateById 更新为 NULL
        if (shopDealerWithdraw.getApplyStatus() == null) {
            shopDealerWithdraw.setApplyStatus(db.getApplyStatus());
        }
        if (shopDealerWithdraw.getPayType() == null) {
            shopDealerWithdraw.setPayType(db.getPayType());
        }

        Integer newStatus = shopDealerWithdraw.getApplyStatus() != null ? shopDealerWithdraw.getApplyStatus() : db.getApplyStatus();
        Integer oldStatus = db.getApplyStatus();
        Integer payType = shopDealerWithdraw.getPayType() != null ? shopDealerWithdraw.getPayType() : db.getPayType();
        Integer incomingStatus = shopDealerWithdraw.getApplyStatus();

        // 驳回操作（状态迁移到30时），退回金额，避免重复退回
        if (Integer.valueOf(30).equals(newStatus) && !Integer.valueOf(30).equals(oldStatus)) {
            ShopDealerUser dealerUser = shopDealerUserService.getByUserIdRel(db.getUserId());
            if (dealerUser != null && dealerUser.getMoney() != null && db.getMoney() != null) {
                dealerUser.setMoney(dealerUser.getMoney().add(db.getMoney()));
                shopDealerUserService.updateById(dealerUser);
            }
        }

        // 审核通过：仅标记为 20，等待用户在提现记录中主动领取（微信等在线转账在领取环节执行）
        if (Integer.valueOf(20).equals(incomingStatus) && !Integer.valueOf(20).equals(oldStatus)) {
            shopDealerWithdraw.setAuditTime(LocalDateTime.now());
        }

        // 微信提现：已打款(40)由用户“领取成功”后置为 40，后台不允许直接改为 40
        if (Integer.valueOf(10).equals(payType)
            && Integer.valueOf(40).equals(incomingStatus)
            && !Integer.valueOf(40).equals(oldStatus)) {
            return fail("微信提现请用户在提现记录中领取后自动完成，后台不可直接置为已打款");
        }

        // 已打款：非微信自动转账的场景，要求上传凭证
        if (Integer.valueOf(40).equals(incomingStatus) && !Integer.valueOf(40).equals(oldStatus)) {
            shopDealerWithdraw.setAuditTime(LocalDateTime.now());
            if (!Integer.valueOf(10).equals(payType) && StrUtil.isBlankIfStr(shopDealerWithdraw.getImage())) {
                return fail("请上传打款凭证");
            }
        }
        if (shopDealerWithdrawService.updateById(shopDealerWithdraw)) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:update')")
    @Operation(summary = "用户领取提现（审核通过后，返回微信收款确认页 package_info）")
    @PostMapping("/receive/{id}")
    public ApiResult<?> receive(@PathVariable("id") Integer id) {
        try {
            User loginUser = getLoginUser();
            if (loginUser == null) {
                return fail("未登录或登录已失效");
            }
            if (id == null) {
                return fail("id不能为空");
            }

            ShopDealerWithdraw db = shopDealerWithdrawService.getByIdRel(id);
            if (db == null) {
                return fail("提现记录不存在");
            }
            if (!loginUser.getUserId().equals(db.getUserId())) {
                return fail("无权领取该提现记录");
            }
            if (!Integer.valueOf(20).equals(db.getApplyStatus())) {
                return fail("当前状态不可领取");
            }
            if (!Integer.valueOf(10).equals(db.getPayType())) {
                return fail("仅微信提现支持在线领取");
            }

            Integer tenantId = db.getTenantId() != null ? db.getTenantId() : getTenantId();
            if (tenantId == null) {
                return fail("tenantId为空，无法发起微信转账");
            }

            String openid = StrUtil.isNotBlank(db.getOpenId()) ? db.getOpenId() : db.getOfficeOpenid();
            if (StrUtil.isBlank(openid)) {
                // 兜底：从分销商信息关联获取openid
                ShopDealerUser dealerUser = shopDealerUserService.getByUserIdRel(db.getUserId());
                if (dealerUser != null && StrUtil.isNotBlank(dealerUser.getOpenid())) {
                    openid = dealerUser.getOpenid();
                }
            }
            if (StrUtil.isBlank(openid)) {
                return fail("用户openid为空，无法拉起微信收款确认页");
            }

            // 使用提现记录ID构造单号，保持幂等；微信要求 5-32 且仅字母/数字
            String outBillNo = String.format("WD%03d", db.getId());
            String remark = "分销商提现";
            String userName = db.getRealName();

            WxTransferService.TransferBillsResponse resp = wxTransferService.initiateSingleTransferWithUserConfirm(
                tenantId,
                openid,
                db.getMoney(),
                outBillNo,
                remark,
                userName
            );
            if (resp == null || StrUtil.isBlank(resp.getPackageInfo())) {
                return fail("后台未返回 package_info，无法调起微信收款确认页");
            }

            Map<String, Object> data = new HashMap<>();
            data.put("package_info", resp.getPackageInfo());
            return success("领取发起成功", data);
        } catch (PaymentException e) {
            return fail(e.getMessage());
        } catch (Exception e) {
            return fail("领取失败");
        }
    }

    @Operation(summary = "用户领取成功回调（将状态置为已打款/已领取40）")
    @PostMapping("/receive-success/{id}")
    public ApiResult<?> receiveSuccess(@PathVariable("id") Integer id) {
        User loginUser = getLoginUser();
        if (loginUser == null) {
            return fail("未登录或登录已失效");
        }
        if (id == null) {
            return fail("id不能为空");
        }

        ShopDealerWithdraw db = shopDealerWithdrawService.getByIdRel(id);
        if (db == null) {
            return fail("提现记录不存在");
        }
        if (!loginUser.getUserId().equals(db.getUserId())) {
            return fail("无权操作该提现记录");
        }
        if (!Integer.valueOf(10).equals(db.getPayType())) {
            return fail("仅微信提现支持在线领取");
        }
        if (Integer.valueOf(40).equals(db.getApplyStatus())) {
            return success("已领取");
        }
        if (!Integer.valueOf(20).equals(db.getApplyStatus())) {
            return fail("当前状态不可确认领取");
        }

        ShopDealerWithdraw upd = new ShopDealerWithdraw();
        upd.setId(db.getId());
        upd.setApplyStatus(40);
        upd.setAuditTime(LocalDateTime.now());
        if (shopDealerWithdrawService.updateById(upd)) {
            return success("领取成功");
        }
        return fail("领取失败");
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:remove')")
    @OperationLog
    @Operation(summary = "删除分销商提现明细表")
    @DeleteMapping("/{id}")
    public ApiResult<?> remove(@PathVariable("id") Integer id) {
        if (shopDealerWithdrawService.removeById(id)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:save')")
    @OperationLog
    @Operation(summary = "批量添加分销商提现明细表")
    @PostMapping("/batch")
    public ApiResult<?> saveBatch(@RequestBody List<ShopDealerWithdraw> list) {
        if (shopDealerWithdrawService.saveBatch(list)) {
            return success("添加成功");
        }
        return fail("添加失败");
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:update')")
    @OperationLog
    @Operation(summary = "批量修改分销商提现明细表")
    @PutMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopDealerWithdraw> batchParam) {
        if (batchParam.update(shopDealerWithdrawService, "id")) {
            return success("修改成功");
        }
        return fail("修改失败");
    }

    @PreAuthorize("hasAuthority('shop:shopDealerWithdraw:remove')")
    @OperationLog
    @Operation(summary = "批量删除分销商提现明细表")
    @DeleteMapping("/batch")
    public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) {
        if (shopDealerWithdrawService.removeByIds(ids)) {
            return success("删除成功");
        }
        return fail("删除失败");
    }

}
