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

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.app.service.IDetailService;
import org.jeecg.modules.app.vo.CourseInfoVO;
import org.jeecg.modules.app.vo.PlaceInfoVO;
import org.jeecg.modules.app.vo.course.CourseRequestVo;
import org.jeecg.modules.app.vo.course.CourseResponseVo;
import org.jeecg.modules.app.vo.stadium.ConcertsDetailsVO;
import org.jeecg.modules.app.vo.stadium.ConcertsVO;
import org.jeecg.modules.app.vo.stadium.StadiumConcertsResponseVO;
import org.jeecg.modules.app.vo.stadium.StadiumConcertsVO;
import org.jeecg.modules.system.app.entity.*;
import org.jeecg.modules.system.app.mapper.*;
import org.jeecg.modules.system.app.utils.TimeRangeFinder;
import org.jeecg.modules.system.app.vo.time.NextSevenDayVo;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.jeecg.modules.system.mapper.SysUserMapper;
import org.jeecg.modules.system.util.PositionUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

import static org.jeecg.modules.system.constant.DefIndexConst.FACILITY_INFO;

@Service
@Log4j2
public class DetailServiceImpl implements IDetailService {
    @Resource
    private AppSiteMapper appSiteMapper;
    @Resource
    private AppCoursesPriceRulesMapper appCoursesPriceRulesMapper;
    @Resource
    private AppCoursesMapper appCoursesMapper;
    @Resource
    private AppOrderProductMapper appOrderProductMapper;

    @Autowired
    private AppOrderProInfoMapper appOrderProInfoMapper;
    @Resource
    private AppSitePriceRulesMapper appSitePriceRulesMapper;
    @Resource
    private AppInstructorMapper appInstructorMapper;
    @Resource
    private AppOrderMapper appOrderMapper;
    @Resource
    private AppSitePlaceMapper appSitePlaceMapper;
    @Resource
    private AppCategoryMapper appCategoryMapper;
    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private SysDictMapper sysDictMapper;

    @Autowired
    private AppInsureMapper appInsureMapper;
    @Autowired
    InsurePriceMapper insurePriceMapper;


