package com.yonge.cooleshow.admin.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.dayaedu.cbs.common.enums.school.ECourseType;
import com.dayaedu.cbs.openfeign.client.CoursewareFeignService;
import com.dayaedu.cbs.openfeign.client.MusicFeignClientService;
import com.dayaedu.cbs.openfeign.wrapper.courseware.CbsLessonCoursewareWrapper;
import com.dayaedu.cbs.openfeign.wrapper.music.MusicSheetCategoriesWrapper;
import com.microsvc.toolkit.common.response.paging.QueryInfo;
import com.yonge.cooleshow.admin.io.request.TenantAlbumVo;
import com.yonge.cooleshow.biz.dal.dto.search.StudentMusicSheetSearch;
import com.yonge.cooleshow.biz.dal.entity.*;
import com.yonge.cooleshow.biz.dal.enums.SourceTypeEnum;
import com.yonge.cooleshow.biz.dal.enums.SubjectTypeEnum;
import com.yonge.cooleshow.biz.dal.service.*;
import com.yonge.cooleshow.biz.dal.vo.MusicSheetVo;
import com.yonge.cooleshow.biz.dal.wrapper.TenantAlbumMusicWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.TenantAlbumWrapper;
import com.yonge.cooleshow.common.constant.SysConfigConstant;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.toolset.base.exception.BizException;
import com.yonge.toolset.base.page.PageInfo;
import com.yonge.toolset.mybatis.support.PageUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author：haonan
 * @Date：2023/7/27 18:26
 * @Filename：TenantAlbumController
 */

@RestController
@RequestMapping("${app-config.url.admin:}/tenantAlbum")
@Api(value = "机构专辑管理", tags = "机构专辑管理")
public class TenantAlbumController {
    @Autowired
    TenantAlbumService tenantAlbumService;

    @Autowired
    private TenantAlbumMusicService tenantAlbumMusicService;

    @Autowired
    private TenantAlbumRefService tenantAlbumRefService;

    @Autowired
    private TenantInfoService tenantInfoService;

    @Autowired
    private MusicSheetService musicSheetService;


    @Autowired
    private CoursewareFeignService coursewareFeignService;

    @Autowired
    private MusicFeignClientService musicFeignClientService;
    @Autowired
    private SysConfigService sysConfigService;


    @Autowired
    private SubjectService subjectService;

    @Autowired
    private MusicTagService musicTagService;

    /**
     * 查询分页
     *
     * @param query
     */
    @PostMapping("/page")
    @ApiOperation(value = "查询分页", notes = "tenantAlbum")
    @PreAuthorize("@pcs.hasPermissions('tenantAlbum/page')")
    public HttpResponseResult<PageInfo<TenantAlbumWrapper.TenantAlbum>> page(@RequestBody TenantAlbumWrapper.TenantAlbumQuery query) {
        IPage<TenantAlbumWrapper.TenantAlbum> pages = tenantAlbumService.selectPage(QueryInfo.getPage(query), query);
        return HttpResponseResult.succeed(PageUtil.pageInfo(pages));
    }


