package com.ruoyi.ss.store.service.impl;

import com.github.pagehelper.PageHelper;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.collection.CollectionUtils;
import com.ruoyi.ss.device.domain.DeviceQuery;
import com.ruoyi.ss.device.service.DeviceService;
import com.ruoyi.ss.store.domain.*;
import com.ruoyi.ss.store.domain.enums.StoreGroupBy;
import com.ruoyi.ss.store.domain.enums.StoreStatus;
import com.ruoyi.ss.store.mapper.StoreMapper;
import com.ruoyi.ss.store.service.StoreAssembler;
import com.ruoyi.ss.store.service.StoreService;
import com.ruoyi.ss.store.service.StoreValidator;
import com.ruoyi.ss.storeApply.domain.enums.StoreApplyType;
import com.ruoyi.ss.storeApply.service.StoreApplyConverter;
import com.ruoyi.ss.storeApply.service.StoreApplyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 店铺Service业务层处理
 *
 * @author 邱贞招
 * @date 2024-02-21
 */
@Service
@Slf4j
public class StoreServiceImpl implements StoreService
{
    @Autowired
    private StoreMapper storeMapper;

    @Autowired
    private DeviceService smDeviceService;

    @Autowired
    private StoreAssembler storeAssembler;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private StoreApplyService storeApplyService;

    @Autowired
    private StoreApplyConverter storeApplyConverter;

    @Autowired
    private StoreValidator storeValidator;

    /**
     * 查询店铺
     *
     * @param storeId 店铺主键
     * @return 店铺
     */
    @Override
    public StoreVo selectSmStoreById(Long storeId)
    {
        return storeMapper.selectSmStoreById(storeId);
    }

    /**
     * 查询店铺列表
     *
     * @param store 店铺
     * @return 店铺
     */
    @Override
    public List<StoreVo> selectSmStoreList(StoreQuery store)
    {
        return storeMapper.selectSmStoreList(store);
    }

    /**
     * 新增店铺
     *
     * @param store 店铺
     * @return 结果
     */
    @Override
    public int insertSmStore(Store store)
    {
        store.setCreateTime(DateUtils.getNowDate());
        store.setCreateBy(SecurityUtils.getUsername());

        Integer result = transactionTemplate.execute(status -> {
            // 新增店铺
            int i = storeMapper.insertSmStore(store);
            ServiceUtil.assertion(i != 1, "新增店铺失败");

            // 后校验
            StoreVo vo = this.selectSmStoreById(store.getStoreId());
            storeValidator.afterCheck(vo);

            // 如果没有默认店铺，则将其设为默认店铺
            if (this.selectDefaultStore(store.getUserId()) == null) {
                this.setDefault(store.getUserId(), store.getStoreId());
            }

            return i;
        });
        return result == null ? 0 : result;
    }
    /**
     * 修改店铺
     *
     * @param store 店铺
     * @return 结果
     */
    @Override
    public int updateSmStore(Store store)
    {
        store.setUpdateTime(DateUtils.getNowDate());
        store.setUpdateBy(SecurityUtils.getUsername());

        Integer result = transactionTemplate.execute(status -> {
            // 更新
            int update = storeMapper.updateSmStore(store);
            ServiceUtil.assertion(update != 1, "修改店铺失败，请刷新后重试");

            // 后校验
            StoreVo vo = this.selectSmStoreById(store.getStoreId());
            storeValidator.afterCheck(vo);

            return update;
        });

        return result == null ? 0 : result;
    }

    @Override
    @Transactional
    public boolean changeSort(List<Store> list) {
        if (list == null) {
            return true;
        }
        List<Store> updateList = new ArrayList<>();
        for (Store item : list) {
            Store store = new Store();
            store.setStoreId(item.getStoreId());
            store.setGroupSort(item.getGroupSort());
            updateList.add(store);
        }
        storeMapper.batchUpdate(updateList);
        return true;
    }

    @Override
    public List<StoreVo> listCount(StoreQuery query) {
        List<StoreVo> list = new ArrayList<>();

        // 查询各各店铺的设备数据
        List<StoreVo> storeList = storeMapper.selectSmStoreList(query);
        storeAssembler.assembleDeviceCount(storeList);

        // 查询全部设备数据
        DeviceQuery deviceDto = new DeviceQuery();
        deviceDto.setUserId(query.getUserId());
        int count = smDeviceService.selectCount(deviceDto);
        StoreVo all = new StoreVo();
        all.setDeviceCount(count);
        all.setName("全部");

        list.add(all);
        list.addAll(storeList);

        return list;
    }

    @Override
    public StoreVo selectDefaultStore(Long userId) {
        if (userId == null) {
            return null;
        }
        StoreQuery dto = new StoreQuery();
        dto.setIsDefault(true);
        dto.setUserId(userId);
        List<StoreVo> list = selectSmStoreList(dto);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }


    /**
     * ids逻辑删除
     *
     * @param ids id列表
     */
    @Override
    public int logicDel(List<Long> ids) {
        if (CollectionUtils.isEmptyElement(ids)) {
            log.warn("ids is empty");
            return 0;
        }
        Integer result = transactionTemplate.execute(status -> {
            // 若删除的包含默认店铺则将默认店铺设置为第一个店铺
            StoreQuery query = new StoreQuery();
            query.setStoreIds(ids);
            query.setIsDefault(true);
            List<StoreVo> defaultList = selectSmStoreList(query);
            if (!CollectionUtils.isEmptyElement(defaultList)) {
                // 包含默认店铺，则查询第一个店铺
                query = new StoreQuery();
                query.setUserId(defaultList.get(0).getUserId());
                StoreVo other = storeMapper.selectOne(query);
                if (other != null) {
                    // 其他店铺不为空，则设置为第一个店铺
                    this.setDefault(other.getUserId(), other.getStoreId());
                }
            }

            // 执行逻辑删除
            return storeMapper.logicDel(ids);
        });
        return result == null ? 0 : result;
    }

