package com.vote.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vctgo.common.core.exception.ServiceException;
import com.vctgo.common.core.text.Convert;
import com.vctgo.common.core.utils.ServletUtils;
import com.vctgo.common.core.web.domain.AjaxResult;
import com.vctgo.common.mybatisplus.constant.MybatisPageConstants;
import com.vctgo.system.api.RemoteBranchKindergartenService;
import com.vctgo.system.api.RemoteFileService;
import com.vctgo.system.api.RemoteTeachStaffService;
import com.vctgo.system.api.RemoteUserService;
import com.vctgo.system.api.domain.FileInfo;
import com.vctgo.system.api.domain.SysUser;
import com.vctgo.system.api.domain.dto.SysBranchKindergartenDto;
import com.vctgo.system.api.domain.vo.SysTeachStaffVo;
import com.vctgo.system.api.domain.vo.VoteFileVo;
import com.vote.system.domain.*;
import com.vote.system.domain.appletDto.VoteAppletNewsDto;
import com.vote.system.domain.appletVo.VoteEventAppletnNewsVo;
import com.vote.system.domain.appletVo.VoteEventNewsVo;
import com.vote.system.domain.dto.VoteRegistrationsDto;
import com.vote.system.domain.dto.VoteSubmissionDto;
import com.vote.system.domain.appletVo.VoteUserSubmissionVo;
import com.vote.system.mapper.*;
import com.vote.system.service.VoteEventAppletService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static com.vctgo.common.core.constant.HttpStatus.EXISTING;
import static com.vctgo.common.core.constant.HttpStatus.NO_EXISTING;
import static com.vote.system.util.ConstantUtils.IS_DELETED_0;
import static com.vote.system.util.ConstantUtils.commit_shelves;

/**
 * @author feng
 * @date 2024/9/2
 */
@Service
public class VoteEventAppletServiceImpl implements VoteEventAppletService {

    @Autowired
    private VoteEventNewsMapper voteEventNewsMapper;

    @Autowired
    private VoteUserActionMapper voteUserActionMapper;

    @Autowired
    private VoteEventsMapper voteEventsMapper;

    @Autowired
    private VoteSubmissionMapper voteSubmissionMapper;

    @Autowired
    private VoteEventNewsCarouselsMapper voteEventNewsCarouselsMapper;

    @Autowired
    private VoteRegistrationsMapper voteRegistrationsMapper;

    @Autowired
    private VoteSubmissionFormMapper voteSubmissionFormMapper;

    @Autowired
    private VoteEventWorkSettingsMapper voteEventWorkSettingsMapper;

    @Autowired
    private VoteDataStorageMapper voteDataStorageMapper;

    @Autowired
    private RemoteUserService remoteUserService;

    @Autowired
    private RemoteTeachStaffService remoteTeachStaffService;

    @Autowired
    private RemoteFileService remoteFileService;

    @Autowired
    private RemoteBranchKindergartenService remoteBranchKindergartenService;

    /**
     * 小程序首页 咨询轮播图
     *
     * @return
     */
    @Override
    public VoteEventAppletnNewsVo carouselsList() {
        VoteEventAppletnNewsVo newsVo = new VoteEventAppletnNewsVo();
        LambdaQueryWrapper<VoteEvents> voteEventsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        voteEventsLambdaQueryWrapper.eq(VoteEvents::getIsDeleted, IS_DELETED_0)
                .eq(VoteEvents::getStatus, commit_shelves)
                .orderByDesc(VoteEvents::getCreatedAt);
        List<VoteEvents> events = voteEventsMapper.selectList(voteEventsLambdaQueryWrapper);
        LambdaQueryWrapper<VoteEventNewsCarousels> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(VoteEventNewsCarousels::getSortOrder);
        List<VoteEventNewsCarousels> carousels = voteEventNewsCarouselsMapper.selectList(queryWrapper);
        newsVo.setEventsList(events);
        newsVo.setCarouselsList(carousels);
        return newsVo;
    }


    /**
     * 查看轮播图详情
     *
     * @param id
     * @return
     */
    @Override
    public VoteEventNews getCarousels(Long id) {
        VoteEventNewsCarousels carousels = voteEventNewsCarouselsMapper.selectById(id);
        return voteEventNewsMapper.selectById(carousels.getNewsId());
    }


    /**
     * 查看新闻详情
     *
     * @param id
     * @return
     */
    @Override
    public VoteEvents getEvent(Long id) {
        return voteEventsMapper.selectById(id);
    }

