package com.ningdatech.kqapi.admin.manage;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ningdatech.basic.model.IdVo;
import com.ningdatech.basic.model.PageVo;
import com.ningdatech.basic.util.CollUtils;
import com.ningdatech.kqapi.admin.mapper.ZoneMapper;
import com.ningdatech.kqapi.admin.model.entity.Window;
import com.ningdatech.kqapi.admin.model.entity.Zone;
import com.ningdatech.kqapi.admin.model.req.ListZoneReq;
import com.ningdatech.kqapi.admin.model.req.ZoneSaveReq;
import com.ningdatech.kqapi.admin.model.vo.ZoneDetailVO;
import com.ningdatech.kqapi.admin.service.IWindowService;
import com.ningdatech.kqapi.admin.service.IZoneService;
import com.ningdatech.kqapi.common.constant.BizConst;
import com.ningdatech.kqapi.common.exception.BizException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 * ZoneManage
 * </p>
 *
 * @author WendyYang
 * @since 12:17 2024/4/20
 */
@Component
@RequiredArgsConstructor
public class ZoneManage {

    private final IZoneService zoneService;
    private final IWindowService windowService;

    @Transactional(rollbackFor = Exception.class)
    public synchronized void zoneSaveOrUpdate(ZoneSaveReq req) {
        Zone zone = BeanUtil.copyProperties(req, Zone.class);
        Wrapper<Zone> nameCheck = Wrappers.lambdaQuery(Zone.class)
                .eq(Zone::getZoneName, req.getZoneName())
                .ne(req.getId() != null, Zone::getId, req.getId())
                .last(BizConst.LIMIT_1);
        if (zoneService.count(nameCheck) > 0) {
            throw BizException.wrap("您新增的【%s】专区已存在，无须重复添加", req.getZoneName());
        }
        if (zone.getId() != null) {
            Zone oldZone = zoneService.getById(req.getId());
            if (!StrUtil.equals(zone.getZoneName(), oldZone.getZoneName())) {
                Wrapper<Window> wUpdate = Wrappers.lambdaUpdate(Window.class)
                        .set(Window::getZoneName, req.getZoneName())
                        .eq(Window::getZoneId, req.getId());
                windowService.update(wUpdate);
            }
        }
        zoneService.saveOrUpdate(zone);
    }


    public void delete(IdVo<Integer> id) {
        zoneService.removeById(id.getId());
    }

    public PageVo<ZoneDetailVO> pageZone(ListZoneReq req) {
        Wrapper<Zone> query = buildZoneQuery(req);
        Page<Zone> page = zoneService.page(req.page(), query);
        if (page.getTotal() == 0) {
            return PageVo.empty();
        }
        List<Zone> records = page.getRecords();
        List<Integer> zoneIds = CollUtils.fieldList(records, Zone::getId);
        Map<Integer, Integer> windowCountMap = windowService.windowCountByZoneIds(zoneIds);
        List<ZoneDetailVO> data = records.stream().map(w -> {
            ZoneDetailVO zone = BeanUtil.copyProperties(w, ZoneDetailVO.class);
            zone.setWindowCount(windowCountMap.getOrDefault(w.getId(), 0));
            return zone;
        }).collect(Collectors.toList());
        return PageVo.of(data, page.getTotal());
    }

    public List<ZoneDetailVO> zoneOption(ListZoneReq req) {
        Wrapper<Zone> query = buildZoneQuery(req);
        Page<Zone> page = zoneService.page(req.page(), query);
        if (page.getTotal() == 0) {
            return Collections.emptyList();
        }
        return CollUtils.convert(page.getRecords(),
                w -> ZoneDetailVO.builder()
                        .id(w.getId())
                        .specialFeature(w.getSpecialFeature())
                        .zoneName(w.getZoneName())
                        .build());
    }

    private static Wrapper<Zone> buildZoneQuery(ListZoneReq req) {
        return Wrappers.lambdaQuery(Zone.class)
                .like(StrUtil.isNotBlank(req.getZoneName()), Zone::getZoneName, req.getZoneName())
                .orderByDesc(Zone::getUpdateOn);
    }

}
