package com.fs.his.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.core.domain.R;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.DateUtils;
import com.fs.common.utils.StringUtils;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyMapper;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.core.config.WxOpenProperties;
import com.fs.his.domain.FsSignArticle;
import com.fs.his.domain.FsSignArticleReadDetail;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserWx;
import com.fs.his.mapper.FsSignArticleMapper;
import com.fs.his.mapper.FsSignArticleReadDetailMapper;
import com.fs.his.mapper.FsUserMapper;
import com.fs.his.param.ClaimArticleRedPacketParam;
import com.fs.his.param.WxSendRedPacketParam;
import com.fs.his.param.APPSignArticleReadDetailParam;
import com.fs.his.service.IFsSignArticleReadDetailService;
import com.fs.his.service.IFsStorePaymentService;
import com.fs.his.service.IFsUserWxService;
import com.fs.qw.domain.QwUser;
import com.fs.qw.domain.SignRedPacketRecord;
import com.fs.qw.mapper.QwUserMapper;
import com.fs.qw.mapper.SignRedPacketRecordMapper;
import com.fs.system.service.ISysConfigService;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

import java.util.List;

/**
 * 用户阅读文章明细Service业务层处理
 *
 * @author fs
 * @date 2026-04-22
 */
@Slf4j
@Service
public class FsSignArticleReadDetailServiceImpl implements IFsSignArticleReadDetailService {
    @Autowired
    private FsSignArticleReadDetailMapper fsSignArticleReadDetailMapper;

    @Autowired
    private IFsStorePaymentService fsStorePaymentService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private WxOpenProperties openProperties;

    @Autowired
    private IFsUserWxService fsUserWxService;

    @Autowired
    private SignRedPacketRecordMapper signRedPacketRecordMapper;

    @Autowired
    private FsSignArticleMapper signArticleMapper;

    @Autowired
    private FsUserMapper userMapper;

    @Autowired
    private CompanyUserMapper companyUserMapper;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private QwUserMapper qwUserMapper;

    /**
     * 查询用户阅读文章明细
     *
     * @param id 用户阅读文章明细主键
     * @return 用户阅读文章明细
     */
    @Override
    public FsSignArticleReadDetail selectFsSignArticleReadDetailById(Long id) {
        return fsSignArticleReadDetailMapper.selectFsSignArticleReadDetailById(id);
    }

    /**
     * 查询用户阅读文章明细列表
     *
     * @param fsSignArticleReadDetail 用户阅读文章明细
     * @return 用户阅读文章明细
     */
    @Override
    public List<FsSignArticleReadDetail> selectFsSignArticleReadDetailList(FsSignArticleReadDetail fsSignArticleReadDetail) {
        return fsSignArticleReadDetailMapper.selectFsSignArticleReadDetailList(fsSignArticleReadDetail);
    }

