package com.gxwebsoft.project.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gxwebsoft.cms.entity.CmsWebsite;
import com.gxwebsoft.cms.service.CmsWebsiteService;
import com.gxwebsoft.project.entity.*;
import com.gxwebsoft.project.mapper.ProjectMapper;
import com.gxwebsoft.project.param.ProjectUserParam;
import com.gxwebsoft.project.service.ProjectCollectionService;
import com.gxwebsoft.project.service.ProjectRenewService;
import com.gxwebsoft.project.service.ProjectService;
import com.gxwebsoft.project.param.ProjectParam;
import com.gxwebsoft.common.core.web.PageParam;
import com.gxwebsoft.common.core.web.PageResult;
import com.gxwebsoft.project.service.ProjectUserService;
import org.springframework.stereotype.Service;

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

/**
 * 应用Service实现
 *
 * @author 科技小王子
 * @since 2025-03-14 16:21:11
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements ProjectService {

  @Resource
  private ProjectService projectService;
  @Resource
  private ProjectUserService projectUserService;
  @Resource
  private ProjectCollectionService projectCollectionService;
  @Resource
  private ProjectRenewService projectRenewService;
  @Resource
  private CmsWebsiteService cmsWebsiteService;

  @Override
  public PageResult<Project> pageRel(ProjectParam param) {
    final String sceneType = param.getSceneType();

    // TODO 特殊场景查询
    if (sceneType != null) {
      param.setUserId(null);
      param.setAppStatus(null);
      param.setAppIds(null);

      List<Project> list = null;
      DateTime date = DateUtil.date();
      final DateTime nextMonth = DateUtil.nextMonth();
      // 获取当前年份的起止时间
      LocalDateTime startOfYear = LocalDateTime.now().withMonth(1).withDayOfMonth(1)
        .withHour(0).withMinute(0).withSecond(0);
      LocalDateTime endOfYear = startOfYear.plusYears(1).minusNanos(1);
      // 去年的起止时间
      LocalDateTime startOfLastYear = LocalDateTime.now().minusYears(1).withMonth(1).withDayOfMonth(1)
        .withHour(0).withMinute(0).withSecond(0);
      LocalDateTime endOfLastYear = startOfLastYear.plusYears(1).minusNanos(1);

      // TODO 我的项目
      if (sceneType.equals("myProject")) {
        param.setUserId(param.getLoginUserId());
        list = listRel(param);
      }

      // TODO 我的参与
      if (sceneType.equals("involved")) {
        final List<ProjectUser> projectUsers = projectUserService.list(new LambdaQueryWrapper<ProjectUser>().eq(ProjectUser::getUserId, param.getLoginUserId()));
        final Set<Integer> collect = projectUsers.stream().map(ProjectUser::getAppId).collect(Collectors.toSet());
        param.setAppIds(collect);
        list = listRel(param);
      }
      // TODO 我的收藏
      if (sceneType.equals("collection")) {
        final List<ProjectCollection> projectCollections = projectCollectionService.list(new LambdaQueryWrapper<ProjectCollection>().eq(ProjectCollection::getUserId, param.getLoginUserId()));
        final Set<Integer> collect = projectCollections.stream().map(ProjectCollection::getAppId).collect(Collectors.toSet());
        param.setAppIds(collect);
        param.setUserId(null);
        list = listRel(param);
        list.forEach(d -> {
          d.setCollection(true);
        });
      }

      if (param.getAppStatus() != null && param.getAppStatus().equals("全部")) {
        param.setAppStatus(null);
      }


      // TODO 近30天可催收的续费总额
      if (sceneType.equals("totalPrice30")) {
        list = list(new LambdaQueryWrapper<Project>()
          .lt(Project::getExpirationTime, nextMonth)
          .gt(Project::getExpirationTime, date)
          .eq(Project::getDeleted, 0)
          .orderByAsc(Project::getExpirationTime)
        );
      }

      // TODO 今年已收续费总额
      if (sceneType.equals("yearTotalPrice")) {
        list = list(new LambdaQueryWrapper<Project>()
          .between(Project::getUpdateTime, startOfYear, endOfYear)
          .eq(Project::getDeleted, 0)
          .orderByDesc(Project::getCreateTime)
        );
      }

      // TODO 去年已收续费列表
      if (sceneType.equals("lastTotalPrice")) {
        list = list(new LambdaQueryWrapper<Project>()
          .between(Project::getUpdateTime, startOfLastYear, endOfLastYear)
          .eq(Project::getDeleted, 0)
          .orderByDesc(Project::getCreateTime)
        );
      }

      // TODO 已流失的续费总额
      if(sceneType.equals("Expired")){
        list = list(new LambdaQueryWrapper<Project>()
          .lt(Project::getExpirationTime, date)
          .eq(Project::getDeleted, 0)
          .eq(Project::getAppStatus,"已上架")
          .eq(Project::getShowExpiration,true)
          .orderByAsc(Project::getExpirationTime)
        );
      }

      // TODO 有效续费总金额
      if (sceneType.equals("effectiveTotalPrice")) {
        list = list(new LambdaQueryWrapper<Project>()
          .gt(Project::getExpirationTime, date)
          .eq(Project::getDeleted, 0)
          .eq(Project::getAppStatus,"已上架")
          .eq(Project::getShowExpiration,true)
          .orderByAsc(Project::getExpirationTime)
        );
      }

      // TODO 全部续费总额
      if (sceneType.equals("AllRenewPrice")) {
        list = list(new LambdaQueryWrapper<Project>()
          .eq(Project::getDeleted, 0)
          .eq(Project::getAppStatus,"已上架")
          .eq(Project::getShowExpiration,true)
          .orderByAsc(Project::getExpirationTime)
        );
      }

      assert list != null;
      return new PageResult<>(getProjectList(list, param.getLoginUserId()), (long) list.size());
    }

    // 常规搜索
    PageParam<Project, ProjectParam> page = new PageParam<>(param);
    page.setDefaultOrder("create_time desc");
    List<Project> list = baseMapper.selectPageRel(page, param);

    return new PageResult<>(getProjectList(list, param.getLoginUserId()), page.getTotal());
  }

  @Override
  public List<Project> listRel(ProjectParam param) {
    List<Project> list = baseMapper.selectListRel(param);
    // 排序
    PageParam<Project, ProjectParam> page = new PageParam<>();
    page.setDefaultOrder("sort_number asc, create_time desc");
    return page.sortRecords(list);
  }

  @Override
  public Project getByIdRel(Integer appId) {
    ProjectParam param = new ProjectParam();
    param.setAppId(appId);
    return param.getOne(baseMapper.selectListRel(param));
  }

  @Override
  public BigDecimal sumMoney(LambdaQueryWrapper<Project> wrapper) {
    return baseMapper.selectSumMoney(wrapper);
  }

  @Override
  public void updateByRenew(ProjectRenew projectRenew) {
    final Project project = projectService.getByIdRel(projectRenew.getAppId());
    if(project.getExpirationTime() != null){
      if (projectRenew.getDays() != null) {
        // 按天续费
        project.setExpirationTime(project.getExpirationTime().plusDays(projectRenew.getDays()));
      } else {
        // 按年续费
        project.setExpirationTime(project.getExpirationTime().plusMonths(12 * projectRenew.getDuration().intValue()));
        // 更新下一年的续费金额
        project.setRenewMoney(projectRenew.getPayPrice());
        project.setShowExpiration(true);
      }
      project.setRenewCount(project.getRenewCount() + 1);

      // 保存到期时间所在的年月日
      final LocalDateTime expirationTime = project.getExpirationTime();
      LocalDate localDate = expirationTime.toLocalDate();
      int year = localDate.getYear();
      int month = localDate.getMonthValue(); // 获取月份，范围是1到12
      int day = localDate.getDayOfMonth(); // 获取日，范围是1到31
      project.setYear(year);
      project.setMonth(month);
      project.setDay(day);
      projectService.updateById(project);
      // 更新明细的到期时间
      projectRenew.setStartTime(expirationTime);
      projectRenew.setEndTime(expirationTime);
      // 同步网站状态
      if (!project.getWebsiteId().equals(0)) {
        final CmsWebsite website = new CmsWebsite();
        website.setVersion(20);
        // 将LocalDateTime转换为Date
        Date expirationDate = Date.from(expirationTime.atZone(ZoneId.systemDefault()).toInstant());
        website.setExpirationTime(expirationDate);
        website.setWebsiteId(project.getWebsiteId());
        cmsWebsiteService.updateByIdAll(website);
      }
    }
    projectRenewService.updateById(projectRenew);
  }

  /**
   * 整理列表数据并返回
   * @return List<Project>
   */
  private List<Project> getProjectList(List<Project> list, Integer loginUserId) {

    final List<ProjectCollection> projectCollections = projectCollectionService.list(new LambdaQueryWrapper<ProjectCollection>().eq(ProjectCollection::getUserId, loginUserId));
    final Set<Integer> collect = projectCollections.stream().map(ProjectCollection::getAppId).collect(Collectors.toSet());

    list.forEach(d -> {
      // 收藏状态
      if (collect.contains(d.getAppId())) {
        d.setCollection(true);
      }
      // 应用成员
      d.setProjectUsers(projectUserService.list(new LambdaQueryWrapper<ProjectUser>().eq(ProjectUser::getAppId, d.getAppId())));
      LocalDateTime now = LocalDateTime.now();
      // 即将过期(30天内过期的)
      d.setSoon(d.getExpirationTime().minusDays(30).compareTo(now));
      // 是否过期 -1已过期 大于0 未过期
      d.setExpired(d.getExpirationTime().compareTo(now));
      // 剩余天数
      d.setExpiredDays(java.time.temporal.ChronoUnit.DAYS.between(now, d.getExpirationTime()));
      // 续费次数
      d.setRenewCount((long) projectRenewService.count(new LambdaQueryWrapper<ProjectRenew>().eq(ProjectRenew::getAppId, d.getAppId()).eq(ProjectRenew::getDeleted, 0)));
    });
    return list;
  }

}
