package org.jeecg.modules.app.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.modules.app.dto.GetPlaceListDTO;
import org.jeecg.modules.app.dto.SearchDTO;
import org.jeecg.modules.app.service.IAppHomeService;
import org.jeecg.modules.app.vo.*;
import org.jeecg.modules.system.app.entity.*;
import org.jeecg.modules.system.app.mapper.*;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysDepartMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.util.PositionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import static org.jeecg.common.constant.CommonConstant.INSTRUCTOR;

@Service
public class AppHomeServiceImpl implements IAppHomeService {
    @Resource
    private AppBannerMapper appBannerMapper;
    @Resource
    private AppCoursesMapper appCoursesMapper;
    @Resource
    private AppInstructorMapper appInstructorMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysDepartMapper sysDepartMapper;
    @Resource
    private AppSiteMapper appSiteMapper;
    @Resource
    private AppCategoryMapper appCategoryMapper;
    @Resource
    private AppGameMapper appGameMapper;
    @Resource
    private AppSitePlaceMapper appSitePlaceMapper;
    @Resource
    private AppSitePriceRulesMapper appSitePriceRulesMapper;
    @Resource
    private AppSearchHotMapper appSearchHotMapper;
    @Resource
    private AppGamePriceRulesMapper appGamePriceRulesMapper;

    @Override
    public HomeVO homeInfo() {
        // 获取 banners
        List<AppBanner> appBanners = appBannerMapper.selectList(Wrappers.<AppBanner>lambdaQuery()
                .eq(AppBanner::getDelFlag, 0).eq(AppBanner::getIsEnabled,1));

        // 精品课程（最多3个）
        List<AppCourses> appCoursesFine = appCoursesMapper.selectList(Wrappers.<AppCourses>lambdaQuery()
                .eq(AppCourses::getPriceType, 0).last("LIMIT 3"));

        // 免费课程（最多3个）
        List<AppCourses> appCoursesFree = appCoursesMapper.selectList(Wrappers.<AppCourses>lambdaQuery()
                .eq(AppCourses::getPriceType, 1).last("LIMIT 3"));

        // 合并课程信息
        List<CourseVO> courseVO = new ArrayList<>();
        courseVO.addAll(convertToCoureseVOList(appCoursesFine));
        courseVO.addAll(convertToCoureseVOList(appCoursesFree));

        // 获取好评率最高的两个教练 ID
        List<String> topInstructorUserIds = sysUserMapper.getUserIdListByRoleId(INSTRUCTOR).stream()
                .map(userId -> {
                    AppInstructor instructor = appInstructorMapper.selectOne(
                            Wrappers.<AppInstructor>lambdaQuery().eq(AppInstructor::getUserId, userId));
                    return new Object() {
                        final String id = userId;
                        final Double goodRate = instructor != null ? Double.parseDouble(String.valueOf(instructor.getGoodRate())) : 0.0;
                    };
                })
                .sorted((a, b) -> Double.compare(b.goodRate, a.goodRate))
                .limit(2)
                .map(obj -> obj.id)
                .collect(Collectors.toList());

        // 构建教练列表
        List<InstructorVO> instructorList = new ArrayList<>();
        for (String userId : topInstructorUserIds) {
            SysUser sysUser = sysUserMapper.selectById(userId);
            AppInstructor appInstructor = appInstructorMapper.selectOne(
                    Wrappers.<AppInstructor>lambdaQuery().eq(AppInstructor::getUserId, userId));

            InstructorVO instructorVO = new InstructorVO();
            BeanUtils.copyProperties(appInstructor,instructorVO);
            List<String> list = new ArrayList<>();
                    List.of(appInstructor.getTrainingPrograms().split(",")).forEach(item -> {
                        String str = appCategoryMapper.selectById(item).getName();
                        list.add(str);
                    });
            AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, appInstructor.getOrgCode()));
            if(null != appSite){
                instructorVO.setId(sysUser.getId())
                        .setAvatar(sysUser.getAvatar())
                        .setName(sysUser.getRealname()).setList(list)
                        .setTeachingCount(appInstructor.getClassesNumber())
                        .setOrgName(appSite.getName());
            }

            // 获取该教练的课程（最多取2个）
            List<AppCourses> courses = appCoursesMapper.selectList(
                    Wrappers.<AppCourses>lambdaQuery().eq(AppCourses::getUserId, userId).last("LIMIT 2"));