    /**
     * 新增用户阅读文章明细
     *
     * @param fsSignArticleReadDetail 用户阅读文章明细
     * @return 结果
     */
    @Override
    public int insertFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail) {
        fsSignArticleReadDetail.setCreateTime(new java.util.Date());
        return fsSignArticleReadDetailMapper.insertFsSignArticleReadDetail(fsSignArticleReadDetail);
    }

    /**
     * 修改用户阅读文章明细
     *
     * @param fsSignArticleReadDetail 用户阅读文章明细
     * @return 结果
     */
    @Override
    public int updateFsSignArticleReadDetail(FsSignArticleReadDetail fsSignArticleReadDetail) {
        return fsSignArticleReadDetailMapper.updateFsSignArticleReadDetail(fsSignArticleReadDetail);
    }

    /**
     * 批量删除用户阅读文章明细
     *
     * @param ids 需要删除的用户阅读文章明细主键
     * @return 结果
     */
    @Override
    public int deleteFsSignArticleReadDetailByIds(Long[] ids) {
        return fsSignArticleReadDetailMapper.deleteFsSignArticleReadDetailByIds(ids);
    }

    /**
     * 删除用户阅读文章明细信息
     *
     * @param id 用户阅读文章明细主键
     * @return 结果
     */
    @Override
    public int deleteFsSignArticleReadDetailById(Long id) {
        return fsSignArticleReadDetailMapper.deleteFsSignArticleReadDetailById(id);
    }

    @Override
    public R userReadArticle(APPSignArticleReadDetailParam param) {
        if (param.getArticleId() == null && param.getUserId() == null && param.getCompanyUserId() == null) {
            return R.error("参数错误");
        }
        FsSignArticleReadDetail detail = fsSignArticleReadDetailMapper.selectUserReadDetailDataByCompanyUserIdAndArticleId(param);
        if (detail == null) {
            detail = new FsSignArticleReadDetail();
            detail.setArticleId(param.getArticleId());
            detail.setFsUserId(param.getUserId());
            detail.setShareCompanyUserId(param.getCompanyUserId());
            detail.setReadDuration(5L);
            detail.setCreateTime(new Date());
            detail.setSource("小程序");
            int i = fsSignArticleReadDetailMapper.insertFsSignArticleReadDetail(detail);
            if (i > 0) {
                return R.ok();
            }
        } else {
            FsSignArticleReadDetail map = new FsSignArticleReadDetail();
            map.setId(detail.getId());
            map.setReadDuration(detail.getReadDuration() + 5L);
            map.setUpdateTime(new Date());
            int i = fsSignArticleReadDetailMapper.updateFsSignArticleReadDetail(map);
            if (i > 0) {
                return R.ok();
            }
        }
        return R.error();
    }

    /**
     * 发送文章红包
     */
    @Override
    public R sendArticleRedPack(ClaimArticleRedPacketParam param) {

        // ******************** 阶段一：业务校验 ********************
        // 1. 是否已有红包记录？
        SignRedPacketRecord existing = signRedPacketRecordMapper
                .selectByUserIdAndArticleId(param.getUserId(), param.getArticleId());
        if (existing != null) {
            return handleExistingRecord(existing);   // 私有方法1：处理已存在记录
        }

        // 2. 今日领取次数是否超限？
        Integer maxNum = getArticleRedPacketConfig();
        if (maxNum == null || maxNum <= 0) {
            throw new CustomException("今日领取红包次数已达上限！");
        }
        int todayCount = signRedPacketRecordMapper.countTodayCollectedByUserId(param.getUserId());
        if (todayCount >= maxNum) {
            throw new CustomException("今日领取红包次数已达上限");
        }

        // 3. 文章、用户、销售、公司、企微信息是否完整？
        FsSignArticle article = signArticleMapper.selectFsSignArticleById(param.getArticleId());
        if (article == null || !Integer.valueOf(1).equals(article.getSignFlag())) {
            throw new CustomException("文章不可领取红包");
        }
        if (article.getAmount() == null || article.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new CustomException("红包金额异常");
        }

        FsUser user = userMapper.selectFsUserById(param.getUserId());
        if (user == null) throw new CustomException("用户信息缺失");

        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(param.getCompanyUserId());
        if (companyUser == null) throw new CustomException("销售信息缺失");

        Company company = companyMapper.selectCompanyById(companyUser.getCompanyId());
        if (company == null) throw new CustomException("公司信息缺失");

        QwUser qwUser = qwUserMapper.selectQwUserById(Long.valueOf(param.getQwUserId()));
        if (qwUser == null) throw new CustomException("企微用户信息缺失");

        // ******************** 阶段二：组装微信参数并发送 ********************
        WxSendRedPacketParam wxParam = new WxSendRedPacketParam();
        //处理多小程序问题
        FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
        if (fsUserWx ==null){
            try {
                handleFsUserWx(user,param.getAppId());
            }catch (Exception e){
                log.error("【更新或插入用户与小程序的绑定关系失败】：{}", user.getUserId());
            }
        }else {
            wxParam.setOpenId(fsUserWx.getOpenId());
        }
        wxParam.setAmount(article.getAmount());
        wxParam.setRedPacketMode(1);
        wxParam.setAppId(param.getAppId());
        wxParam.setMpAppId(param.getAppId());
        wxParam.setUser(user);
        wxParam.setSource(2);
        wxParam.setCompanyId(companyUser.getCompanyId());
        wxParam.setSourceType(1L);      // 文章红包标识

        R sendResult = fsStorePaymentService.sendArticleRedPack(wxParam);

        // ******************** 阶段三：处理结果并落库 ********************
        return saveRecordAndReturn(sendResult, param, user, companyUser, company, qwUser, article);
    }

