package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import shop.alien.entity.store.LifeCoupon;
import shop.alien.entity.store.LifeDiscountCoupon;
import shop.alien.entity.store.LifeDiscountCouponUser;
import shop.alien.entity.store.StoreInfo;
import shop.alien.entity.store.StoreUser;
import shop.alien.entity.store.vo.AccountLogoutCompleteResultVo;
import shop.alien.mapper.LifeCouponMapper;
import shop.alien.mapper.LifeDiscountCouponMapper;
import shop.alien.mapper.LifeDiscountCouponUserMapper;
import shop.alien.mapper.StoreInfoMapper;
import shop.alien.store.service.NearMeService;
import shop.alien.store.service.StoreLogoutSyncService;
import shop.alien.util.common.constant.CouponStatusEnum;
import shop.alien.util.common.constant.DiscountCouponEnum;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

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

@Slf4j
@Service
@RequiredArgsConstructor
public class StoreLogoutSyncServiceImpl implements StoreLogoutSyncService {

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

    private final StoreInfoMapper storeInfoMapper;
    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
    private final LifeDiscountCouponUserMapper lifeDiscountCouponUserMapper;
    private final LifeCouponMapper lifeCouponMapper;
    private final NearMeService nearMeService;

    @Override
    public void applyCoolingForStoreUser(StoreUser storeUser, String logoutReason, String logoutCode) {
        StoreInfo store = getLinkedStore(storeUser);
        if (store == null) {
            return;
        }
        storeInfoMapper.update(null, new LambdaUpdateWrapper<StoreInfo>()
                .eq(StoreInfo::getId, store.getId())
                .set(StoreInfo::getLogoutFlag, StoreInfo.LOGOUT_FLAG_COOLING)
                .set(StoreInfo::getBusinessStatus, StoreInfo.BUSINESS_STATUS_PAUSE)
                .set(StoreInfo::getStoreStatus, -1)
                .set(StoreInfo::getLogoutTime, storeUser.getLogoutTime())
                .set(StoreInfo::getLogoutReason, logoutReason)
                .set(StoreInfo::getLogoutCode, logoutCode));
        log.info("关联店铺进入注销冷静期: storeId={}, userId={}", store.getId(), storeUser.getId());
    }

    @Override
    public void revokeCoolingForStoreUser(StoreUser storeUser) {
        StoreInfo store = getLinkedStore(storeUser);
        if (store == null) {
            return;
        }
        storeInfoMapper.update(null, new LambdaUpdateWrapper<StoreInfo>()
                .eq(StoreInfo::getId, store.getId())
                .set(StoreInfo::getLogoutFlag, StoreInfo.LOGOUT_FLAG_NORMAL)
                // 暂停营业，当撤销注销时，营业状态变成暂停营业，不管注销之前或者是注销之后的状态是什么，都改为暂停营业
//                .set(StoreInfo::getBusinessStatus, StoreInfo.BUSINESS_STATUS_NORMAL)
                .set(StoreInfo::getBusinessStatus, 1)
                .set(StoreInfo::getStoreStatus, 1)
                .set(StoreInfo::getLogoutReason, "")
                .set(StoreInfo::getLogoutCode, "")
                .set(StoreInfo::getLogoutTime, null));
        log.info("关联店铺撤销注销冷静期: storeId={}, userId={}", store.getId(), storeUser.getId());
    }

    @Override
    public void completeLogoutForStoreUser(StoreUser storeUser, AccountLogoutCompleteResultVo result) {
        StoreInfo store = getLinkedStore(storeUser);
        if (store == null) {
            if (result != null) {
                result.addDetail("STORE_USER#" + storeUser.getId() + " 无关联店铺，跳过店铺同步");
            }
            return;
        }
        if (isStoreLogoutCompleted(store)) {
            if (result != null) {
                result.addDetail("STORE#" + store.getId() + " 跳过：已是已注销状态");
            }
            return;
        }
        try {
            invalidateStoreCoupons(store.getId());
            try {
                nearMeService.removeGeolocation(Boolean.TRUE, store.getId().toString());
            } catch (Exception e) {
                log.warn("清理Redis地理位置失败 storeId={}", store.getId(), e);
            }
            storeInfoMapper.update(null, new LambdaUpdateWrapper<StoreInfo>()
                    .eq(StoreInfo::getId, store.getId())
                    .set(StoreInfo::getLogoutFlag, StoreInfo.LOGOUT_FLAG_DONE)
                    .set(StoreInfo::getStoreStatus, 2)
                    .set(StoreInfo::getBusinessStatus, StoreInfo.BUSINESS_STATUS_PERMANENT_CLOSE)
                    .set(StoreInfo::getLogoutTime, storeUser.getLogoutTime()));
            if (result != null) {
                result.addDetail("STORE#" + store.getId() + " 已注销（随商家用户同步）");
            }
            log.info("关联店铺注销完成: storeId={}, userId={}", store.getId(), storeUser.getId());
        } catch (Exception e) {
            log.error("关联店铺注销完成失败 storeId={}, userId={}", store.getId(), storeUser.getId(), e);
            throw e;
        }
    }

    private StoreInfo getLinkedStore(StoreUser storeUser) {
        if (storeUser == null || storeUser.getStoreId() == null) {
            return null;
        }
        return storeInfoMapper.selectById(storeUser.getStoreId());
    }

    private static boolean isStoreLogoutCompleted(StoreInfo store) {
        return store != null
                && StoreInfo.LOGOUT_FLAG_DONE == store.getLogoutFlag()
                && StoreInfo.BUSINESS_STATUS_PERMANENT_CLOSE == store.getBusinessStatus();
    }

    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));
        }
    }
}