            List<InstructorVO.CourseInfoVO> courseInfoVOS = courses.stream()
                    .map(course -> {
                        InstructorVO.CourseInfoVO vo = new InstructorVO.CourseInfoVO();
                        BeanUtils.copyProperties(course,vo);
                        //todo 教练订单统计
                        vo.setCount(6666);
                        vo.setSellingPrice(course.getSellingPrice());
                        return vo;
                    })
                    .collect(Collectors.toList());

            instructorVO.setCourseList(courseInfoVOS);
            instructorList.add(instructorVO);
        }
        // 返回首页数据
        return new HomeVO()
                .setBannerList(appBanners.stream()
                        .map(banner -> new AppBannerVO()
                                .setId(banner.getId())
                                .setEventType(banner.getEventType())
                                .setEventValue(banner.getEventValue())
                                .setSortOrder(banner.getSortOrder())
                                .setImageUrl(banner.getImageUrl()))
                        .collect(Collectors.toList()))
                .setCourseList(courseVO)
                .setInstructorList(instructorList);
    }

    /**
     * @Author SheepHy
     * @Description 合并课程信息
     * @Date 9:14 2025/7/4
     * @Param appCoureseList {@link List<AppCourses>}
     * @return List<CoureseVO> {@link List<CourseVO>}
     **/
    private List<CourseVO> convertToCoureseVOList(List<AppCourses> appCoureseList) {
        return appCoureseList.stream()
                .map(courses -> new CourseVO()
                        .setId(courses.getId()).setCover(courses.getCover().split(",")[0])
                        .setPriceType(courses.getPriceType())
                        .setCover(courses.getCover().split( ",")[0])
                        .setSellingPrice(courses.getSellingPrice()))
                .collect(Collectors.toList());
    }

    @Override
    public Page<PlaceVO> getPlaceList(GetPlaceListDTO getPlaceListDTO) {
        Page<PlaceVO> page = new Page<>(getPlaceListDTO.getCurrent(), getPlaceListDTO.getSize());
        Page<PlaceVO> placeList = appSiteMapper.getPlaceList(page, getPlaceListDTO.getVenueType());
        if (ObjectUtil.isNotEmpty(placeList)) {
            placeList.getRecords().forEach(placeVO -> {
                boolean ticketWhether = false;
                List<AppSitePriceRules> appSitePriceRules = new ArrayList<>();
                appSitePlaceMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery()
                        .eq(AppSitePlace::getSiteId, placeVO.getId())
                        .eq(AppSitePlace::getDelFlag,0)
                        .eq(AppSitePlace::getStatus,0)).forEach(appSitePlace -> {
                    appSitePriceRules.addAll(appSitePriceRulesMapper.selectList(Wrappers.<AppSitePriceRules>lambdaQuery()
                            .eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId())
                            .eq(AppSitePriceRules::getDelFlag, 0)
                            .eq(AppSitePriceRules::getStatus, 0)
                            .ne(AppSitePriceRules::getInventory, 0)));
                });
                if(!appSitePriceRules.isEmpty()) ticketWhether = true;
                placeVO.setKm(PositionUtil.calculateDistance(getPlaceListDTO.getLatitude(), getPlaceListDTO.getLongitude(), placeVO.getLatitude().doubleValue(), placeVO.getLongitude().doubleValue()))
                        .setCategory(getCategoryName(placeVO.getCategoryId()))
                        .setTicketWhether(ticketWhether);
            });
        }

        if(getPlaceListDTO.getVenueType().equals("0-2")
                || getPlaceListDTO.getVenueType().equals("1-1")
                || getPlaceListDTO.getVenueType().equals("2-1")){
            // 按 km 升序排序（从近到远）
            placeList.getRecords().sort((p1, p2) -> {
                Double km1 = p1.getKm();
                Double km2 = p2.getKm();
                return km1.compareTo(km2);
            });
        }
        return placeList;
    }

    @Override
    public Object search(SearchDTO searchDTO) {
        switch (searchDTO.getVenueType().charAt(0)) {
            case '0':
                    addAHotWordSearchHistory(searchDTO);
                    return convertSearchPlaceVOPage(searchDTO);
            case '1':
                    addAHotWordSearchHistory(searchDTO);
                    return convertSearchTrainVOPage(searchDTO);
            case '2':
                    addAHotWordSearchHistory(searchDTO);
                    return convertSearchCompetitionVOPage(searchDTO);
            case '3':
                    addAHotWordSearchHistory(searchDTO);
                    return convertSearchInstructorVOPage(searchDTO);
        }

        return new Page<>();
    }

    private void addAHotWordSearchHistory(SearchDTO searchDTO){
        AppSearchHot appSearchHot = appSearchHotMapper.selectOne(Wrappers.<AppSearchHot>lambdaQuery()
                .eq(AppSearchHot::getSearchContent, searchDTO.getKeyword())
                .last("LIMIT 1"));
        if(null == appSearchHot){
            appSearchHotMapper.insert(new AppSearchHot()
                    .setSearchContent(searchDTO.getKeyword())
                    .setSearchCount(1)
                    .setIsActive(1)
                    .setVenueType(searchDTO.getVenueType())
                    .setIsRecommend(0));
        }else {
            appSearchHotMapper.updateById(appSearchHot.setSearchCount(appSearchHot.getSearchCount() + 1));
        }
    }

    @Override
    public List<AppSearchHot> getHotSearch() {
        return appSearchHotMapper.selectList(Wrappers.<AppSearchHot>lambdaQuery()
                // 新增条件：当前时间在 startTime 和 endTime 之间
                .le(AppSearchHot::getStartTime, new Date())  // 开始时间 <= 当前时间
                .ge(AppSearchHot::getEndTime, new Date())    // 结束时间 >= 当前时间
                .last("LIMIT 10")
                .orderByDesc(AppSearchHot::getSearchCount));
    }

    /**
     * @Author SheepHy
     * @Description 全局搜索场地分页查询
     * @Date 11:05 2025/7/7
     * @Param searchDTO {@link SearchDTO}
     * @return Page<SearchVO.SearchPlaceVO>
     **/
    private Page<SearchVO.SearchPlaceVO> convertSearchPlaceVOPage(SearchDTO searchDTO) {
        Page<SearchVO.SearchPlaceVO> page = new Page<>(searchDTO.getCurrent(), searchDTO.getSize());
        Page<SearchVO.SearchPlaceVO> searchPlaceVOPage = appSiteMapper.convertSearchPlaceVOPage(page, searchDTO);
        searchPlaceVOPage.getRecords().forEach(placeVO -> {
            AppSite appSite = appSiteMapper.selectById(placeVO.getId());
            placeVO.setKm(PositionUtil.calculateDistance(searchDTO.getLatitude(), searchDTO.getLongitude(), appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()))
                    .setCategory(getCategoryName(placeVO.getCategoryId())).setCover(placeVO.getCover().split(",")[0]);

        });
        if(searchDTO.getVenueType().equals("0-2")
                || searchDTO.getVenueType().equals("1-1")
                || searchDTO.getVenueType().equals("2-1")){
            // 按 km 升序排序（searchDTO）
            searchPlaceVOPage.getRecords().sort((p1, p2) -> {
                Double km1 = p1.getKm();
                Double km2 = p2.getKm();
                return km1.compareTo(km2);
            });
        }
        return searchPlaceVOPage;
    }

    /**
     * @Author SheepHy
     * @Description 根据类目ID获取完整的类目名称
     * @Date 13:31 2025/7/7
     * @Param categoryId 类目ID
     * @return List<String>
     **/
    private List<String> getCategoryName(String categoryId) {
        List<String> list = new ArrayList<>();
        if(null != categoryId){
            String[] split = categoryId.split(",");
            Arrays.stream(split).forEach(id -> {
                list.add(appCategoryMapper.selectById(id).getName());
            });
        }
        return list;
    }

    /**
     * @Author SheepHy
     * @Description 培训课程分页查询
     * @Date 13:37 2025/7/7
     * @Param searchDTO {@link SearchDTO}
     * @return Page<SearchVO.SearchTrainVO>
     **/
    private Page<SearchVO.SearchTrainVO> convertSearchTrainVOPage(SearchDTO searchDTO) {
        Page<SearchVO.SearchTrainVO> page = new Page<>(searchDTO.getCurrent(), searchDTO.getSize());
        Page<SearchVO.SearchTrainVO> searchTrainVOPage = appCoursesMapper.convertSearchTrainVOPage(page, searchDTO);
        searchTrainVOPage.getRecords().forEach(trainVO -> {
            AppSite appSite = appSiteMapper.selectById(trainVO.getSiteId());
            trainVO.setKm(PositionUtil.calculateDistance(searchDTO.getLatitude(), searchDTO.getLongitude(), appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()));
        });
        return searchTrainVOPage;
    }

    /**
     * @Author SheepHy
     * @Description 赛事分页查询
     * @Date 14:04 2025/7/7
     * @Param searchDTO {@link SearchDTO}
     * @return Page<SearchVO.SearchRaceVO>
     **/
    private Page<SearchVO.SearchRaceVO> convertSearchCompetitionVOPage(SearchDTO searchDTO) {
        Page<SearchVO.SearchRaceVO> page = new Page<>(searchDTO.getCurrent(), searchDTO.getSize());
        Page<SearchVO.SearchRaceVO> searchCompetitionVOPage = appGameMapper.convertSearchCompetitionVOPage(page, searchDTO);
        searchCompetitionVOPage.getRecords().forEach(competitionVO -> {
            AppSite appSite = appSiteMapper.selectOne(
                    Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, competitionVO.getOrgCode()));
            competitionVO.setKm(PositionUtil.calculateDistance(
                    searchDTO.getLatitude(), searchDTO.getLongitude(),
                    appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()));
            // 获取价格规则并判断 type
            List<AppGamePriceRules> appGamePriceRules = appGamePriceRulesMapper.selectList(
                    Wrappers.<AppGamePriceRules>lambdaQuery()
                            .eq(AppGamePriceRules::getGameId, competitionVO.getId()));
            int targetType = -1; // 默认无效状态
            if (appGamePriceRules != null && !appGamePriceRules.isEmpty()) {
                boolean hasType0 = appGamePriceRules.stream()
                        .anyMatch(rule -> rule.getType() == 0);
                boolean hasType1 = appGamePriceRules.stream()
                        .anyMatch(rule -> rule.getType() == 1);
                if (hasType0 && hasType1) {
                    targetType = 2;
                } else if (hasType0) {
                    targetType = 0;
                } else if (hasType1) {
                    targetType = 1;
                }
            }
            competitionVO.setType(targetType);
            competitionVO.setKm(PositionUtil.calculateDistance(searchDTO.getLatitude(), searchDTO.getLongitude(), appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()));
            competitionVO.setCategory(getCategoryName(appSite.getCategoryId()));
        });
        return page;
    }
    
    /** 
     * @Author SheepHy
     * @Description
     * @Date 14:43 2025/7/7
     * @Param searchDTO {@link SearchDTO}
     * @return Page<SearchVO.SearchInstructorVO>
     **/
    private Page<SearchVO.SearchInstructorVO> convertSearchInstructorVOPage(SearchDTO searchDTO) {
        Page<SearchVO.SearchInstructorVO> page = new Page<>(searchDTO.getCurrent(), searchDTO.getSize());
        Page<SearchVO.SearchInstructorVO> searchInstructorVOPage = appInstructorMapper.convertSearchInstructorVOPage(page, searchDTO);
        searchInstructorVOPage.getRecords().forEach(instructorVO -> {
            // 获取该教练的课程（最多取2个）
            List<AppCourses> courses = appCoursesMapper.selectList(
                    Wrappers.<AppCourses>lambdaQuery().eq(AppCourses::getUserId, instructorVO.getUserId()).last("LIMIT 2"));
            List<SearchVO.SearchCoursesVO> courseInfoVOS = courses.stream()
                    .map(course -> {
                        SearchVO.SearchCoursesVO vo = new SearchVO.SearchCoursesVO();
                        BeanUtils.copyProperties(course, vo);
                        vo.setSales(666);
                        return vo;
                    })
                    .collect(Collectors.toList());
            AppSite appSite = appSiteMapper.selectOne(Wrappers.<AppSite>lambdaQuery().eq(AppSite::getOrgCode, instructorVO.getOrgCode()));
            if (appSite!=null&& ObjectUtils.isNotEmpty(appSite.getLatitude())&&ObjectUtils.isNotEmpty(appSite.getLongitude())){
                instructorVO.setKm(PositionUtil.calculateDistance(searchDTO.getLatitude(), searchDTO.getLongitude(), appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()))
                        .setCourseList(courseInfoVOS);
            }
        });
        return searchInstructorVOPage;
    }
}
