package org.dromara.art.service.impl;

import org.dromara.art.domain.ArtSchoolCollege;
import org.dromara.art.domain.ArtSchoolMajorTag;
import org.dromara.art.mapper.ArtSchoolCollegeMapper;
import org.dromara.art.mapper.ArtSchoolMajorTagMapper;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.dromara.art.domain.bo.ArtSchoolMajorBo;
import org.dromara.art.domain.vo.ArtSchoolMajorVo;
import org.dromara.art.domain.ArtSchoolMajor;
import org.dromara.art.mapper.ArtSchoolMajorMapper;
import org.dromara.art.service.IArtSchoolMajorService;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 学校专业Service业务层处理
 *
 * @author ZhouWenTao
 * @date 2026-02-17
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ArtSchoolMajorServiceImpl implements IArtSchoolMajorService {

    private final ArtSchoolMajorMapper baseMapper;
    private final ArtSchoolCollegeMapper artSchoolCollegeMapper;
    private final ArtSchoolMajorTagMapper artSchoolMajorTagMapper;

    /**
     * 查询学校专业
     *
     * @param majorId 主键
     * @return 学校专业
     */
    @Override
    public ArtSchoolMajorVo queryById(Long majorId){
        ArtSchoolMajorVo vo = baseMapper.selectVoById(majorId);
        fillCampusName(vo);
        fillMajorTags(vo);
        return vo;
    }

    /**
     * 分页查询学校专业列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 学校专业分页列表
     */
    @Override
    public TableDataInfo<ArtSchoolMajorVo> queryPageList(ArtSchoolMajorBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<ArtSchoolMajor> lqw = buildQueryWrapper(bo);
        Page<ArtSchoolMajorVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        fillCampusName(result.getRecords());
        fillMajorTags(result.getRecords());
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的学校专业列表
     *
     * @param bo 查询条件
     * @return 学校专业列表
     */
    @Override
    public List<ArtSchoolMajorVo> queryList(ArtSchoolMajorBo bo) {
        LambdaQueryWrapper<ArtSchoolMajor> lqw = buildQueryWrapper(bo);
        List<ArtSchoolMajorVo> list = baseMapper.selectVoList(lqw);
        fillCampusName(list);
        fillMajorTags(list);
        return list;
    }

    private LambdaQueryWrapper<ArtSchoolMajor> buildQueryWrapper(ArtSchoolMajorBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ArtSchoolMajor> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(ArtSchoolMajor::getSchoolMajorId);
        lqw.eq(bo.getSchoolId() != null, ArtSchoolMajor::getSchoolId, bo.getSchoolId());
        lqw.eq(bo.getCollegeId() != null, ArtSchoolMajor::getCollegeId, bo.getCollegeId());
        lqw.eq(StringUtils.isNotBlank(bo.getMajorCode()), ArtSchoolMajor::getMajorCode, bo.getMajorCode());
        lqw.like(StringUtils.isNotBlank(bo.getMajorName()), ArtSchoolMajor::getMajorName, bo.getMajorName());
        lqw.eq(StringUtils.isNotBlank(bo.getEducationLevel()), ArtSchoolMajor::getEducationLevel, bo.getEducationLevel());
        lqw.eq(bo.getDurationYears() != null, ArtSchoolMajor::getDurationYears, bo.getDurationYears());
        lqw.eq(StringUtils.isNotBlank(bo.getMajorCategory()), ArtSchoolMajor::getMajorCategory, bo.getMajorCategory());
        lqw.eq(StringUtils.isNotBlank(bo.getDegreeType()), ArtSchoolMajor::getDegreeType, bo.getDegreeType());
        lqw.eq(StringUtils.isNotBlank(bo.getIntroduction()), ArtSchoolMajor::getIntroduction, bo.getIntroduction());
        return lqw;
    }

    private void fillCampusName(ArtSchoolMajorVo vo) {
        if (vo == null || vo.getCollegeId() == null) {
            return;
        }
        ArtSchoolCollege college = artSchoolCollegeMapper.selectById(vo.getCollegeId());
        if (college != null) {
            vo.setCollegeName(college.getCollegeName());
        }
    }

    private void fillCampusName(List<ArtSchoolMajorVo> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        Set<Long> collegeIds = list.stream()
            .map(ArtSchoolMajorVo::getCollegeId)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
        if (CollUtil.isEmpty(collegeIds)) {
            return;
        }
        LambdaQueryWrapper<ArtSchoolCollege> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.select(ArtSchoolCollege::getCollegeId, ArtSchoolCollege::getCollegeName);
        queryWrapper.in(ArtSchoolCollege::getCollegeId, collegeIds);
        Map<Long, String> campusNameMap = artSchoolCollegeMapper.selectList(queryWrapper).stream()
            .collect(Collectors.toMap(ArtSchoolCollege::getCollegeId, ArtSchoolCollege::getCollegeName, (v1, v2) -> v1, HashMap::new));
        list.forEach(item -> item.setCollegeName(campusNameMap.get(item.getCollegeId())));
    }

    /**
     * 新增学校专业
     *
     * @param bo 学校专业
     * @return 是否新增成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(ArtSchoolMajorBo bo) {
        ArtSchoolMajor add = MapstructUtils.convert(bo, ArtSchoolMajor.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (!flag) {
            return false;
        }
        Long schoolMajorId = Objects.requireNonNull(add).getSchoolMajorId();
        bo.setSchoolMajorId(schoolMajorId);
        boolean majorTagFlag = saveOrUpdateMajorTagsByMajorId(schoolMajorId, bo.getMajorTags());
        if (!majorTagFlag) {
            throw new ServiceException("专业标签保存失败");
        }
        return flag;
    }

    /**
     * 修改学校专业
     *
     * @param bo 学校专业
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(ArtSchoolMajorBo bo) {
        ArtSchoolMajor update = MapstructUtils.convert(bo, ArtSchoolMajor.class);
        validEntityBeforeSave(update);
        boolean flag = baseMapper.updateById(update) > 0;
        if (!flag) {
            return false;
        }
        boolean majorTagFlag = saveOrUpdateMajorTagsByMajorId(bo.getSchoolMajorId(), bo.getMajorTags());
        if (!majorTagFlag) {
            throw new ServiceException("专业标签更新失败");
        }
        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ArtSchoolMajor entity){
        //TODO 做一些数据校验,如唯一约束
    }

    private boolean saveOrUpdateMajorTagsByMajorId(Long majorId, List<String> majorTags) {
        if (majorTags == null) {
            return true;
        }
        artSchoolMajorTagMapper.deletePhyByMajorId(majorId);
        if (CollUtil.isEmpty(majorTags)) {
            return true;
        }
        Set<String> uniqueTags = new LinkedHashSet<>();
        for (String tag : majorTags) {
            String tagName = trimToEmpty(tag);
            if (StringUtils.isBlank(tagName)) {
                throw new ServiceException("专业标签不能为空");
            }
            if (!uniqueTags.add(tagName)) {
                continue;
            }
            ArtSchoolMajorTag majorTag = new ArtSchoolMajorTag();
            majorTag.setMajorId(majorId);
            majorTag.setTagName(tagName);
            boolean insertFlag = artSchoolMajorTagMapper.insert(majorTag) > 0;
            if (!insertFlag) {
                return false;
            }
        }
        return true;
    }

    private void fillMajorTags(ArtSchoolMajorVo vo) {
        if (vo == null) {
            return;
        }
        fillMajorTags(Collections.singletonList(vo));
    }

    private void fillMajorTags(List<ArtSchoolMajorVo> list) {
        if (CollUtil.isEmpty(list)) {
            return;
        }
        Set<Long> majorIds = list.stream()
            .map(ArtSchoolMajorVo::getSchoolMajorId)
            .filter(Objects::nonNull)
            .collect(Collectors.toSet());
        if (CollUtil.isEmpty(majorIds)) {
            return;
        }
        List<ArtSchoolMajorTag> majorTagList = artSchoolMajorTagMapper.selectList(
            Wrappers.<ArtSchoolMajorTag>lambdaQuery()
                .in(ArtSchoolMajorTag::getMajorId, majorIds)
                .orderByAsc(ArtSchoolMajorTag::getMajorTagId));
        Map<Long, List<String>> majorTagMap = majorTagList.stream()
            .collect(Collectors.groupingBy(ArtSchoolMajorTag::getMajorId,
                LinkedHashMap::new,
                Collectors.mapping(ArtSchoolMajorTag::getTagName, Collectors.toList())));
        list.forEach(item -> item.setMajorTags(majorTagMap.getOrDefault(item.getSchoolMajorId(), Collections.emptyList())));
    }

    private String trimToEmpty(String value) {
        return StringUtils.isBlank(value) ? "" : value.trim();
    }

    /**
     * 校验并批量删除学校专业信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public boolean saveOrUpdateByCollegeId(ArtSchoolMajor schoolMajor) {
        if (schoolMajor.getCollegeId() != null) {
            boolean updated = baseMapper.updateById(schoolMajor) > 0;
            if (updated) {
                return true;
            }
        }
        LambdaQueryWrapper<ArtSchoolMajor> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(ArtSchoolMajor::getSchoolId, schoolMajor.getSchoolId());
        queryWrapper.eq(ArtSchoolMajor::getCollegeId, schoolMajor.getCollegeId());
        queryWrapper.eq(ArtSchoolMajor::getMajorName, schoolMajor.getMajorName());
        ArtSchoolMajor exist = baseMapper.selectOne(queryWrapper, false);
        if (exist == null) {
            return baseMapper.insert(schoolMajor) > 0;
        }
        schoolMajor.setSchoolMajorId(exist.getSchoolMajorId());
        return baseMapper.updateById(schoolMajor) > 0;
    }
}