    /**
     * 查询详情
     *
     * @param id 详情ID
     * @return TenantAlbum
     */
    @GetMapping("/detailInfo")
    @ApiOperation(value = "查询详情", notes = "detail")
    @PreAuthorize("@pcs.hasPermissions('tenantAlbum/detailInfo')")
    public HttpResponseResult<List<TenantAlbumWrapper.TenantAlbumSheet>> detailInfo(@RequestParam("id") Long id,@RequestParam("subjectType") String subjectType) {
        TenantAlbum tenantAlbum = tenantAlbumService.detail(id);
        if (tenantAlbum == null) {
            throw new BizException("专辑信息不存在");
        }

        List<TenantAlbumMusic> tenantAlbumMusics = tenantAlbumMusicService.lambdaQuery()
            .eq(TenantAlbumMusic::getTenantAlbumId, id)
            .eq(TenantAlbumMusic::getSubjectType, SubjectTypeEnum.valueOf(subjectType))
            .eq(TenantAlbumMusic::getDelFlag, false)
            .list();

        Map<SubjectTypeEnum, List<TenantAlbumMusic>> groupByType =
            tenantAlbumMusics.stream().collect(Collectors.groupingBy(TenantAlbumMusic::getSubjectType));


        List<Long> musicSheetIdlist = tenantAlbumMusics.stream()
            .filter(o ->o.getSubjectType() !=SubjectTypeEnum.COURSEWARE)
            .map(TenantAlbumMusic::getMusicSheetId).distinct()
            .collect(Collectors.toList());
        // 过滤出课件
        List<Long> coursewareList = tenantAlbumMusics.stream()
            .filter(o -> o.getSubjectType() == SubjectTypeEnum.COURSEWARE)
            .map(TenantAlbumMusic::getMusicSheetId).distinct().collect(Collectors.toList());
        Map<Long,CbsLessonCoursewareWrapper.Entity> coursewareDtoMap = new HashMap<>();

        if (CollectionUtils.isNotEmpty(coursewareList)) {
            List<CbsLessonCoursewareWrapper.Entity> entities = coursewareFeignService
                .lessonCoursewareLambdaQuery(CbsLessonCoursewareWrapper.LambdaQuery.builder().ids(coursewareList).delFlag(false).build()).feignData();
            coursewareDtoMap.putAll(entities.stream().filter(o-> !o.getDelFlag()).collect(Collectors.toMap(CbsLessonCoursewareWrapper.Entity::getId, Function.identity())));
        }

        Map<Long, MusicSheetVo> idMsMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(musicSheetIdlist)) {
            StudentMusicSheetSearch search = new StudentMusicSheetSearch();
            search.setMusicSheetIdlist(musicSheetIdlist);
            search.setPage(1);
            search.setRows(9999);
            search.setProviderType(SourceTypeEnum.TENANT);
            IPage<MusicSheetVo> records = musicSheetService.selectStudentPage(PageUtil.getPage(search), search, null);
            idMsMap.putAll(records.getRecords().stream()
                .collect(Collectors.toMap(MusicSheet::getId, Function.identity())));
        }
        List<TenantAlbumWrapper.TenantAlbumSheet> tenantAlbumSheets = new ArrayList<>();
        groupByType.forEach((key, value) -> {
            value.sort(Comparator.comparing(TenantAlbumMusic::getSortNumber));
            TenantAlbumWrapper.MusicSheetData sheetData = new TenantAlbumWrapper.MusicSheetData();
            sheetData.setSubjectType(key);
            tenantAlbumSheets.addAll(value.stream().map(next -> {

                TenantAlbumWrapper.TenantAlbumSheet tenantAlbumSheet =JSON.parseObject(JSON.toJSONString(next), TenantAlbumWrapper.TenantAlbumSheet.class);
                Long musicSheetId = tenantAlbumSheet.getMusicSheetId();
                switch (key) {
                    case COURSEWARE:
                        CbsLessonCoursewareWrapper.Entity entity = coursewareDtoMap.get(musicSheetId);
                        if (entity != null) {
                            tenantAlbumSheet.setMusicSheetName(entity.getName());
                            tenantAlbumSheet.setTitleImg(entity.getCoverImg());
                            tenantAlbumSheet.setMusicSubject(entity.getCourseTypeCode());
                            tenantAlbumSheet.setMusicSubjectName(ECourseType.valueOf(entity.getCourseTypeCode()).getName());
                        } else {
                            return null;
                        }
                        break;
                    case MUSIC:
                    case SUBJECT:
                    case ENSEMBLE:
                    {
                        MusicSheetVo musicSheet = idMsMap.get(musicSheetId);
                        if (musicSheet == null) {
                            return null;
                        }
                        tenantAlbumSheet.setMusicSheetName(musicSheet.getMusicSheetName());
                        tenantAlbumSheet.setMusicTag(musicSheet.getMusicTag());
                        tenantAlbumSheet.setComposer(musicSheet.getComposer());
                        tenantAlbumSheet.setMusicSubject(musicSheet.getMusicSubject());
                        tenantAlbumSheet.setMusicSubjectName(musicSheet.getSubjectNames());
                        tenantAlbumSheet.setMusicTagName(musicSheet.getMusicTagNames());

                    }
                    break;
                    default:
                        break;
                }

                return tenantAlbumSheet;
            }).filter(Objects::nonNull).collect(Collectors.toList()));

        });
        return HttpResponseResult.succeed(tenantAlbumSheets);

    }

    private String updateCategory(List<MusicSheetCategoriesWrapper.MusicSheetCategories> musicSheetCategories,
                                Long categoryId, String tenantCategoryId,TenantAlbumWrapper.TenantAlbumSheet tenantAlbumSheet) {

        if (StringUtils.isBlank(tenantCategoryId)) {
            return "";
        }
        for (MusicSheetCategoriesWrapper.MusicSheetCategories o : musicSheetCategories) {
            if (o.getId().equals(Long.parseLong(tenantCategoryId))) {
                return o.getName();
            }
            if (CollectionUtils.isNotEmpty(o.getMusicSheetCategoriesList())) {
                String s = updateCategory( o.getMusicSheetCategoriesList(), categoryId, tenantCategoryId,tenantAlbumSheet);
                if (!tenantAlbumSheet.getLoop()) {
                    return s;
                }
                if (o.getId().equals(categoryId) && StringUtils.isNotBlank(s)) {
                    tenantAlbumSheet.setErrFlag(false);
//                    tenantAlbumSheet.setLoop(false);
//                    return s;
                }
                if (StringUtils.isNotBlank(s)) {
                    return o.getName() + "/" + s;
                }
            }
        }
        return "";
    }

    private Long getCategoryId(String subjectType) {
        if (StringUtils.isBlank(subjectType)) {
            return null;
        }
        if (SubjectTypeEnum.SUBJECT.name().equals(subjectType)) {
            return Long.parseLong(sysConfigService.findConfigValue(SysConfigConstant.TENANT_ALBUM_SUBJECT_TYPE_CATEGORY));
        } else if (SubjectTypeEnum.ENSEMBLE.name().equals(subjectType)) {
            return Long.parseLong(sysConfigService.findConfigValue(SysConfigConstant.TENANT_ALBUM_ENSEMBLE_TYPE_CATEGORY));
        } if (SubjectTypeEnum.MUSIC.name().equals(subjectType)) {
            return Long.parseLong(sysConfigService.findConfigValue(SysConfigConstant.TENANT_ALBUM_MUSIC_TYPE_CATEGORY));
        }
        return null;
    }

    /**
     * 查询详情
     *
     * @param id 详情ID
     * @return TenantAlbum
     */
    @PostMapping("/detail")
    @ApiOperation(value = "查询详情", notes = "detail")
    @PreAuthorize("@pcs.hasPermissions('tenantAlbum/detail')")
    public HttpResponseResult<TenantAlbumWrapper.TenantAlbum> detail(@RequestParam("id") Long id) {
        TenantAlbum tenantAlbum = tenantAlbumService.detail(id);
        if (tenantAlbum == null) {
            throw new BizException("专辑信息不存在");
        }

        TenantAlbumWrapper.TenantAlbum vo = JSON.parseObject(JSON.toJSONString(tenantAlbum),
                TenantAlbumWrapper.TenantAlbum.class);

        //查关联表
        TenantAlbumRef one = tenantAlbumRefService.lambdaQuery().eq(TenantAlbumRef::getTenantAlbumId, id)
                .last("limit 1").one();
        vo.setTenantId(one.getTenantId().toString());
        //查询曲目表

        TenantInfo tenantInfo = tenantInfoService.getById(one.getTenantId());
        vo.setTenantName(tenantInfo.getName());

        return HttpResponseResult.succeed(vo);
    }


    /**
     * 新增专辑
     */
    @PostMapping("/save")
    @ApiOperation(value = "新增专辑", notes = "新增专辑")
    @PreAuthorize("@pcs.hasPermissions('tenantAlbum/save')")
    public HttpResponseResult<Boolean> save(@Validated @RequestBody TenantAlbumVo.TenantAlbum album) {

        // 检查曲目重复
        if (CollectionUtils.isNotEmpty(album.getMusicSheetData())) {
            List<Long> musicIds = album.getMusicSheetData().stream()
                .filter(o ->o.getSubjectType() !=SubjectTypeEnum.COURSEWARE)
                .flatMap(o -> o.getMusicSheetList().stream().map(TenantAlbumVo.MusicObject::getId))
                .collect(Collectors.toList());
            Set<Long> musicSet = new HashSet<>(musicIds);
            if (musicSet.size() < musicIds.size()) {
                throw new BizException("不能添加相同的曲目");
            }
        }

        TenantAlbum tenantAlbum = JSON.parseObject(album.jsonString(), TenantAlbum.class);
        List<TenantAlbumVo.MusicSheetData> musicSheetData = album.getMusicSheetData();

        List<TenantAlbumWrapper.MusicSheetData> musicSheetDataList = musicSheetData.stream().map(next ->{
                    TenantAlbumWrapper.MusicSheetData sheetData =new TenantAlbumWrapper.MusicSheetData();

                    List<TenantAlbumVo.MusicObject> musicSheetList = next.getMusicSheetList();
                    sheetData.getTenantAlbumSheetList().addAll( musicSheetList.stream().map(m->{
                        TenantAlbumWrapper.TenantAlbumSheet tenantAlbumSheet = new TenantAlbumWrapper.TenantAlbumSheet();
                        tenantAlbumSheet.setLevel(m.getLevel());
                        tenantAlbumSheet.setType(m.getType());
                        tenantAlbumSheet.setId(m.getId().toString());
                        return tenantAlbumSheet;
                    }).collect(Collectors.toList()));
                    sheetData.setSubjectType(next.getSubjectType());
                    return sheetData;
                }
        ).collect(Collectors.toList());
        tenantAlbumService.insertTenantAlbum(album.getTenantId(), tenantAlbum, musicSheetDataList);
        return HttpResponseResult.succeed();
    }

    @PostMapping("/update")
    @ApiOperation(value = "修改专辑", notes = "修改专辑")
    @PreAuthorize("@pcs.hasPermissions('tenantAlbum/update')")
    public HttpResponseResult<Boolean> update( @RequestBody TenantAlbumVo.TenantAlbum album) {

        // 检查曲目重复
        if (CollectionUtils.isNotEmpty(album.getMusicSheetData())) {
            List<Long> musicIds = album.getMusicSheetData().stream()
                .filter(o -> o.getSubjectType() != SubjectTypeEnum.COURSEWARE)
                .flatMap(o -> o.getMusicSheetList().stream().map(TenantAlbumVo.MusicObject::getId))
                .collect(Collectors.toList());
            Set<Long> musicSet = new HashSet<>(musicIds);
            if (musicSet.size() < musicIds.size()) {
                throw new BizException("不能添加相同的曲目");
            }
        }

        TenantAlbum tenantAlbum = JSON.parseObject(album.jsonString(), TenantAlbum.class);
        List<TenantAlbumVo.MusicSheetData> musicSheetData = album.getMusicSheetData();

        List<TenantAlbumWrapper.MusicSheetData> musicSheetDataList = musicSheetData.stream().map(next ->{
            TenantAlbumWrapper.MusicSheetData sheetData =new TenantAlbumWrapper.MusicSheetData();

            List<TenantAlbumVo.MusicObject> musicSheetList = next.getMusicSheetList();
            sheetData.getTenantAlbumSheetList().addAll( musicSheetList.stream().map(m->{
                TenantAlbumWrapper.TenantAlbumSheet tenantAlbumSheet = new TenantAlbumWrapper.TenantAlbumSheet();
                tenantAlbumSheet.setLevel(m.getLevel());
                tenantAlbumSheet.setType(m.getType());
                tenantAlbumSheet.setId(m.getId().toString());
                return tenantAlbumSheet;
            }).collect(Collectors.toList()));
            sheetData.setSubjectType(next.getSubjectType());
            return sheetData;
        }).collect(Collectors.toList());
        tenantAlbumService.updateAlbum(album.getTenantId(), tenantAlbum, musicSheetDataList);
        return HttpResponseResult.succeed();
    }

    @PostMapping("/updateStatus")
    @ApiOperation(value = "启用/冻结", notes = "启用/冻结")
    @PreAuthorize("@pcs.hasPermissions('tenantAlbum/updateStatus')")
    public HttpResponseResult<Boolean> updateStatus(@Validated @RequestBody TenantAlbumVo.UpdateStatus status) {
        tenantAlbumService.updateStatus(status.getId(), status.getStatus());
        return HttpResponseResult.succeed();
    }

}