    /**
     * 添加报名
     */
    @Override
    @Transactional
    public AjaxResult signUp(VoteRegistrationsDto voteRegistrationsDto) {
        LambdaQueryWrapper<VoteRegistrations> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VoteRegistrations::getPhone, voteRegistrationsDto.getPhone());
        List<VoteRegistrations> voteRegistrations = voteRegistrationsMapper.selectList(wrapper);
        if (!voteRegistrations.isEmpty()) {
            return AjaxResult.error(EXISTING, "手机号: " + voteRegistrationsDto.getPhone()
                    + "已经报名该活动！");
        }
        Long userId = voteRegistrationsDto.getUid();
//        SysTeachStaffVo data = remoteTeachStaffService.getLocationId(userId).getData();
//        if (data == null) {
//            return AjaxResult.error(NO_EXISTING, "查询不到该用户的所在园所，请先添加园所");
//        }
        voteRegistrationsDto.setLocationId(voteRegistrationsDto.getLocationId());
        voteRegistrationsDto.setCreatedAt(new Date());
        //回填教职工信息
        SysTeachStaffVo update = new SysTeachStaffVo();
        update.setPostValue(voteRegistrationsDto.getPostValue());
        update.setSexValue(voteRegistrationsDto.getSexValue());
        update.setProfessionalValue(voteRegistrationsDto.getProfessionalValue());
        update.setLocationId(voteRegistrationsDto.getLocationId());
        update.setUserId(userId);
        update.setCertificateNumberValue(voteRegistrationsDto.getCertificateNumberValue());
        update.setNameValue(voteRegistrationsDto.getName());
        remoteTeachStaffService.updateStaffByKinderId(update);
        return AjaxResult.success(voteRegistrationsMapper.insert(voteRegistrationsDto));
    }

    /**
     * 类型回显
     */
    @Override
    public List<VoteEventWorkSettings> getWorkType(Long eventId) {
        LambdaQueryWrapper<VoteEventWorkSettings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VoteEventWorkSettings::getEventId, eventId);
        List<VoteEventWorkSettings> voteEventWorkSettings = voteEventWorkSettingsMapper.selectList(wrapper);
        if (voteEventWorkSettings == null || voteEventWorkSettings.size() == 0) {
            throw new RuntimeException("该活动下暂未配置类型信息");
        }
        ArrayList<VoteEventWorkSettings> workSettings = new ArrayList<>();
        voteEventWorkSettings.forEach(item -> {
            VoteEventWorkSettings eventWorkSettings = new VoteEventWorkSettings();
            eventWorkSettings.setId(item.getId());
            eventWorkSettings.setAlias(item.getAlias());
            eventWorkSettings.setEventId(item.getEventId());
            eventWorkSettings.setRoundsId(item.getRoundsId());
            workSettings.add(eventWorkSettings);
        });
        return workSettings;

    }


    /**
     * 提交作品
     */
    @Override
    @Transactional
    public int submission(VoteSubmissionDto voteSubmissionDto) {
        LambdaQueryWrapper<VoteRegistrations> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VoteRegistrations::getUid, voteSubmissionDto.getUserId())
                .eq(VoteRegistrations::getEventId, voteSubmissionDto.getEventId());
        VoteRegistrations voteRegistrations = voteRegistrationsMapper.selectOne(queryWrapper);
        if (voteRegistrations == null) {
            throw new ServiceException("暂未该用户的报名信息，请先报名");
        }
        SysUser user = remoteUserService.getUserInfo(voteSubmissionDto.getUserId()).getData();
        voteSubmissionDto.setCommitName(user.getNickName());
        voteSubmissionDto.setLocationId(voteRegistrations.getLocationId());
        voteSubmissionDto.setCreateAt(new Date());
        return voteSubmissionMapper.insert(voteSubmissionDto);
    }

    /**
     * 查询用户作品
     */
    @Override
    public List<VoteUserSubmissionVo> getUserSubmission(Long userId) {
        // 查询用户提交的所有作品
        List<VoteSubmission> voteSubmissions = voteSubmissionMapper.selectList(
                new LambdaQueryWrapper<VoteSubmission>().eq(VoteSubmission::getUserId, userId).orderByDesc(VoteSubmission::getCreateAt)
        );
        // 如果用户没有提交作品，则直接返回空列表
        if (voteSubmissions.isEmpty()) {
            return Collections.emptyList();
        }
        // 获取所有相关的活动ID对应的活动名称，以减少数据库查询次数
        Map<Long, String> eventNames = voteSubmissions.stream()
                .map(VoteSubmission::getEventId)
                .distinct()
                .collect(Collectors.toMap(
                        eventId -> eventId,
                        eventId -> voteEventsMapper.selectById(eventId).getName()
                ));
        Map<String, String> ageSegmentMap = getStringStringMap();
        // 构建返回的VO对象列表
        return voteSubmissions.stream().map(voteSubmission -> {
            VoteUserSubmissionVo vo = new VoteUserSubmissionVo();
            vo.setWorkStingsId(voteSubmission.getWorkSettingsId());
            vo.setEventId(voteSubmission.getEventId());
            vo.setSubmissionId(voteSubmission.getId());
            vo.setName(voteSubmission.getName());
            vo.setEventsName(eventNames.get(voteSubmission.getEventId()));
            vo.setAgeSegment(processAgeSegment(voteSubmission.getAgeSegment(), ageSegmentMap));
            vo.setMainAuthor(voteSubmission.getMainAuthor());
            vo.setPhone(voteSubmission.getPhone());
            return vo;
        }).collect(Collectors.toList());
    }


    /**
     * 作品详情
     */
    @Override
    public VoteUserSubmissionVo getSubmissionDetail(Long submissionId) {
        VoteUserSubmissionVo vo = new VoteUserSubmissionVo();
        // 查询提交记录
        VoteSubmission submission = voteSubmissionMapper.selectById(submissionId);
        if (submission == null) {
            return vo;  // 如果没有找到相应记录，返回空的 VO
        }
        // 获取作品设置和表单模板
        VoteEventWorkSettings workSettings = voteEventWorkSettingsMapper.selectById(submission.getWorkSettingsId());
        VoteSubmissionForm submissionForm = voteSubmissionFormMapper.selectById(workSettings.getSubmissionTemplateId());
        // 解析表单数据
        String formData = submissionForm.getFormData();
        List<Map<String, Object>> formFields = parseFormData(formData);  // 解析 formData
        // 动态封装字段到 VO 对象中
        for (Map<String, Object> field : formFields) {
            String vModel = (String) field.get("vModel");
            try {
                // 通过反射获取 VoteSubmission 中相应字段的值
                Field submissionField = VoteSubmission.class.getDeclaredField(vModel);
                submissionField.setAccessible(true);  // 设置可访问性
                Object value = submissionField.get(submission);
                // 通过反射将字段值设置到 VoteUserSubmissionVo 中
                Field voField = VoteUserSubmissionVo.class.getDeclaredField(vModel);
                voField.setAccessible(true);  // 设置可访问性
                voField.set(vo, value);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                // 记录错误日志
                System.out.println("字段处理错误: " + vModel + ", 错误信息: " + e.getMessage());
            }
        }
        // 设置基础信息
        vo.setWorkStingsId(submission.getWorkSettingsId());
        vo.setEventId(submission.getEventId());
        vo.setSubmissionId(submissionId);
        // 特殊处理评审状态
        if ("3".equals(submission.getAppraiseStatus())) {
            vo.setRemarks(submission.getRemarks());
        }
        return vo;
    }

    /**
     * 解析表单数据为 List<Map> 形式，并将 vModel 转为驼峰命名
     *
     * @param formData 表单数据 JSON 字符串
     * @return List of Maps with form field details
     */
    private List<Map<String, Object>> parseFormData(String formData) {
        ObjectMapper mapper = new ObjectMapper();
        List<Map<String, Object>> formFields;
        try {
            // 解析 JSON 字符串为 List<Map<String, Object>>
            formFields = mapper.readValue(formData, new TypeReference<List<Map<String, Object>>>() {
            });

            // 将每个 formField 中的 vModel 字段转为驼峰命名
            for (Map<String, Object> field : formFields) {
                String vModel = (String) field.get("vModel");
                field.put("vModel", toCamelCase(vModel));  // 转换为驼峰命名并覆盖原值
            }
        } catch (JsonProcessingException e) {
            // 可以在这里添加异常处理逻辑
            formFields = Collections.emptyList();
        }
        return formFields;
    }

    /**
     * 将下划线命名转为驼峰命名
     *
     * @param str 字段名称
     * @return 转换后的驼峰命名
     */
    private String toCamelCase(String str) {
        StringBuilder result = new StringBuilder();
        boolean nextUpperCase = false;
        for (char c : str.toCharArray()) {
            if (c == '_') {
                nextUpperCase = true;
            } else if (nextUpperCase) {
                result.append(Character.toUpperCase(c));
                nextUpperCase = false;
            } else {
                result.append(c);
            }
        }
        return result.toString();
    }

    /**
     * 新闻列表
     *
     * @param voteAppletNewsDto
     * @return
     */
    @Override
    public IPage<VoteEventNewsVo> getNewsList(VoteAppletNewsDto voteAppletNewsDto) {
        // 构建分页参数
        long pageNum = Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_NUM), 1L);
        long pageSize = Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_SIZE), 10L);
        Page<VoteEventNewsVo> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<VoteEventNews> wrapper = new LambdaQueryWrapper<>();
        if (voteAppletNewsDto.getTitle() != null) {
            wrapper.like(VoteEventNews::getTitle, voteAppletNewsDto.getTitle());
        }
        wrapper.eq(VoteEventNews::getStatus, "1");
        List<VoteEventNews> eventNews = voteEventNewsMapper.selectList(wrapper);
        List<VoteEventNewsVo> eventNewsVoList = eventNews.stream()
                .map(news -> {
                    VoteEventNewsVo vo = new VoteEventNewsVo();
                    // 进行属性映射
                    vo.setNewsId(news.getId());
                    vo.setTitle(news.getTitle());
                    vo.setIsTop(news.getIsTop());
                    vo.setLikeNum(news.getLikeNum());
                    vo.setReadNum(news.getReadNum());
                    vo.setCover(news.getCoverImage());
                    // 如果有更多字段需要转换，在此继续添加
                    return vo;
                }).collect(Collectors.toList());
        // 设置转换后的数据到分页对象中
        page.setRecords(eventNewsVoList);
        page.setTotal(eventNews.size());

        return page;
    }

    /**
     * 点赞人列表
     */
    @Override
    public IPage<String> getLikeRecord(Long newsId) {
        // 构建分页参数
        long pageNum = Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_NUM), 1L);
        long pageSize = Convert.toLong(ServletUtils.getParameterToInt(MybatisPageConstants.PAGE_SIZE), 10L);
        Page<String> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<VoteUserAction> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VoteUserAction::getNewsId, newsId);
        List<VoteUserAction> userActions = voteUserActionMapper.selectList(wrapper);
        if (userActions == null) {
            throw new ServiceException("暂无点赞");
        }
        List<Long> userIds = userActions.stream().map(VoteUserAction::getUserId).collect(Collectors.toList());
        List<String> userName = remoteUserService.getUserName(userIds).getData();
        page.setRecords(userName);
        page.setTotal(userName.size());
        return page;
    }

    /**
     * 新闻点赞
     */
    @Override
    @Transactional
    public int thumbsUp(VoteAppletNewsDto voteAppletNewsDto) {
        // 构建查询条件，校验是否已经点赞
        LambdaQueryWrapper<VoteUserAction> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VoteUserAction::getNewsId, voteAppletNewsDto.getNewsId())
                .eq(VoteUserAction::getUserId, voteAppletNewsDto.getUserId());
        // 查询是否已经存在该用户的点赞记录
        VoteUserAction userAction = voteUserActionMapper.selectOne(wrapper);
        // 如果记录存在，则更新 hasLiked 字段为 true
        if (userAction != null) {
            userAction.setHasLiked(1); // 更新为点赞状态
            updateNewsLikeCount(voteAppletNewsDto.getNewsId());//更新点赞数
            return voteUserActionMapper.updateById(userAction); // 更新记录
        } else {
            // 如果记录不存在，则创建新记录并设置 hasLiked 为 true
            VoteUserAction newUserAction = new VoteUserAction();
            newUserAction.setUserId(voteAppletNewsDto.getUserId())
                    .setNewsId(voteAppletNewsDto.getNewsId())
                    .setHasLiked(1)  // 设置点赞为 true
                    .setHasRead(1);   // 设置已读为 true
            updateNewsLikeCount(voteAppletNewsDto.getNewsId());//更新点赞数
            return voteUserActionMapper.insert(newUserAction); // 插入新记录
        }
    }


    /**
     * 流程状态
     */
    @Override
    public String registrationsStatus(Long userid) {
        LambdaQueryWrapper<VoteRegistrations> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VoteRegistrations::getUid, userid);
        VoteRegistrations selectOne = voteRegistrationsMapper.selectOne(wrapper);
        String userInfo = (selectOne == null) ? "3" : selectOne.getUserInfo();
        return userInfo;
    }

    /**
     * 获取园所列表
     *
     * @return
     */
    @Override
    public Map<Long, String> getBranchKindergarten(VoteRegistrationsDto voteRegistrationsDto) {
        // 调用远程服务获取幼儿园数据
        List<SysBranchKindergartenDto> kindergartenDtos = remoteBranchKindergartenService
                .get(voteRegistrationsDto.getProvinceId(), voteRegistrationsDto.getCityId(), voteRegistrationsDto.getDistrictId())
                .getData();
        // 使用stream 将 id 和 kindergartenName 收集到 Map 中
        return kindergartenDtos.stream()
                .collect(Collectors.toMap(SysBranchKindergartenDto::getId, SysBranchKindergartenDto::getKindergartenName));
    }

    /**
     * 查询作品模板
     */
    @Override
    public VoteSubmissionForm getsSubmissionFormDate(Long workSettingsId) {
        VoteEventWorkSettings voteEventWorkSettings = voteEventWorkSettingsMapper.selectById(workSettingsId);
        return voteSubmissionFormMapper.selectById(voteEventWorkSettings.getSubmissionTemplateId());
    }


    /**
     * 编辑作品
     */
    @Override
    public int updateById(VoteSubmission voteSubmission) {
        voteSubmission.setPromoteStatus("1");
        voteSubmission.setAppraiseStatus("0");
        voteSubmission.setStatus("1");
        voteSubmission.setRemarks("");
        return voteSubmissionMapper.updateById(voteSubmission);
    }

    /**
     * 根据活动查询该用户的报名详情
     */
    @Override
    public VoteRegistrations getRegDetail(Long userId, Long eventId) {
        LambdaQueryWrapper<VoteRegistrations> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VoteRegistrations::getUid, userId)
                .eq(VoteRegistrations::getEventId, eventId);
        return voteRegistrationsMapper.selectOne(queryWrapper);
    }


    /**
     * 修改用户报名信息
     */
    @Override
    public int edit(Long userId, VoteRegistrations voteRegistrations) {
        voteRegistrations.setUserInfo("1");
        voteRegistrations.setUpdatedAt(new Date());
        return voteRegistrationsMapper.updateById(voteRegistrations);
    }


    /**
     * 查看新闻详情
     */
    @Override
    public VoteEventNews getNewsDetails(VoteAppletNewsDto voteAppletNewsDto) {
        if (voteAppletNewsDto.getUserId() == 0) {
            // 未登录用户，直接增加阅读数
            updateNewsReadCount(voteAppletNewsDto.getNewsId());
        } else {
            // 已登录用户，先判断是否已阅读
            Boolean hasRead = checkUserHasRead(voteAppletNewsDto.getUserId(), voteAppletNewsDto.getNewsId());
            // 如果返回值为 null 或者用户未阅读过该新闻
            if (hasRead == null || !hasRead) {
                // 增加阅读数
                updateNewsReadCount(voteAppletNewsDto.getNewsId());

                // 插入用户阅读记录
                VoteUserAction voteUserAction = new VoteUserAction();
                voteUserAction.setUserId(voteAppletNewsDto.getUserId())
                        .setNewsId(voteAppletNewsDto.getNewsId())
                        .setHasRead(1) // 设置为已阅读
                        .setHasLiked(0); // 默认未点赞
                voteUserActionMapper.insert(voteUserAction);
            }
        }
        // 返回新闻详情
        return voteEventNewsMapper.selectById(voteAppletNewsDto.getNewsId());
    }


    //查询用户是否已阅读
    private Boolean checkUserHasRead(Long userId, Long newsId) {
        return voteUserActionMapper.checkUserHasRead(userId, newsId);
    }

    //更新阅读数
    private void updateNewsReadCount(Long newsId) {
        voteEventNewsMapper.updateNewsReadCount(newsId);
    }

    //更新点赞数
    private void updateNewsLikeCount(Long newsId) {
        voteEventNewsMapper.updateNewsLikeCount(newsId);
    }


    private String processAgeSegment(String ageSegment, Map<String, String> ageSegmentMap) {
        if (ageSegment == null) {
            return "";
        }
        return Arrays.stream(ageSegment.split(","))
                .map(ageSegmentMap::get)
                .filter(Objects::nonNull)
                .collect(Collectors.joining(","));
    }

    private static Map<String, String> getStringStringMap() {
        Map<String, String> ageSegmentMap = new HashMap<>();
        ageSegmentMap.put("0", "小班");
        ageSegmentMap.put("1", "中班");
        ageSegmentMap.put("2", "大班");
        ageSegmentMap.put("3", "其他");
        return ageSegmentMap;
    }
}
