package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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 shop.alien.entity.store.*;
import shop.alien.entity.store.dto.AccountLogoutCompleteRequestDTO;
import shop.alien.entity.store.vo.AccountLogoutCompleteResultVo;
import shop.alien.mapper.*;
import shop.alien.store.service.AccountLogoutCompleteService;
import shop.alien.store.service.NearMeService;
import shop.alien.store.service.StoreLogoutSyncService;
import shop.alien.util.common.AccountLogoutUtil;
import shop.alien.util.common.constant.CouponStatusEnum;
import shop.alien.util.common.constant.DiscountCouponEnum;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class AccountLogoutCompleteServiceImpl implements AccountLogoutCompleteService {

    private static final String LOGOUT_DISPLAY_NAME = "已注销";

    private final StoreUserMapper storeUserMapper;
    private final StoreInfoMapper storeInfoMapper;
    private final LifeUserMapper lifeUserMapper;
    private final LawyerUserMapper lawyerUserMapper;
    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
    private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
    private final LifeCouponMapper lifeCouponMapper;
    private final NearMeService nearMeService;
    private final StoreLogoutSyncService storeLogoutSyncService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AccountLogoutCompleteResultVo completeCoolingPeriod(boolean force) {
        AccountLogoutCompleteRequestDTO request = new AccountLogoutCompleteRequestDTO();
        request.setAccountType("ALL");
        request.setForce(force);
        return completeCoolingPeriod(request);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AccountLogoutCompleteResultVo completeCoolingPeriod(AccountLogoutCompleteRequestDTO request) {
        boolean force = request == null || request.getForce() == null || Boolean.TRUE.equals(request.getForce());
        String accountType = normalizeAccountType(request != null ? request.getAccountType() : null);
        Integer id = request != null ? request.getId() : null;
        String phone = request != null ? request.getPhone() : null;

        AccountLogoutCompleteResultVo result = new AccountLogoutCompleteResultVo();
        if ("ALL".equals(accountType) || "STORE_USER".equals(accountType)) {
            completeStoreUsers(force, id, phone, result);
        }
        // 仅兼容历史独立店铺注销数据；新流程随商家用户一并注销
        if ("STORE".equals(accountType)) {
            completeLegacyStores(force, id, result);
        }
        if ("ALL".equals(accountType) || "LIFE_USER".equals(accountType)) {
            completeLifeUsers(force, id, phone, result);
        }
        if ("ALL".equals(accountType) || "LAWYER".equals(accountType)) {
            completeLawyerUsers(force, id, phone, result);
        }
        log.info("注销冷静期完成处理: force={}, type={}, success={}, fail={}, skipped={}",
                force, accountType, result.getSuccessCount(), result.getFailCount(), result.getSkippedCount());
        return result;
    }

    private void completeStoreUsers(boolean force, Integer id, String phone, AccountLogoutCompleteResultVo result) {
        LambdaQueryWrapper<StoreUser> wrapper = new LambdaQueryWrapper<StoreUser>()
                .and(w -> w.eq(StoreUser::getLogoutFlag, StoreUser.LOGOUT_FLAG_COOLING)
                        .or(o -> o.eq(StoreUser::getLogoutFlag, StoreUser.LOGOUT_FLAG_DONE)
                                .eq(StoreUser::getStatus, -1)));
        if (id != null) {
            wrapper.eq(StoreUser::getId, id);
        }
        if (StringUtils.hasText(phone)) {
            wrapper.eq(StoreUser::getPhone, phone);
        }
        for (StoreUser storeUser : storeUserMapper.selectList(wrapper)) {
            try {
                if (storeUser.getLogoutTime() == null) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("STORE_USER#" + storeUser.getId() + " 跳过：无 logoutTime");
                    continue;
                }
                if (!force && !AccountLogoutUtil.isLogoutCoolingExpired(storeUser.getLogoutTime())) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("STORE_USER#" + storeUser.getId() + " 跳过：未满7天冷静期");
                    continue;
                }
                storeUser.setLogoutFlag(StoreUser.LOGOUT_FLAG_DONE);
                storeUser.setName(LOGOUT_DISPLAY_NAME);
                storeUser.setNickName(LOGOUT_DISPLAY_NAME);
                storeUser.setHeadImg(null);
                if (Integer.valueOf(-1).equals(storeUser.getStatus())) {
                    storeUser.setStatus(0);
                }
                LambdaUpdateWrapper<StoreUser> storeUserUpdate = new LambdaUpdateWrapper<StoreUser>()
                        .eq(StoreUser::getId, storeUser.getId())
                        .set(StoreUser::getLogoutFlag, StoreUser.LOGOUT_FLAG_DONE)
                        .set(StoreUser::getName, LOGOUT_DISPLAY_NAME)
                        .set(StoreUser::getNickName, LOGOUT_DISPLAY_NAME)
                        .set(StoreUser::getHeadImg, null);
                if (Integer.valueOf(-1).equals(storeUser.getStatus())) {
                    storeUserUpdate.set(StoreUser::getStatus, 0);
                }
                storeUserMapper.update(null, storeUserUpdate);
                storeLogoutSyncService.completeLogoutForStoreUser(storeUser, result);
                result.setSuccessCount(result.getSuccessCount() + 1);
                result.addDetail("STORE_USER#" + storeUser.getId() + " 已注销");
            } catch (Exception e) {
                result.setFailCount(result.getFailCount() + 1);
                result.addDetail("STORE_USER#" + storeUser.getId() + " 失败：" + e.getMessage());
                log.error("商家账号注销完成失败 userId={}", storeUser.getId(), e);
            }
        }
    }

    /** 处理历史独立店铺注销数据（新流程已合并至商家用户注销） */
    private void completeLegacyStores(boolean force, Integer storeId, AccountLogoutCompleteResultVo result) {
        LambdaQueryWrapper<StoreInfo> wrapper = new LambdaQueryWrapper<StoreInfo>()
                .and(w -> w.eq(StoreInfo::getLogoutFlag, StoreInfo.LOGOUT_FLAG_COOLING)
                        .or(o -> o.eq(StoreInfo::getLogoutFlag, StoreInfo.LOGOUT_FLAG_DONE)
                                .eq(StoreInfo::getStoreStatus, -1)));
        if (storeId != null) {
            wrapper.eq(StoreInfo::getId, storeId);
        }
        for (StoreInfo storeInfo : storeInfoMapper.selectList(wrapper)) {
            try {
                if (storeInfo.getLogoutTime() == null) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("STORE#" + storeInfo.getId() + " 跳过：无 logoutTime");
                    continue;
                }
                if (!force && !AccountLogoutUtil.isLogoutCoolingExpired(storeInfo.getLogoutTime())) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("STORE#" + storeInfo.getId() + " 跳过：未满7天冷静期");
                    continue;
                }
                if (StoreInfo.LOGOUT_FLAG_DONE == storeInfo.getLogoutFlag()
                        && StoreInfo.BUSINESS_STATUS_PERMANENT_CLOSE == storeInfo.getBusinessStatus()) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("STORE#" + storeInfo.getId() + " 跳过：已是已注销状态");
                    continue;
                }
                invalidateStoreCoupons(storeInfo.getId());
                try {
                    nearMeService.removeGeolocation(Boolean.TRUE, storeInfo.getId().toString());
                } catch (Exception e) {
                    log.warn("清理Redis地理位置失败 storeId={}", storeInfo.getId(), e);
                }
                storeInfoMapper.update(null, new LambdaUpdateWrapper<StoreInfo>()
                        .eq(StoreInfo::getId, storeInfo.getId())
                        .set(StoreInfo::getLogoutFlag, StoreInfo.LOGOUT_FLAG_DONE)
                        .set(StoreInfo::getStoreStatus, 2)
                        .set(StoreInfo::getBusinessStatus, StoreInfo.BUSINESS_STATUS_PERMANENT_CLOSE)
                        .set(StoreInfo::getStoreName, LOGOUT_DISPLAY_NAME));
                result.setSuccessCount(result.getSuccessCount() + 1);
                result.addDetail("STORE#" + storeInfo.getId() + " 已注销");
            } catch (Exception e) {
                result.setFailCount(result.getFailCount() + 1);
                result.addDetail("STORE#" + storeInfo.getId() + " 失败：" + e.getMessage());
                log.error("店铺注销完成失败 storeId={}", storeInfo.getId(), e);
            }
        }
    }

    private void completeLifeUsers(boolean force, Integer id, String phone, AccountLogoutCompleteResultVo result) {
        LambdaQueryWrapper<LifeUser> wrapper = new LambdaQueryWrapper<LifeUser>()
                .eq(LifeUser::getLogoutFlag, LifeUser.LOGOUT_FLAG_COOLING);
        if (id != null) {
            wrapper.eq(LifeUser::getId, id);
        }
        if (StringUtils.hasText(phone)) {
            wrapper.eq(LifeUser::getUserPhone, phone);
        }
        for (LifeUser lifeUser : lifeUserMapper.selectList(wrapper)) {
            try {
                if (lifeUser.getLogoutTime() == null) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("LIFE_USER#" + lifeUser.getId() + " 跳过：无 logoutTime");
                    continue;
                }
                if (!force && !AccountLogoutUtil.isLogoutCoolingExpired(lifeUser.getLogoutTime())) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("LIFE_USER#" + lifeUser.getId() + " 跳过：未满7天冷静期");
                    continue;
                }
                lifeUserMapper.update(null, new LambdaUpdateWrapper<LifeUser>()
                        .eq(LifeUser::getId, lifeUser.getId())
                        .set(LifeUser::getLogoutFlag, LifeUser.LOGOUT_FLAG_DONE)
                        .set(LifeUser::getUserName, LOGOUT_DISPLAY_NAME)
                        .set(LifeUser::getUserImage, null));
                result.setSuccessCount(result.getSuccessCount() + 1);
                result.addDetail("LIFE_USER#" + lifeUser.getId() + " 已注销");
            } catch (Exception e) {
                result.setFailCount(result.getFailCount() + 1);
                result.addDetail("LIFE_USER#" + lifeUser.getId() + " 失败：" + e.getMessage());
                log.error("C端用户注销完成失败 userId={}", lifeUser.getId(), e);
            }
        }
    }

    private void completeLawyerUsers(boolean force, Integer id, String phone, AccountLogoutCompleteResultVo result) {
        LambdaQueryWrapper<LawyerUser> wrapper = new LambdaQueryWrapper<LawyerUser>()
                .eq(LawyerUser::getLogoutFlag, LawyerUser.LOGOUT_FLAG_COOLING)
                .eq(LawyerUser::getDeleteFlag, 0);
        if (id != null) {
            wrapper.eq(LawyerUser::getId, id);
        }
        if (StringUtils.hasText(phone)) {
            wrapper.eq(LawyerUser::getPhone, phone);
        }
        for (LawyerUser lawyerUser : lawyerUserMapper.selectList(wrapper)) {
            try {
                if (lawyerUser.getLogoutTime() == null) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("LAWYER#" + lawyerUser.getId() + " 跳过：无 logoutTime");
                    continue;
                }
                if (!force && !AccountLogoutUtil.isLogoutCoolingExpired(lawyerUser.getLogoutTime())) {
                    result.setSkippedCount(result.getSkippedCount() + 1);
                    result.addDetail("LAWYER#" + lawyerUser.getId() + " 跳过：未满7天冷静期");
                    continue;
                }
                lawyerUserMapper.update(null, new LambdaUpdateWrapper<LawyerUser>()
                        .eq(LawyerUser::getId, lawyerUser.getId())
                        .set(LawyerUser::getLogoutFlag, LawyerUser.LOGOUT_FLAG_DONE)
                        .set(LawyerUser::getName, LOGOUT_DISPLAY_NAME)
                        .set(LawyerUser::getNickName, LOGOUT_DISPLAY_NAME)
                        .set(LawyerUser::getHeadImg, null)
                        .set(LawyerUser::getOrderReceivingStatus, 0)
                        .set(LawyerUser::getIsOnline, 0)
                        .set(LawyerUser::getIsRecommended, 0)
                        .set(LawyerUser::getLastOnlineTime, new Date()));
                result.setSuccessCount(result.getSuccessCount() + 1);
                result.addDetail("LAWYER#" + lawyerUser.getId() + " 已注销");
            } catch (Exception e) {
                result.setFailCount(result.getFailCount() + 1);
                result.addDetail("LAWYER#" + lawyerUser.getId() + " 失败：" + e.getMessage());
                log.error("律师注销完成失败 lawyerId={}", lawyerUser.getId(), e);
            }
        }
    }

    private void invalidateStoreCoupons(Integer storeId) {
        if (storeId == null) {
            return;
        }
        String storeIdStr = String.valueOf(storeId);
        int voidedUserCouponStatus = Integer.parseInt(DiscountCouponEnum.HAVE_BEEN_VOIDED.getValue());

        lifeDiscountCouponMapper.update(null, new LambdaUpdateWrapper<LifeDiscountCoupon>()
                .eq(LifeDiscountCoupon::getStoreId, storeIdStr)
                .set(LifeDiscountCoupon::getCouponStatus, LifeDiscountCoupon.COUPON_STATUS_INVALID)
                .set(LifeDiscountCoupon::getGetStatus, 0));

        List<LifeDiscountCoupon> storeCoupons = lifeDiscountCouponMapper.selectList(
                new LambdaQueryWrapper<LifeDiscountCoupon>().eq(LifeDiscountCoupon::getStoreId, storeIdStr));
        if (!storeCoupons.isEmpty()) {
            List<Integer> couponIds = storeCoupons.stream().map(LifeDiscountCoupon::getId).collect(Collectors.toList());
            lifeDiscountCouponUserMapper.update(null, new LambdaUpdateWrapper<LifeDiscountCouponUser>()
                    .in(LifeDiscountCouponUser::getCouponId, couponIds)
                    .eq(LifeDiscountCouponUser::getStatus, Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()))
                    .set(LifeDiscountCouponUser::getStatus, voidedUserCouponStatus));
        }

        lifeCouponMapper.update(null, new LambdaUpdateWrapper<LifeCoupon>()
                .eq(LifeCoupon::getStoreId, storeIdStr)
                .notIn(LifeCoupon::getStatus, CouponStatusEnum.ENDED.getCode(), CouponStatusEnum.INVALID.getCode())
                .set(LifeCoupon::getStatus, CouponStatusEnum.INVALID.getCode()));

        List<LifeCoupon> storeVouchers = lifeCouponMapper.selectList(
                new LambdaQueryWrapper<LifeCoupon>().eq(LifeCoupon::getStoreId, storeIdStr));
        if (!storeVouchers.isEmpty()) {
            List<String> voucherIds = storeVouchers.stream().map(LifeCoupon::getId).collect(Collectors.toList());
            lifeDiscountCouponUserMapper.update(null, new LambdaUpdateWrapper<LifeDiscountCouponUser>()
                    .in(LifeDiscountCouponUser::getVoucherId, voucherIds)
                    .eq(LifeDiscountCouponUser::getStatus, Integer.parseInt(DiscountCouponEnum.WAITING_USED.getValue()))
                    .set(LifeDiscountCouponUser::getStatus, voidedUserCouponStatus));
        }
    }

    private static String normalizeAccountType(String accountType) {
        if (!StringUtils.hasText(accountType)) {
            return "ALL";
        }
        return accountType.trim().toUpperCase(Locale.ROOT);
    }
}