    @Override
    public PlaceInfoVO getPlaceInfo(String id) {
        AppSite appSite = appSiteMapper.selectById(id);
        PlaceInfoVO placeInfo = appSiteMapper.getPlaceInfo(id);
        List<DictModel> dictModels = sysDictMapper.queryDictItemsByCode(FACILITY_INFO);
        List<String> facilityInfo = new ArrayList<>();
        if(null != placeInfo.getFacility()){
            Arrays.stream(placeInfo.getFacility().split(",")).forEach(facility -> {
                dictModels.forEach(dictModel -> {
                    if(facility.equals(dictModel.getValue())){
                        facilityInfo.add(dictModel.getTitle());
                    }
                });
            });
        }
        placeInfo.setFacilityInfo(facilityInfo);
        List<PlaceInfoVO.InstructorVO> instructorVOList = new ArrayList<>();
        List<AppInstructor> appInstructors = appInstructorMapper.selectList(Wrappers.<AppInstructor>lambdaQuery()
                .eq(AppInstructor::getOrgCode, appSite.getOrgCode()));
        if (appInstructors != null) {
            for (AppInstructor instructor : appInstructors) {
                PlaceInfoVO.InstructorVO vo = new PlaceInfoVO.InstructorVO();
                BeanUtils.copyProperties(instructor,vo); // 注意参数顺序
                List<String> category = new ArrayList<>();
                Arrays.stream(instructor.getTrainingPrograms().split(",")).forEach(categoryId -> {
                    AppCategory appCategory = appCategoryMapper.selectById(categoryId);
                    category.add(appCategory.getName());
                });
                vo.setCategory(category);
                SysUser sysUser = sysUserMapper.selectById(instructor.getUserId());
                vo.setName(sysUser.getUsername()).setAvatar(sysUser.getAvatar());
                instructorVOList.add(vo);
            }
        }
        placeInfo.setInstructorVOList(instructorVOList);
        if(appSite.getType() == 0){
            List<PlaceInfoVO.PlaceInfoMsgVO> placeInfoMsgVOS = new ArrayList<>();
            appSitePlaceMapper.selectList(Wrappers.<AppSitePlace>lambdaQuery().eq(AppSitePlace::getSiteId, id)
                    .eq(AppSitePlace::getType,0)).forEach(appSitePlace -> {
                PlaceInfoVO.PlaceInfoMsgVO placeInfoMsgVO = new PlaceInfoVO.PlaceInfoMsgVO();
                placeInfoMsgVO.setName(appSitePlace.getName())
                        .setSales(getPlaceSales(id))
                        .setId(appSitePlace.getId())
                        .setOriginalPrice(appSitePriceRulesMapper.selectOne(Wrappers.<AppSitePriceRules>lambdaQuery()
                                .eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId())
                                .last("limit 1").orderByDesc(AppSitePriceRules::getOriginalPrice)).getOriginalPrice())
                        .setSellingPrice(appSitePriceRulesMapper.selectOne(Wrappers.<AppSitePriceRules>lambdaQuery()
                                .eq(AppSitePriceRules::getSitePlaceId, appSitePlace.getId())
                                .last("limit 1").orderByDesc(AppSitePriceRules::getSellingPrice)).getSellingPrice())
                        .setCategory(getCategoryName(appSitePlace.getCategoryId()))
                        .setCover(appSitePlace.getCover().split(",")[0])
                        .setReminder(appSitePlace.getReminder())
                        .setRefundType(appSitePlace.getRefundType());
                placeInfoMsgVOS.add(placeInfoMsgVO);
            });
            placeInfo.setPlaceInfoMsgVO(placeInfoMsgVOS);
            return placeInfo;
        }else if(appSite.getType() == 1){
            List<PlaceInfoVO.PlaceInfoGymMsgVO> placeInfoMsgVO = appSitePlaceMapper.getPlaceInfoNoFixation(appSite.getId());
            placeInfo.setPlaceInfoMsgVO(placeInfoMsgVO);
            return placeInfo;
        }else {
            return null;
        }
    }


    @Override
    public CourseInfoVO getCourseInfo(String id, double latitude, double longitude) {
        CourseInfoVO courseInfoVO = appCoursesMapper.getCourseInfo(id);
        AppSite appSite = appSiteMapper.selectById(courseInfoVO.getAddressSiteId());
        if (appSite!=null&& ObjectUtils.isNotEmpty(appSite.getLatitude())&& ObjectUtils.isNotEmpty(appSite.getLongitude())){
            courseInfoVO.setKm(PositionUtil.calculateDistance(latitude, longitude, appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue()));
        }
        courseInfoVO.setSales(getCourseSales(id));
        List<CourseInfoVO.CourseDetailVO> courseDetailVOList = new ArrayList<>();
        appCoursesPriceRulesMapper.selectList(Wrappers.<AppCoursesPriceRules>lambdaQuery()
                .eq(AppCoursesPriceRules::getCoursesId, courseInfoVO.getId())).forEach(appCourses -> {
            CourseInfoVO.CourseDetailVO courseDetailVO = new CourseInfoVO.CourseDetailVO();
            BeanUtils.copyProperties(appCourses,courseDetailVO);
            courseDetailVOList.add(courseDetailVO);
        });

        courseInfoVO.setCourseDetail(courseDetailVOList);
        return courseInfoVO;
    }

    @Override
    public List<PlaceInfoVO.CourseInfoVO> courseInfoVOList(String categoryId,String id,double longitude,double latitude) {
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<PlaceInfoVO.CourseInfoVO> courseInfoVOList = new ArrayList<>();
        appCoursesMapper.selectList(Wrappers.<AppCourses>lambdaQuery()
                .eq(AppCourses::getAddressSiteId, id)
                .like(AppCourses::getCategoryId, categoryId)
                .eq(AppCourses::getStatus, 0)
                .eq(AppCourses::getDelFlag, 0)).forEach(appCourses -> {
            List<String> list = Arrays.asList(appCourses.getCover().split(","));
            PlaceInfoVO.CourseInfoVO courseInfoVO = new PlaceInfoVO.CourseInfoVO();
            BeanUtils.copyProperties(appCourses, courseInfoVO);
            courseInfoVO.setSales(getCourseSalesCount(appCourses.getId()));
            courseInfoVO.setSalesYear(getCourseSales(appCourses.getId()));
            courseInfoVO.setPriceType(isFirstPurchase(user.getId()));
            courseInfoVO.setCover(list.get(0));
            AppSite appSite = appSiteMapper.selectById(appCourses.getAddressSiteId());
            if (appSite!=null){
                courseInfoVO.setAddress(appSite.getAddress());
                double km = PositionUtil.calculateDistance(latitude, longitude, appSite.getLatitude().doubleValue(), appSite.getLongitude().doubleValue());
                courseInfoVO.setKm(new BigDecimal(String.valueOf(km)));
            }

            courseInfoVOList.add(courseInfoVO);
        });
        return courseInfoVOList;
    }

    @Override
    public PlaceInfoVO.theGymnasiumIsCharteredVO getPlaceInfoNoFixation(String id, String categoryId) {
        AppSitePlace appSitePlace = appSitePlaceMapper.selectOne(Wrappers.<AppSitePlace>lambdaQuery()
                .eq(AppSitePlace::getSiteId, id)
                .eq(AppSitePlace::getStatus, 0)
                .eq(AppSitePlace::getDelFlag, 0)
                .last("LIMIT 1"));
        List<PlaceInfoVO.theGymnasiumIsCharteredInfoVO> collect = new ArrayList<>();
        PlaceInfoVO.theGymnasiumIsCharteredVO theGymnasiumIsCharteredVO = new PlaceInfoVO.theGymnasiumIsCharteredVO()
                .setCategory(getCategoryName(categoryId));
        if(appSitePlace != null){
            collect = appSitePriceRulesMapper.theGymnasiumIsCharteredInfo(appSitePlace.getOrgCode(), categoryId);
            theGymnasiumIsCharteredVO.setEarlyRefundTime(Optional.ofNullable(appSitePlace.getEarlyRefundTime()).orElse(0));

        }
        if(!collect.isEmpty()){
            theGymnasiumIsCharteredVO.setVr(appSiteMapper.selectById(id).getVr());
        }
        theGymnasiumIsCharteredVO.setTimeSlot(collect);
        return theGymnasiumIsCharteredVO;
    }

    @Override
    public Result<StadiumConcertsResponseVO> findConcerts(String siteId, String categoryId) {
        List<NextSevenDayVo> nextSevenDays = TimeRangeFinder.getNextSevenDays();
        StadiumConcertsResponseVO  stadiumConcertsResponseVO = appSitePlaceMapper.findBySidAndCid(siteId,categoryId);
        if (stadiumConcertsResponseVO==null){
            stadiumConcertsResponseVO = new StadiumConcertsResponseVO();
        }
        List<StadiumConcertsVO> stadiumConcertsVOS = new ArrayList<>();
        Boolean label = true;
        for (NextSevenDayVo nextSevenDay : nextSevenDays) {
            StadiumConcertsVO stadiumConcertsVO = new StadiumConcertsVO();
            BeanUtils.copyProperties(nextSevenDay,stadiumConcertsVO);
            List<ConcertsVO>  concertsVOList=null;
            //查询当天所有场地和场次及状态
            if (label){
                concertsVOList= appSitePlaceMapper.findByConcertsAndTime(stadiumConcertsVO.getWeekDay(),siteId,categoryId);
            }else {
                concertsVOList= appSitePlaceMapper.findByConcerts(stadiumConcertsVO.getWeekDay(),siteId,categoryId);
            }

            label=false;
            stadiumConcertsVO.setConcertsVOList(concertsVOList);
            long count=0L;
            if (concertsVOList!=null&&!concertsVOList.isEmpty()){

                for (ConcertsVO concertsVO : concertsVOList) {
                    List<ConcertsDetailsVO> concertsDetailsVOList = concertsVO.getConcertsDetailsVOList();
                    if (concertsDetailsVOList!=null&&!concertsDetailsVOList.isEmpty()){
                        count = count+concertsDetailsVOList.stream()
                                .filter(Objects::nonNull) // 过滤掉null元素
                                .filter(vo -> vo.getConcertStatus() == 0) // 精确匹配状态0
                                .count();
                    }
                }

            }
            stadiumConcertsVO.setNoDayConcertsReservationNum(count);


            stadiumConcertsVOS.add(stadiumConcertsVO);
        }
        stadiumConcertsResponseVO.setStadiumConcertsVOList(stadiumConcertsVOS);
        return Result.ok(stadiumConcertsResponseVO);
    }

    @Override
    public List<AppCategory> getAllCategory(String id) {
        AppSite appSite = appSiteMapper.selectById(id);
        List<AppCategory> appCategories = new ArrayList<>();
        if (appSite!=null &&StringUtils.isNotBlank(appSite.getCategoryId())){
            List<String> strings = new ArrayList<>();
            if (appSite.getCategoryId().indexOf(",")>0){
                strings = Arrays.asList(appSite.getCategoryId().split(","));
            }else {
                strings.add(appSite.getCategoryId());
            }
            appCategories = appCategoryMapper.selectList(Wrappers.<AppCategory>lambdaQuery()
                    .eq(AppCategory::getStatus, 0).in(AppCategory::getId,strings)
                    .eq(AppCategory::getDelFlag, 0));
        }
        return appCategories;
    }

    /**
     * 查询课程分页列表
     * @param courseRequestVo
     * @return
     */
    @Override
    public IPage<CourseResponseVo> findByCourseList(CourseRequestVo courseRequestVo) {
        Page<CourseResponseVo> page = new Page<CourseResponseVo>(courseRequestVo.getPageNo(), courseRequestVo.getPageSize());
        IPage<CourseResponseVo>  courseInfoVOIPage=null;
        if (ObjectUtil.isNotEmpty(courseRequestVo.getOrderByType())){
            if (ObjectUtil.isNotEmpty(courseRequestVo.getLongitude())
                    &&ObjectUtil.isNotEmpty(courseRequestVo.getLatitude())){
                courseInfoVOIPage= appCoursesMapper.findByLaLoList(page,courseRequestVo);
            }else {
                courseInfoVOIPage= appCoursesMapper.findByList(page,courseRequestVo);
            }
        }else {
            courseInfoVOIPage= appCoursesMapper.findByCourseList(page,courseRequestVo);
        }
        courseInfoVOIPage.getRecords().forEach(courseResponseVo -> {
            String string = courseResponseVo.getCover().split(",")[0];
            courseResponseVo.setCover(string);
        });
        return courseInfoVOIPage;
    }

    /**
     * @return
     * @Author SheepHy
     * @Description 查询门店下场地销售次数
     * @Date 20:02 2025/7/7
     * @Param
     **/
    private int getPlaceSales(String id) {
        List<String> ids = appCoursesPriceRulesMapper.selectRuleIdsByCourseId(id);
        int totalOrders = 0;
        if (!ids.isEmpty()) {
            totalOrders = Math.toIntExact(appOrderProductMapper.selectCount(
                    Wrappers.<AppOrderProduct>lambdaQuery()
                            .in(AppOrderProduct::getProductId, ids)
            ));
        }
        return totalOrders;
    }

    /**
     * @Author SheepHy
     * @Description 计算当前课程年销售数
     * @Date 15:47 2025/7/8
     * @Param id 课程id
     * @return int 课程年销售数
     **/
    private int getCourseSales(String id) {
        // 获取当前年份的时间范围（如：2025-01-01 00:00:00 到 2026-01-01 00:00:00）
        LocalDate now = LocalDate.now();
        LocalDateTime startOfYear = now.withDayOfYear(1).atStartOfDay(); // 当前年份第一天
        LocalDateTime endOfYear = startOfYear.plusYears(1); // 下一年第一天

        return Math.toIntExact(appOrderProInfoMapper.selectCount(
                Wrappers.<AppOrderProInfo>lambdaQuery()
                        .eq(AppOrderProInfo::getProductId, id)
                        .eq(AppOrderProInfo::getStatus,0)
                        .eq(AppOrderProInfo::getDelFlag,0)
                        .ge(AppOrderProInfo::getCreateTime, Date.from(startOfYear.atZone(ZoneId.systemDefault()).toInstant())) // >= 2025-01-01
                        .lt(AppOrderProInfo::getCreateTime, Date.from(endOfYear.atZone(ZoneId.systemDefault()).toInstant())) // < 2026-01-01
        ));
    }

    /**
     * @Author SheepHy
     * @Description 计算当前课程销售数
     * @Date 15:47 2025/7/8
     * @Param id 课程id
     * @return int 课程年销售数
     **/
    private int getCourseSalesCount(String id) {
        return Math.toIntExact(appOrderProInfoMapper.selectCount(
                Wrappers.<AppOrderProInfo>lambdaQuery()
                        .eq(AppOrderProInfo::getProductId, id)
        ));
    }

    /**
     * @Author SheepHy
     * @Description 查询用户是否为第一次购买
     * @Date 16:54 2025/7/8
     * @Param
     * @return
     **/
    private int isFirstPurchase(String userId) {
        AppOrder appOrder = appOrderMapper.selectOne(Wrappers.<AppOrder>lambdaQuery()
                .eq(AppOrder::getUpdateBy, userId).last("limit 1"));
        if(null == appOrder){
            return 1;
        }else {
            return 0;
        }
    }

    /**
     * @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;
    }
}