package com.usky.vpp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.vpp.domain.VppDevice;
import com.usky.vpp.domain.VppResourcePoint;
import com.usky.vpp.mapper.VppDeviceMapper;
import com.usky.vpp.mapper.VppResourcePointMapper;
import com.usky.vpp.service.VppResourcePointService;
import com.usky.vpp.service.VppSiteService;
import com.usky.vpp.domain.VppSite;
import com.usky.vpp.mapper.VppSiteMapper;
import com.usky.vpp.service.vo.ResourcePointListVO;
import com.usky.vpp.service.vo.ResourcePointRequest;
import com.usky.vpp.util.VppAuditHelper;
import com.usky.vpp.util.VppPageHelper;
import com.usky.vpp.util.VppResourceTypeHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;

@Service
public class VppResourcePointServiceImpl implements VppResourcePointService {

    @Autowired
    private VppResourcePointMapper resourcePointMapper;
    @Autowired
    private VppSiteService siteService;
    @Autowired
    private VppDeviceMapper deviceMapper;
    @Autowired
    private VppSiteMapper siteMapper;

    @Override
    public CommonPage<VppResourcePoint> pageResourcePoint(Map<String, Object> params) {
        Page<VppResourcePoint> page = VppPageHelper.of(params);
        return toCommonPage(resourcePointMapper.selectPage(page, buildQueryWrapper(params)));
    }

    @Override
    public CommonPage<ResourcePointListVO> pageResourcePointList(Map<String, Object> params) {
        Page<VppResourcePoint> page = VppPageHelper.of(params);
        LambdaQueryWrapper<VppResourcePoint> wrapper = buildQueryWrapper(params);
        applyNameFilters(wrapper, params);
        Page<VppResourcePoint> result = resourcePointMapper.selectPage(page, wrapper);
        return toListVoPage(result);
    }

    @Override
    public CommonPage<VppResourcePoint> listBySiteId(Long siteId, Map<String, Object> params) {
        siteService.getSite(siteId);
        Page<VppResourcePoint> page = VppPageHelper.of(params);
        LambdaQueryWrapper<VppResourcePoint> wrapper = buildQueryWrapper(params)
                .eq(VppResourcePoint::getSiteId, siteId);
        return toCommonPage(resourcePointMapper.selectPage(page, wrapper));
    }

