package org.dromara.main.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.ratelimiter.annotation.RateLimiter;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.web.core.BaseController;
import org.dromara.main.domain.WithdrawAccount;
import org.dromara.main.domain.bo.WithdrawBo;
import org.dromara.main.domain.vo.WithdrawAccountVo;
import org.dromara.main.domain.vo.WithdrawVo;
import org.dromara.main.mapper.WithdrawAccountMapper;
import org.dromara.main.service.IWithdrawService;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.service.ISysTenantService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 门户提现接口
 */
@Slf4j
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/portal/withdraw")
public class PortalWithdrawController extends BaseController {

    private final IWithdrawService withdrawService;
    private final WithdrawAccountMapper withdrawAccountMapper;
    private final ISysTenantService tenantService;

    @GetMapping("/account/list")
    public R<List<WithdrawAccountVo>> getAccountList() {
        Long companyId = getCurrentCompany().getId();

        LambdaQueryWrapper<WithdrawAccount> lqw = Wrappers.lambdaQuery();
        lqw.eq(WithdrawAccount::getCompanyId, companyId);
        lqw.eq(WithdrawAccount::getStatus, 1);
        lqw.orderByDesc(WithdrawAccount::getIsDefault);
        lqw.orderByDesc(WithdrawAccount::getCreateTime);
        return R.ok(withdrawAccountMapper.selectVoList(lqw));
    }

    @PostMapping("/account/save")
    public R<Void> saveAccount(@RequestBody WithdrawAccount account) {
        Long companyId = getCurrentCompany().getId();
        account.setCompanyId(companyId);
        account.setStatus(1);
        if (account.getIsDefault() == null) {
            account.setIsDefault(1);
        }

        if (account.getIsDefault() == 1) {
            WithdrawAccount reset = new WithdrawAccount();
            reset.setIsDefault(0);
            withdrawAccountMapper.update(reset, Wrappers.<WithdrawAccount>lambdaUpdate()
                .eq(WithdrawAccount::getCompanyId, companyId));
        }

        if (account.getId() != null) {
            WithdrawAccount exists = withdrawAccountMapper.selectById(account.getId());
            if (exists == null || !companyId.equals(exists.getCompanyId())) {
                return R.fail("收款账户不存在");
            }
            withdrawAccountMapper.updateById(account);
        } else {
            WithdrawAccount exists = withdrawAccountMapper.selectOne(Wrappers.<WithdrawAccount>lambdaQuery()
                .eq(WithdrawAccount::getCompanyId, companyId)
                .eq(WithdrawAccount::getAccountType, account.getAccountType())
                .last("limit 1"));
            if (exists != null) {
                account.setId(exists.getId());
                withdrawAccountMapper.updateById(account);
            } else {
                withdrawAccountMapper.insert(account);
            }
        }

        return R.ok();
    }

    @RateLimiter(key = "#phonenumber", time = 60, count = 5)
    @PostMapping("/sendSmsCode")
    public R<Void> sendSmsCode(@RequestParam @NotBlank(message = "手机号不能为空") String phonenumber) {
        String code = RandomUtil.randomNumbers(6);
        RedisUtils.setCacheObject("captcha_codes:withdraw:" + phonenumber, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
        log.warn("提现验证码已生成，手机号: {}, code: {}", phonenumber, code);
        return R.ok();
    }

    @GetMapping("/list")
    public TableDataInfo<WithdrawVo> list(WithdrawBo bo, PageQuery pageQuery) {
        bo.setCompanyId(getCurrentCompany().getId());
        return withdrawService.queryPageList(bo, pageQuery);
    }

    @PostMapping("/apply")
    public R<Long> apply(@Validated(AddGroup.class) @RequestBody WithdrawBo bo) {
        Long id = withdrawService.applyWithdraw(bo);
        return R.ok("提现申请已提交，等待审核", id);
    }

    @SaIgnore
    @PostMapping("/alipay/notify")
    public String alipayTransferNotify(HttpServletRequest request) {
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        return withdrawService.handleAlipayTransferNotify(params);
    }

    private SysTenantVo getCurrentCompany() {
        String tenantId = LoginHelper.getTenantId();
        if (tenantId == null || tenantId.isBlank()) {
            throw new org.dromara.common.core.exception.ServiceException("未登录或token已失效");
        }
        SysTenantVo company = tenantService.queryByTenantId(tenantId);
        if (company == null) {
            throw new org.dromara.common.core.exception.ServiceException("企业信息不存在");
        }
        return company;
    }
}