    /**
     * 查询附近的店铺
     *
     * @param query
     * @return
     */
    @Override
    public List<StoreVo> listNearBy(StoreQuery query) {
        if (query == null) {
            return Collections.emptyList();
        }
        if (CollectionUtils.isEmpty(query.getCenter())) {
            return Collections.emptyList();
        }
        return this.selectSmStoreList(query);
    }

    /**
     * ids查询查询列表
     *
     * @param storeIds
     * @return
     */
    @Override
    public List<StoreVo> selectStoreByIds(List<Long> storeIds) {
        if (CollectionUtils.isEmpty(storeIds)) {
            return Collections.emptyList();
        }
        return storeMapper.selectSmStoreByIds(storeIds);
    }

    /**
     * 查询数量
     *
     * @param query 查询条件
     */
    @Override
    public int selectCount(StoreQuery query) {
        return storeMapper.selectCount(query);
    }

    /**
     * 查询用户ID列表
     *
     * @param userIds
     * @return
     */
    @Override
    public Map<Long, Integer> selectCountMapByUserIds(List<Long> userIds) {
        StoreQuery query = new StoreQuery();
        query.setUserIds(userIds);
        query.setGroupBy(StoreGroupBy.user_id.name());
        return this.selectCountMap(query, StoreCountVO::getUserId);
    }

    /**
     * 设为默认店铺
     *
     * @param userId
     * @param storeId
     * @return
     */
    @Override
    public boolean setDefault(Long userId, Long storeId) {
        storeMapper.setDefault(userId, storeId);
        return true;
    }

    /**
     * 查询店铺映射表
     *
     * @param query
     * @param keyMapper
     */
    @Override
    public <K> Map<K, StoreVo> selectMap(StoreQuery query, Function<? super StoreVo, ? extends K> keyMapper) {
        List<StoreVo> list = this.selectSmStoreList(query);
        if (CollectionUtils.isEmptyElement(list)) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(keyMapper, item -> item));
    }

    /**
     * ids查询列表
     *
     * @param ids
     * @param userId
     */
    @Override
    public List<StoreVo> selectSmStoreListByIds(List<Long> ids, Long userId) {
        if (CollectionUtils.isEmptyElement(ids)) {
            return Collections.emptyList();
        }
        StoreQuery query = new StoreQuery();
        query.setStoreIds(ids);
        query.setUserId(userId);
        return selectSmStoreList(query);
    }

    @Override
    public List<StoreVo> selectByUserId(Long userId) {
        if (userId == null) {
            return Collections.emptyList();
        }
        StoreQuery query = new StoreQuery();
        query.setUserId(userId);
        return storeMapper.selectSmStoreList(query);
    }

    @Override
    public int insertAndApply(StoreBO store) {
        store.setStatus(StoreStatus.APPROVING.getStatus());
        store.setEnabled(false);

        Integer result = transactionTemplate.execute(status -> {
            int insert = this.insertSmStore(store);
            ServiceUtil.assertion(insert != 1, "新增店铺失败");

            int insertApply = storeApplyService.insertStoreApply(storeApplyConverter.toPo(store, SecurityUtils.getUserId(), StoreApplyType.ADD));
            ServiceUtil.assertion(insertApply != 1, "提交审核失败");
            return insertApply;
        });

        return result == null ? 0 : result;
    }

    @Override
    public int updateApply(StoreBO data) {
        Integer result = transactionTemplate.execute(status -> {
            // 修改店铺状态为审核中
            Store updateData = new Store();
            updateData.setStatus(StoreStatus.APPROVING.getStatus());
            StoreQuery updateQuery = new StoreQuery();
            updateQuery.setStoreId(data.getStoreId());
            updateQuery.setStatus(StoreStatus.NORMAL.getStatus());
            int update = this.updateByQuery(updateData, updateQuery);
            ServiceUtil.assertion(update != 1, "店铺状态已发生变化，请刷新后重试");

            // 新增申请
            int insert = storeApplyService.insertStoreApply(storeApplyConverter.toPo(data, SecurityUtils.getUserId(), StoreApplyType.UPDATE));
            ServiceUtil.assertion(insert != 1, "创建申请失败");

            return insert;
        });

        return result == null ? 0 : result;
    }

    @Override
    public int updateByQuery(Store data, StoreQuery query) {
        if (query == null) {
            return 0;
        }
        return storeMapper.updateByQuery(data, query);
    }

    @Override
    public List<StoreVo> selectStaffStoreList(StoreQuery query) {
        query.setInStaff(true);
        return this.selectSmStoreList(query);
    }

    @Override
    public StoreVo selectStaffStoreOne(StoreQuery query) {
        PageHelper.startPage(1, 1);
        List<StoreVo> list = this.selectStaffStoreList(query);
        return CollectionUtils.getFirst(list);
    }

    /**
     * 通用查询数量
     *
     * @param query
     * @param keyMapper
     * @return
     */
    private <K> Map<K, Integer> selectCountMap(StoreQuery query, Function<? super StoreCountVO, ? extends K > keyMapper) {
        List<StoreCountVO> list = storeMapper.selectCommonCount(query);
        if (CollectionUtils.isEmptyElement(list)) {
            return Collections.emptyMap();
        }
        return list.stream().collect(Collectors.toMap(keyMapper, StoreCountVO::getCount));
    }

}