// ==================== 私有方法1：处理已存在的红包记录 ====================
    /**
     * 根据已有记录的状态返回对应的前端提示
     */
    private R handleExistingRecord(SignRedPacketRecord record) {
        if (record.getCollectType() == 1) {
            return R.error("您已领取过该文章红包");
        } else if (record.getCollectType() == 0 || record.getCollectTag() == 1) {
            if (StringUtils.isNotEmpty(record.getResult())) {
                // 从数据库存的 JSON 字符串中解析出需要的字段
                JSONObject storedJson = JSON.parseObject(record.getResult());
                R result = R.ok();
                result.put("data", storedJson.get("data"));
                result.put("isNew", storedJson.get("isNew"));
                result.put("mchId", storedJson.get("mchId"));
                return result;
            } else {
                return R.error("操作频繁，请稍后再试！");
            }
        }
        return R.error("红包状态异常");
    }

// ==================== 私有方法2：保存红包发放记录 ====================
    /**
     * 解析微信返回结果，构建 SignRedPacketRecord 并入库
     */
    private R saveRecordAndReturn(R sendResult,
                                  ClaimArticleRedPacketParam param,
                                  FsUser user,
                                  CompanyUser companyUser,
                                  Company company,
                                  QwUser qwUser,
                                  FsSignArticle article) {

        if (!sendResult.get("code").equals(200)) {
            log.error("打卡文章红包-领取失败: {}", sendResult);
            throw new CustomException("系统繁忙 请稍后再试");
        }

        SignRedPacketRecord record = new SignRedPacketRecord();
        record.setResult(JSON.toJSONString(sendResult));

        Object isNew = sendResult.get("isNew");
        if (Integer.valueOf(1).equals(isNew)) {
            TransferBillsResult data = (TransferBillsResult) sendResult.get("data");
            record.setOutBatchNo(data.getOutBillNo());
            record.setBatchId(data.getTransferBillNo());
        } else {
            record.setOutBatchNo(sendResult.get("orderCode").toString());
            record.setBatchId(sendResult.get("batchId").toString());
        }

        Date now = DateUtils.getNowDate();
        record.setSignUrl(param.getSignUrl());
        record.setCollectTag(1);
        record.setCollectType(0);
        record.setSignType(param.getSignType());
        record.setSendTime(now);
        record.setUpdateTime(now);
        record.setCreateTime(now);
        record.setUserId(param.getUserId());
        record.setUserName(user.getRealName());
        record.setCompanyId(companyUser.getCompanyId());
        record.setCompanyUserId(param.getCompanyUserId());
        record.setCompanyName(company.getCompanyName());
        record.setArticleId(param.getArticleId());
        record.setAmount(article.getAmount());
        record.setQwUserId(param.getQwUserId());
        record.setQwUserName(qwUser.getQwUserName());

        signRedPacketRecordMapper.insertSignRedPacketRecord(record);
        // ========== 构造前端需要的返回结构 ==========
        R result = R.ok();                           // 自带 code=200, msg="success"
        result.put("data", sendResult.get("data"));  // 把微信的 data 对象直接放进去
        result.put("isNew", sendResult.get("isNew"));
        result.put("mchId", sendResult.get("mchId"));
        return result;
    }

    /**
     * 获取文章红包配置
     *
     * @return 领取次数
     */
    @Override
    public Integer getArticleRedPacketConfig() {
        String json = configService.selectConfigByKey("articleRedPacket.config");
        if (StringUtils.isNotEmpty(json)) {
            try {
                JSONObject jsonObject = JSON.parseObject(json);
                return jsonObject.getInteger("redPacketNum");
            } catch (Exception e) {
                log.error("解析文章红包配置失败, json={}", json, e);
                return 0;
            }
        }
        return 0; // 默认返回 0次
    }

    private void handleFsUserWx(FsUser user, String appId) {
        FsUserWx fsUserWx = new FsUserWx();
        fsUserWx.setType(1);
        fsUserWx.setFsUserId(user.getUserId());
        fsUserWx.setAppId(appId);
        fsUserWx.setOpenId(user.getCourseMaOpenId());
        fsUserWx.setUnionId(user.getUnionId());
        fsUserWx.setCreateTime(new Date());
        fsUserWx.setUpdateTime(new Date());
        fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);

        log.info("【更新或插入用户与小程序{}的绑定关系】：{}", appId, user.getUserId());
    }
}