    @Override
    public VppResourcePoint getResourcePoint(Long id) {
        VppResourcePoint resource = resourcePointMapper.selectById(id);
        if (resource == null || VppAuditHelper.isDeleted(resource.getDeleteFlag())) {
            throw new BusinessException("资源点不存在");
        }
        return resource;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public VppResourcePoint createResourcePoint(Long siteId, ResourcePointRequest request) {
        siteService.getSite(siteId);
        validateRequest(request, null);
        ensureDeviceBelongsToSite(request.getDeviceId(), siteId);
        VppResourcePoint resource = new VppResourcePoint();
        resource.setSiteId(siteId);
        applyRequest(resource, request);
        VppAuditHelper.fillCreate(resource);
        resourcePointMapper.insert(resource);
        return resource;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateResourcePoint(Long id, ResourcePointRequest request) {
        VppResourcePoint existing = getResourcePoint(id);
        validateRequest(request, id);
        ensureDeviceBelongsToSite(request.getDeviceId(), existing.getSiteId());
        applyRequest(existing, request);
        VppAuditHelper.fillUpdate(existing);
        resourcePointMapper.updateById(existing);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteResourcePoint(Long id) {
        VppResourcePoint resource = getResourcePoint(id);
        VppAuditHelper.fillSoftDelete(resource);
        resourcePointMapper.updateById(resource);
    }

    private LambdaQueryWrapper<VppResourcePoint> buildQueryWrapper(Map<String, Object> params) {
        LambdaQueryWrapper<VppResourcePoint> wrapper = new LambdaQueryWrapper<VppResourcePoint>()
                .eq(VppResourcePoint::getDeleteFlag, VppAuditHelper.NOT_DELETED)
                .orderByDesc(VppResourcePoint::getCreateTime);
        if (params == null) {
            return wrapper;
        }
        if (params.get("siteId") != null) {
            wrapper.eq(VppResourcePoint::getSiteId, Long.parseLong(params.get("siteId").toString()));
        }
        if (params.get("resourceType") != null) {
            wrapper.eq(VppResourcePoint::getResourceType, params.get("resourceType").toString());
        }
        if (params.get("resourceName") != null) {
            wrapper.like(VppResourcePoint::getResourceName, params.get("resourceName").toString());
        }
        if (params.get("isControl") != null) {
            wrapper.eq(VppResourcePoint::getIsControl, Integer.parseInt(params.get("isControl").toString()));
        }
        return wrapper;
    }

    private void applyNameFilters(LambdaQueryWrapper<VppResourcePoint> wrapper, Map<String, Object> params) {
        if (params == null) {
            return;
        }
        if (params.get("siteName") != null && StringUtils.hasText(params.get("siteName").toString())) {
            List<VppSite> sites = siteMapper.selectList(new LambdaQueryWrapper<VppSite>()
                    .like(VppSite::getSiteName, params.get("siteName").toString())
                    .eq(VppSite::getDeleteFlag, VppAuditHelper.NOT_DELETED));
            if (sites.isEmpty()) {
                wrapper.eq(VppResourcePoint::getId, -1L);
                return;
            }
            wrapper.in(VppResourcePoint::getSiteId,
                    sites.stream().map(VppSite::getId).collect(java.util.stream.Collectors.toList()));
        }
        if (params.get("deviceName") != null && StringUtils.hasText(params.get("deviceName").toString())) {
            List<VppDevice> devices = deviceMapper.selectList(new LambdaQueryWrapper<VppDevice>()
                    .like(VppDevice::getDeviceName, params.get("deviceName").toString())
                    .eq(VppDevice::getDeleteFlag, VppAuditHelper.NOT_DELETED));
            if (devices.isEmpty()) {
                wrapper.eq(VppResourcePoint::getId, -1L);
                return;
            }
            wrapper.in(VppResourcePoint::getDeviceId,
                    devices.stream().map(VppDevice::getId).collect(java.util.stream.Collectors.toList()));
        }
    }

    private CommonPage<ResourcePointListVO> toListVoPage(Page<VppResourcePoint> page) {
        List<VppResourcePoint> records = page.getRecords();
        if (records.isEmpty()) {
            return new CommonPage<>(java.util.Collections.emptyList(), page.getTotal(), page.getCurrent(), page.getSize());
        }
        java.util.Set<Long> siteIds = records.stream().map(VppResourcePoint::getSiteId)
                .filter(java.util.Objects::nonNull).collect(java.util.stream.Collectors.toSet());
        java.util.Set<Long> deviceIds = records.stream().map(VppResourcePoint::getDeviceId)
                .filter(java.util.Objects::nonNull).collect(java.util.stream.Collectors.toSet());
        java.util.Map<Long, VppSite> siteMap = siteIds.isEmpty() ? java.util.Collections.emptyMap()
                : siteMapper.selectBatchIds(siteIds).stream()
                .collect(java.util.stream.Collectors.toMap(VppSite::getId, s -> s, (a, b) -> a));
        java.util.Map<Long, VppDevice> deviceMap = deviceIds.isEmpty() ? java.util.Collections.emptyMap()
                : deviceMapper.selectBatchIds(deviceIds).stream()
                .collect(java.util.stream.Collectors.toMap(VppDevice::getId, d -> d, (a, b) -> a));

        List<ResourcePointListVO> voList = new java.util.ArrayList<>();
        for (VppResourcePoint resource : records) {
            ResourcePointListVO vo = new ResourcePointListVO();
            vo.setId(resource.getId());
            vo.setResourceCode(resource.getResourceCode());
            vo.setResourceName(resource.getResourceName());
            vo.setSiteId(resource.getSiteId());
            vo.setDeviceId(resource.getDeviceId());
            vo.setResourceType(resource.getResourceType());
            vo.setResourceTypeLabel(VppResourceTypeHelper.resourceTypeLabel(resource.getResourceType()));
            vo.setCapacityKw(resource.getCapacityKw());
            vo.setIsControl(resource.getIsControl());
            vo.setIsSupportPeak(resource.getIsSupportPeak());
            vo.setIsSupportFm(resource.getIsSupportFm());
            vo.setResponseMin(resource.getResponseMin());
            vo.setMaxUpKw(resource.getMaxUpKw());
            vo.setMinDownKw(resource.getMinDownKw());
            vo.setRemark(resource.getRemark());
            vo.setCreateTime(resource.getCreateTime());
            VppSite site = siteMap.get(resource.getSiteId());
            if (site != null) {
                vo.setSiteName(site.getSiteName());
            }
            VppDevice device = deviceMap.get(resource.getDeviceId());
            if (device != null) {
                vo.setDeviceName(device.getDeviceName());
            }
            voList.add(vo);
        }
        return new CommonPage<>(voList, page.getTotal(), page.getCurrent(), page.getSize());
    }

    private void ensureDeviceBelongsToSite(Long deviceId, Long siteId) {
        VppDevice device = deviceMapper.selectById(deviceId);
        if (device == null || VppAuditHelper.isDeleted(device.getDeleteFlag())) {
            throw new BusinessException("设备不存在");
        }
        if (!siteId.equals(device.getSiteId())) {
            throw new BusinessException("设备不属于当前站点");
        }
    }

    private void validateRequest(ResourcePointRequest request, Long excludeId) {
        if (request == null || !StringUtils.hasText(request.getResourceCode())) {
            throw new BusinessException("资源编号不能为空");
        }
        if (!StringUtils.hasText(request.getResourceName())) {
            throw new BusinessException("资源名称不能为空");
        }
        if (request.getDeviceId() == null) {
            throw new BusinessException("关联设备不能为空");
        }
        if (!StringUtils.hasText(request.getResourceType())) {
            throw new BusinessException("资源类型不能为空");
        }
        if (request.getCapacityKw() == null) {
            throw new BusinessException("装机容量不能为空");
        }
        LambdaQueryWrapper<VppResourcePoint> wrapper = new LambdaQueryWrapper<VppResourcePoint>()
                .eq(VppResourcePoint::getResourceCode, request.getResourceCode())
                .eq(VppResourcePoint::getDeleteFlag, VppAuditHelper.NOT_DELETED);
        if (excludeId != null) {
            wrapper.ne(VppResourcePoint::getId, excludeId);
        }
        if (resourcePointMapper.selectCount(wrapper) > 0) {
            throw new BusinessException("资源编号已存在");
        }
    }

    private void applyRequest(VppResourcePoint resource, ResourcePointRequest request) {
        resource.setResourceCode(request.getResourceCode());
        resource.setResourceName(request.getResourceName());
        resource.setDeviceId(request.getDeviceId());
        resource.setResourceType(request.getResourceType());
        resource.setCapacityKw(request.getCapacityKw());
        resource.setIsControl(request.getIsControl() == null ? 0 : request.getIsControl());
        resource.setIsSupportPeak(request.getIsSupportPeak() == null ? 0 : request.getIsSupportPeak());
        resource.setIsSupportFm(request.getIsSupportFm() == null ? 0 : request.getIsSupportFm());
        resource.setResponseMin(request.getResponseMin());
        resource.setMaxUpKw(request.getMaxUpKw());
        resource.setMinDownKw(request.getMinDownKw());
        resource.setRemark(request.getRemark());
    }

    private CommonPage<VppResourcePoint> toCommonPage(Page<VppResourcePoint> page) {
        return new CommonPage<>(page.getRecords(), page.getTotal(), page.getCurrent(), page.getSize());
    }
}
