package com.yonge.cooleshow.biz.dal.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dayaedu.cbs.openfeign.client.MusicFeignClientService;
import com.dayaedu.cbs.openfeign.wrapper.musicInstrument.CbsMusicalInstrumentWrapper;
import com.microsvc.toolkit.common.webportal.exception.BizException;
import com.yonge.cooleshow.biz.dal.dao.InstrumentDao;
import com.yonge.cooleshow.biz.dal.entity.Instrument;
import com.yonge.cooleshow.biz.dal.entity.Subject;
import com.yonge.cooleshow.biz.dal.service.InstrumentService;
import com.yonge.cooleshow.biz.dal.service.SubjectService;
import com.yonge.cooleshow.biz.dal.wrapper.InstrumentWrapper;
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.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 乐器设置
 * 2024-04-22 16:55:18
 */
@Slf4j
@Service
public class InstrumentServiceImpl extends ServiceImpl<InstrumentDao, Instrument> implements InstrumentService {

    @Resource
    private MusicFeignClientService musicFeignClientService;
    @Resource
    private SubjectService subjectService;

    /**
     * 查询详情
     *
     * @param id 详情ID
     * @return Instrument
     */
    @Override
    public Instrument detail(Long id) {

        return baseMapper.selectById(id);
    }

    /**
     * 分页查询
     *
     * @param page  IPage<Instrument>
     * @param query InstrumentWrapper.InstrumentQuery
     * @return IPage<Instrument>
     */
    @Override
    public IPage<InstrumentWrapper.Instrument> selectPage(IPage<InstrumentWrapper.Instrument> page, InstrumentWrapper.InstrumentQuery query) {

        IPage<InstrumentWrapper.Instrument> instrumentIPage = page.setRecords(baseMapper.selectPage(page, query));
        List<InstrumentWrapper.Instrument> records = instrumentIPage.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return instrumentIPage;
        }
        List<InstrumentWrapper.Instrument> instruments = getInstruments(records.stream().map(InstrumentWrapper.Instrument::getId).distinct().collect(Collectors.toList()));
        return instrumentIPage.setRecords(instruments);
    }

    /**
     * 添加
     *
     * @param instrument InstrumentWrapper.Instrument
     * @return Boolean
     */
    @Override
    public Boolean add(InstrumentWrapper.Instrument instrument) {

        return this.save(JSON.parseObject(instrument.jsonString(), Instrument.class));
    }

    /**
     * 更新
     *
     * @param instrument InstrumentWrapper.Instrument
     * @return Boolean
     */
    @Override
    public Boolean update(InstrumentWrapper.Instrument instrument) {

        return this.updateById(JSON.parseObject(instrument.jsonString(), Instrument.class));
    }

    @Override
    public List<Instrument> queryBySubjectId(Long subject) {
        if (subject == null) {
            return new ArrayList<>();
        }
        return this.lambdaQuery()
            .eq(Instrument::getSubjectId, subject)
            .list();
    }

    @Override
    public Map<Long, InstrumentWrapper.Instrument> getMapByIds(List<Long> instrumentIdList) {
        if (CollectionUtils.isEmpty(instrumentIdList)) {
            return new HashMap<>();
        }
        instrumentIdList = instrumentIdList.stream().distinct().collect(Collectors.toList());
        List<InstrumentWrapper.Instrument> instrumentList = getInstruments(instrumentIdList);
        return instrumentList.stream().collect(Collectors.toMap(InstrumentWrapper.Instrument::getId, Function.identity()));
    }

    private List<InstrumentWrapper.Instrument> getInstruments(List<Long> instrumentIdList) {
        instrumentIdList = instrumentIdList.stream().filter(Objects::nonNull).collect(Collectors.toList());
        Map<Long, Instrument> idImstrumentMap = this.lambdaQuery().in(Instrument::getId, instrumentIdList).list()
            .stream().collect(Collectors.toMap(Instrument::getId, Function.identity()));
        // 去内容平台查询乐器名称
        CbsMusicalInstrumentWrapper.MusicalInstrumentQuery build = CbsMusicalInstrumentWrapper.MusicalInstrumentQuery.builder()
            .rows(-1)
            .ids(instrumentIdList.stream().map(Long::intValue).distinct().collect(Collectors.toList()))
            .build();
        List<CbsMusicalInstrumentWrapper.MusicalInstrumentQueryDto> rows;
        try {
            rows = musicFeignClientService
                .musicalInstrumentPage(build).feignData().getRows();
        } catch (Exception e) {
            throw new BizException("内容平台服务异常");
        }
        Map<Integer, CbsMusicalInstrumentWrapper.MusicalInstrumentQueryDto> idMap = rows.stream().collect(Collectors.toMap(CbsMusicalInstrumentWrapper.MusicalInstrumentQueryDto::getId,
            Function.identity()));

        List<InstrumentWrapper.Instrument> instrumentList = new ArrayList<>();
        instrumentIdList.forEach(next -> {
            CbsMusicalInstrumentWrapper.MusicalInstrumentQueryDto dto = idMap.get(next.intValue());
            if (dto == null) {
                return;
            }
            InstrumentWrapper.Instrument instrument = JSON.parseObject(JSON.toJSONString(dto), InstrumentWrapper.Instrument.class);
            if (dto.getDefaultScore() != null) {
                instrument.setDefaultScore(dto.getDefaultScore().name());
            }
            instrument.setId(next);

            Instrument instrument1 = idImstrumentMap.getOrDefault(next, new Instrument());
            instrument.setOrientation(instrument1.getOrientation());
            instrument.setEnableFlag(instrument1.getEnableFlag());
            instrument.setOperator(instrument1.getOperator());
            instrument.setSubjectId(instrument1.getSubjectId());
            instrumentList.add(instrument);
        });
        return instrumentList;
    }

    @Override
    public Map<Integer, List<InstrumentWrapper.Instrument>> getGroupBySubjectId(List<Integer> subjectIds, Boolean enableFlag) {
        if (CollectionUtils.isEmpty(subjectIds)) {
            return new HashMap<>();
        }
        List<Instrument> list = this.lambdaQuery()
            .in(Instrument::getSubjectId, subjectIds)
            .eq(enableFlag != null, Instrument::getEnableFlag, enableFlag)
            .list();
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        // group
        Map<Integer, List<Long>> idResult = list.stream()
            .collect(Collectors.groupingBy(o->o.getSubjectId().intValue(), LinkedHashMap::new,Collectors.mapping(Instrument::getId, Collectors.toList())));

        // id 集合
        List<Long> instrumentIds = list.stream().map(Instrument::getId).collect(Collectors.toList());
        Map<Long, InstrumentWrapper.Instrument> instrumentMap = getMapByIds(instrumentIds);
        Map<Integer, List<InstrumentWrapper.Instrument>> result = new HashMap<>();
        idResult.forEach((k,v)->{
            List<InstrumentWrapper.Instrument> instruments = v.stream().map(instrumentMap::get).collect(Collectors.toList());
            result.put(k, instruments);
        });
        return result;

    }

    @Override
    public List<InstrumentWrapper.Instrument> getList(InstrumentWrapper.InstrumentQuery query) {

        IPage<InstrumentWrapper.Instrument> instrumentIPage = this.selectPage(new Page<>(1, -1), query);
        return instrumentIPage.getRecords();
    }

    @Override
    public List<Long> getInstrumentIdsBySubjectId(Long subjectId) {
        List<Instrument> list = this.lambdaQuery()
            .eq(Instrument::getSubjectId, subjectId)
            .list();
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(Instrument::getId).collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void modify(InstrumentWrapper.Update update) {
        Instrument instrument = JSON.parseObject(JSON.toJSONString(update), Instrument.class);

        this.updateById(instrument);

        if (update.getEnableFlag() != null && update.getEnableFlag()) {
            // 启用声部
            Instrument entity = this.getById(update.getId());
            if (entity == null) {
                return;
            }
            Subject subject = subjectService.get(entity.getSubjectId());
            subject.setEnableFlag(true);
            subjectService.getDao().update(subject);
        }
    }
}
