package com.liquidnet.service.adam.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.adam.dto.param.AdamCaomeiBadgeApplyParam;
import com.liquidnet.service.adam.dto.AdamCaomeiBadgeApplyRecordUserDto;
import com.liquidnet.service.adam.dto.vo.AdamCaomeiBadgeApplyRecordUserVo;
import com.liquidnet.service.adam.dto.vo.AdamRealInfoVo;
import com.liquidnet.service.adam.entity.AdamCaomeiBadgeApplyRecord;
import com.liquidnet.service.adam.entity.AdamCaomeiBadge;
import com.liquidnet.service.adam.entity.AdamCaomeiPassport;
import com.liquidnet.service.adam.mapper.AdamCaomeiBadgeApplyRecordMapper;
import com.liquidnet.service.adam.mapper.AdamCaomeiBadgeMapper;
import com.liquidnet.service.adam.mapper.AdamCaomeiPassportMapper;
import com.liquidnet.service.adam.service.AdamRdmService;
import com.liquidnet.service.adam.service.IAdamCaomeiBadgeUserService;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class AdamCaomeiBadgeUserServiceImpl implements IAdamCaomeiBadgeUserService {

    @Autowired
    private AdamCaomeiBadgeMapper adamCaomeiBadgeMapper;
    @Autowired
    private AdamCaomeiPassportMapper adamCaomeiPassportMapper;
    @Autowired
    private AdamCaomeiBadgeApplyRecordMapper badgeApplyRecordMapper;
    @Autowired
    private AdamRdmService adamRdmService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto<String> claimBadge(String badgeId, String uid) {
        if (StringUtils.isBlank(uid)) {
            return ResponseDto.failure(ErrorMapping.get("10001"));
        }

        // 1. 查询徽章配置
        AdamCaomeiBadge badge = adamCaomeiBadgeMapper.selectOne(
                Wrappers.lambdaQuery(AdamCaomeiBadge.class)
                        .eq(AdamCaomeiBadge::getBadgeId, badgeId)
                        .eq(AdamCaomeiBadge::getDisplayStatus, 1)
        );
        if (badge == null) {
            log.error("[claimBadge] 徽章不存在或未上架, uid: {}, badgeId: {}", uid, badgeId);
            return ResponseDto.failure(ErrorMapping.get("10607"));
        }

        // 2. 检查用户是否已经领取过该徽章
        int count = adamCaomeiBadgeMapper.checkUserBadgeExists(uid, badgeId);
        if (count > 0) {
            log.info("[claimBadge] 用户已领取过该徽章, uid: {}, badgeId: {}", uid, badgeId);
            return ResponseDto.failure(ErrorMapping.get("10608"));
        }

        int type = badge.getType() == null ? 0 : badge.getType();

        // 3. 根据徽章类型执行不同的认领逻辑
        if (type == 1) {
            // 护照纪念徽章：需要绑定了护照才能领取
            AdamCaomeiPassport bound = adamCaomeiPassportMapper.selectOne(
                    Wrappers.lambdaQuery(AdamCaomeiPassport.class)
                            .eq(AdamCaomeiPassport::getUserId, uid)
                            .eq(AdamCaomeiPassport::getStatus, 1)
                            .last("limit 1")
            );
            if (bound == null) {
                log.error("[claimBadge] 认领护照纪念徽章需先绑定护照, uid: {}, badgeId: {}", uid, badgeId);
                return ResponseDto.failure(ErrorMapping.get("10609"));
            }
            
            // 发放徽章 (source: 1-绑定护照自动发放/护照徽章认领)
            adamCaomeiBadgeMapper.insertUserBadge(uid, badgeId, 1);
            adamRdmService.delUserCaomeiBadgesByUid(uid);
            log.info("[claimBadge] 护照纪念徽章认领成功, uid: {}, badgeId: {}", uid, badgeId);
            return ResponseDto.success(badgeId);

        } else if (type == 2) {
            // 演出纪念徽章：需要实名认证 +（购票记录 或 补签审核已通过）
            AdamRealInfoVo real = adamRdmService.getRealInfoVoByUidPlain(uid);
            if (real == null || real.getState() == null || real.getState() != 1 || StringUtils.isBlank(real.getIdCard())) {
                log.error("[claimBadge] 认领演出徽章需先实名, uid: {}, badgeId: {}", uid, badgeId);
                return ResponseDto.failure(ErrorMapping.get("10610"));
            }

            String idCard = real.getIdCard();
            List<String> paidPerformanceIds = adamCaomeiBadgeMapper.selectPaidPerformanceIdsByIdCard(idCard);
            // 有支付记录
            boolean hasPaidRecord = paidPerformanceIds != null && paidPerformanceIds.contains(badge.getPerformanceId());
            Integer passedApplyCount = badgeApplyRecordMapper.selectCount(
                    Wrappers.lambdaQuery(AdamCaomeiBadgeApplyRecord.class)
                            .eq(AdamCaomeiBadgeApplyRecord::getUserId, uid)
                            .eq(AdamCaomeiBadgeApplyRecord::getBadgeId, badgeId)
                            .eq(AdamCaomeiBadgeApplyRecord::getAuditStatus, 1)
            );
            boolean hasPassedApply = passedApplyCount != null && passedApplyCount > 0;

            if (!hasPaidRecord && !hasPassedApply) {
                log.error("[claimBadge] 无购票记录且无通过的补签申请，无法认领, uid: {}, badgeId: {}", uid, badgeId);
                return ResponseDto.failure(ErrorMapping.get("10611"));
            }

            // 自动发放该演出所有关联徽章
//            List<AdamCaomeiBadge> performanceBadges = adamCaomeiBadgeMapper.selectList(
//                    Wrappers.lambdaQuery(AdamCaomeiBadge.class)
//                            .eq(AdamCaomeiBadge::getPerformanceId, badge.getPerformanceId())
//                            .eq(AdamCaomeiBadge::getDisplayStatus, 1)
//                            .eq(AdamCaomeiBadge::getType, 2)
//            );
            
//            for (AdamCaomeiBadge perfBadge : performanceBadges) {
                // 发放徽章：2-购票自动发放/演出徽章认领，3-补签审核通过后认领
            int source = hasPaidRecord ? 2 : 3;
            adamCaomeiBadgeMapper.insertUserBadge(uid, badgeId, source);
            adamRdmService.delUserCaomeiBadgesByUid(uid);
//            }
            
            log.info("[claimBadge] 演出纪念徽章认领成功, uid: {}, badgeId: {}, 发放数量: {}", uid, badgeId, 1);
            return ResponseDto.success(badgeId);

        } else if (type == 3) {
            // 特殊徽章不可自助领取
            log.error("[claimBadge] 特殊徽章不可自助领取, uid: {}, badgeId: {}", uid, badgeId);
            return ResponseDto.failure(ErrorMapping.get("10612"));
        }

        log.error("[claimBadge] 未知的徽章类型, uid: {}, badgeId: {}, type: {}", uid, badgeId, type);
        return ResponseDto.failure(ErrorMapping.get("10613"));
    }

    @Override
    public ResponseDto<List<AdamCaomeiBadgeApplyRecordUserVo>> getApplyRecords(String uid) {
        if (StringUtils.isBlank(uid)) {
            return ResponseDto.failure(ErrorMapping.get("10001"));
        }
        List<AdamCaomeiBadgeApplyRecordUserDto> rows = badgeApplyRecordMapper.selectUserApplyRecordsByUid(uid);
        if (rows == null) {
            rows = Collections.emptyList();
        }
        List<AdamCaomeiBadgeApplyRecordUserVo> list = rows.stream().map(r -> {
            AdamCaomeiBadgeApplyRecordUserVo v = new AdamCaomeiBadgeApplyRecordUserVo();
            v.setApplyRecordId(r.getApplyRecordId());
            v.setBadgeName(StringUtils.defaultString(r.getBadgeName()));
            v.setApplyTime(r.getApplyTime());
            v.setAuditStatus(r.getAuditStatus());
            v.setRejectReason(StringUtils.defaultString(r.getRejectReason()));
            v.setCanReupload(r.getAuditStatus() != null && r.getAuditStatus() == 2);
            v.setProofImageUrl(r.getProofImageUrl());
            return v;
        }).collect(Collectors.toList());
        return ResponseDto.success(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseDto<String> applyBadge(AdamCaomeiBadgeApplyParam param, String uid) {
        if (StringUtils.isBlank(uid)) {
            return ResponseDto.failure(ErrorMapping.get("10001"));
        }
        if (param == null || StringUtils.isBlank(param.getBadgeId()) || StringUtils.isBlank(param.getProofImageUrl())) {
            return ResponseDto.failure("参数错误");
        }
        String badgeId = StringUtils.trimToEmpty(param.getBadgeId());
        String proofImageUrl = StringUtils.trimToEmpty(param.getProofImageUrl());

        AdamCaomeiBadge badge = adamCaomeiBadgeMapper.selectOne(
                Wrappers.lambdaQuery(AdamCaomeiBadge.class)
                        .eq(AdamCaomeiBadge::getBadgeId, badgeId)
                        .last("limit 1")
        );
        if (badge == null) {
            return ResponseDto.failure(ErrorMapping.get("10607"));
        }
        if (badge.getType() == null || badge.getType() != 2) {
            return ResponseDto.failure("仅演出纪念徽章支持补签申请");
        }

        int claimedCount = adamCaomeiBadgeMapper.checkUserBadgeExists(uid, badgeId);
        if (claimedCount > 0) {
            return ResponseDto.failure(ErrorMapping.get("10608"));
        }

        Integer pendingCount = badgeApplyRecordMapper.selectCount(
                Wrappers.lambdaQuery(AdamCaomeiBadgeApplyRecord.class)
                        .eq(AdamCaomeiBadgeApplyRecord::getUserId, uid)
                        .eq(AdamCaomeiBadgeApplyRecord::getBadgeId, badgeId)
                        .eq(AdamCaomeiBadgeApplyRecord::getAuditStatus, 0)
        );
        if (pendingCount != null && pendingCount > 0) {
            return ResponseDto.failure("您已有待审核的补签申请，请勿重复提交");
        }

        Date now = new Date();
        AdamCaomeiBadgeApplyRecord record = new AdamCaomeiBadgeApplyRecord();
        record.setApplyRecordId(IDGenerator.nextSnowId());
        record.setUserId(uid);
        record.setBadgeId(badgeId);
        record.setPerformanceId(StringUtils.defaultString(badge.getPerformanceId()));
        record.setProofImageUrl(proofImageUrl);
        record.setAuditStatus(0);
        record.setRejectReason("");
        record.setCreatedAt(now);
        record.setUpdatedAt(now);
        int inserted = badgeApplyRecordMapper.insert(record);
        if (inserted <= 0) {
            return ResponseDto.failure();
        }
        return ResponseDto.success(record.getApplyRecordId());
    }
}
