package com.competition.modules.pub.service;

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.competition.common.exception.BusinessException;
import com.competition.common.result.PageResult;
import com.competition.modules.biz.contest.entity.BizContest;
import com.competition.modules.biz.contest.entity.BizContestRegistration;
import com.competition.modules.biz.contest.entity.BizContestWork;
import com.competition.modules.biz.contest.mapper.ContestMapper;
import com.competition.modules.biz.contest.mapper.ContestRegistrationMapper;
import com.competition.modules.biz.contest.mapper.ContestWorkMapper;
import com.competition.modules.pub.dto.PublicRegisterActivityDto;
import com.competition.modules.ugc.entity.UgcWork;
import com.competition.modules.ugc.entity.UgcWorkPage;
import com.competition.modules.ugc.mapper.UgcWorkMapper;
import com.competition.modules.ugc.mapper.UgcWorkPageMapper;
import com.competition.modules.user.entity.UserChild;
import com.competition.modules.user.mapper.UserChildMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
@RequiredArgsConstructor
public class PublicActivityService {

    private final ContestMapper contestMapper;
    private final ContestRegistrationMapper contestRegistrationMapper;
    private final ContestWorkMapper contestWorkMapper;
    private final UserChildMapper userChildMapper;
    private final UgcWorkMapper ugcWorkMapper;
    private final UgcWorkPageMapper ugcWorkPageMapper;

    /**
     * 活动列表（公开）
     */
    public PageResult<BizContest> listActivities(int page, int pageSize, String keyword, String contestType) {
        LambdaQueryWrapper<BizContest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizContest::getVisibility, "public")
                .eq(BizContest::getContestState, "published");
        if (StringUtils.hasText(keyword)) {
            wrapper.like(BizContest::getContestName, keyword);
        }
        if (StringUtils.hasText(contestType)) {
            wrapper.eq(BizContest::getContestType, contestType);
        }
        wrapper.orderByDesc(BizContest::getCreateTime);

        IPage<BizContest> result = contestMapper.selectPage(new Page<>(page, pageSize), wrapper);
        return PageResult.from(result);
    }

    /**
     * 活动详情
     */
    public Map<String, Object> getActivityDetail(Long id) {
        BizContest contest = contestMapper.selectById(id);
        if (contest == null) {
            throw new BusinessException(404, "活动不存在");
        }

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("id", contest.getId());
        result.put("contestName", contest.getContestName());
        result.put("contestType", contest.getContestType());
        result.put("contestState", contest.getContestState());
        result.put("status", contest.getStatus());
        result.put("visibility", contest.getVisibility());
        result.put("startTime", contest.getStartTime());
        result.put("endTime", contest.getEndTime());
        result.put("coverUrl", contest.getCoverUrl());
        result.put("posterUrl", contest.getPosterUrl());
        result.put("content", contest.getContent());
        result.put("address", contest.getAddress());
        result.put("contactName", contest.getContactName());
        result.put("contactPhone", contest.getContactPhone());
        result.put("contactQrcode", contest.getContactQrcode());
        result.put("organizers", contest.getOrganizers());
        result.put("coOrganizers", contest.getCoOrganizers());
        result.put("sponsors", contest.getSponsors());
        result.put("registerStartTime", contest.getRegisterStartTime());
        result.put("registerEndTime", contest.getRegisterEndTime());
        result.put("registerState", contest.getRegisterState());
        result.put("submitStartTime", contest.getSubmitStartTime());
        result.put("submitEndTime", contest.getSubmitEndTime());
        result.put("submitRule", contest.getSubmitRule());
        result.put("reviewStartTime", contest.getReviewStartTime());
        result.put("reviewEndTime", contest.getReviewEndTime());
        result.put("workType", contest.getWorkType());
        result.put("workRequirement", contest.getWorkRequirement());
        result.put("resultState", contest.getResultState());
        result.put("resultPublishTime", contest.getResultPublishTime());
        return result;
    }

    /**
     * 查询当前用户的报名信息（包含作品提交状态）
     */
    public Map<String, Object> getMyRegistration(Long contestId, Long userId) {
        BizContestRegistration reg = contestRegistrationMapper.selectOne(
                new LambdaQueryWrapper<BizContestRegistration>()
                        .eq(BizContestRegistration::getContestId, contestId)
                        .eq(BizContestRegistration::getUserId, userId)
                        .last("LIMIT 1"));

        if (reg == null) {
            return null;
        }

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("id", reg.getId());
        result.put("contestId", reg.getContestId());
        result.put("userId", reg.getUserId());
        result.put("registrationType", reg.getRegistrationType());
        result.put("registrationState", reg.getRegistrationState());
        result.put("registrationTime", reg.getRegistrationTime());

        // 查询是否已提交作品（只统计最新版本）
        Long workCount = contestWorkMapper.selectCount(
                new LambdaQueryWrapper<BizContestWork>()
                        .eq(BizContestWork::getRegistrationId, reg.getId())
                        .eq(BizContestWork::getIsLatest, true));
        result.put("hasSubmittedWork", workCount > 0);
        result.put("workCount", workCount);

        return result;
    }

    /**
     * 我的报名列表
     */
    public Map<String, Object> getMyRegistrations(Long userId, int page, int pageSize) {
        // 查询报名列表
        LambdaQueryWrapper<BizContestRegistration> regWrapper = new LambdaQueryWrapper<>();
        regWrapper.eq(BizContestRegistration::getUserId, userId)
                .orderByDesc(BizContestRegistration::getRegistrationTime);

        IPage<BizContestRegistration> regPage = contestRegistrationMapper.selectPage(new Page<>(page, pageSize), regWrapper);

        // 获取所有 contestId
        List<Long> contestIds = regPage.getRecords().stream()
                .map(BizContestRegistration::getContestId)
                .distinct()
                .toList();

        // 批量查询活动信息
        Map<Long, BizContest> contestMap = new HashMap<>();
        if (!contestIds.isEmpty()) {
            List<BizContest> contests = contestMapper.selectBatchIds(contestIds);
            for (BizContest contest : contests) {
                contestMap.put(contest.getId(), contest);
            }
        }

        // 查询所有报名对应的作品
        List<BizContestRegistration> registrations = regPage.getRecords();
        List<Long> registrationIds = registrations.stream()
                .map(BizContestRegistration::getId)
                .toList();

        Map<Long, List<BizContestWork>> worksMap = new HashMap<>();
        if (!registrationIds.isEmpty()) {
            LambdaQueryWrapper<BizContestWork> workWrapper = new LambdaQueryWrapper<>();
            workWrapper.in(BizContestWork::getRegistrationId, registrationIds);
            List<BizContestWork> works = contestWorkMapper.selectList(workWrapper);
            for (BizContestWork work : works) {
                worksMap.computeIfAbsent(work.getRegistrationId(), k -> new ArrayList<>()).add(work);
            }
        }

        // 获取所有 childId
        List<Long> childIds = registrations.stream()
                .map(BizContestRegistration::getChildId)
                .filter(Objects::nonNull)
                .distinct()
                .toList();

        // 批量查询子女信息
        Map<Long, UserChild> childMap = new HashMap<>();
        if (!childIds.isEmpty()) {
            List<UserChild> children = userChildMapper.selectBatchIds(childIds);
            for (UserChild child : children) {
                childMap.put(child.getId(), child);
            }
        }

        // 组装返回数据
        List<Map<String, Object>> list = new ArrayList<>();
        for (BizContestRegistration reg : registrations) {
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("id", reg.getId());
            item.put("contestId", reg.getContestId());
            item.put("userId", reg.getUserId());
            item.put("registrationType", reg.getRegistrationType());
            item.put("registrationState", reg.getRegistrationState());
            item.put("registrationTime", reg.getRegistrationTime());
            item.put("participantType", reg.getParticipantType());
            item.put("childId", reg.getChildId());
            item.put("teamId", reg.getTeamId());

            // 关联子女信息
            if (reg.getChildId() != null) {
                UserChild child = childMap.get(reg.getChildId());
                if (child != null) {
                    Map<String, Object> childInfo = new LinkedHashMap<>();
                    childInfo.put("id", child.getId());
                    childInfo.put("name", child.getName());
                    childInfo.put("gender", child.getGender());
                    childInfo.put("grade", child.getGrade());
                    item.put("child", childInfo);
                }
            }

            // 关联活动信息
            BizContest contest = contestMap.get(reg.getContestId());
            if (contest != null) {
                Map<String, Object> contestInfo = new LinkedHashMap<>();
                contestInfo.put("id", contest.getId());
                contestInfo.put("contestName", contest.getContestName());
                contestInfo.put("contestType", contest.getContestType());
                contestInfo.put("coverUrl", contest.getCoverUrl());
                contestInfo.put("posterUrl", contest.getPosterUrl());
                contestInfo.put("startTime", contest.getStartTime());
                contestInfo.put("endTime", contest.getEndTime());
                contestInfo.put("submitStartTime", contest.getSubmitStartTime());
                contestInfo.put("submitEndTime", contest.getSubmitEndTime());
                item.put("contest", contestInfo);
            }

            // 关联作品信息
            List<BizContestWork> works = worksMap.get(reg.getId());
            if (works != null && !works.isEmpty()) {
                List<Map<String, Object>> worksList = new ArrayList<>();
                for (BizContestWork work : works) {
                    Map<String, Object> workInfo = new LinkedHashMap<>();
                    workInfo.put("id", work.getId());
                    workInfo.put("title", work.getTitle());
                    workInfo.put("description", work.getDescription());
                    workInfo.put("previewUrl", work.getPreviewUrl());
                    workInfo.put("previewUrls", work.getPreviewUrls());
                    workInfo.put("attachments", work.getFiles());
                    workInfo.put("createTime", work.getCreateTime());
                    worksList.add(workInfo);
                }
                item.put("works", worksList);
            }

            list.add(item);
        }

        Map<String, Object> result = new LinkedHashMap<>();
        result.put("list", list);
        result.put("total", regPage.getTotal());
        result.put("page", regPage.getCurrent());
        result.put("pageSize", regPage.getSize());

        return result;
    }

    /**
     * 报名活动
     */
    @Transactional
    public BizContestRegistration register(Long contestId, Long userId, Long tenantId, PublicRegisterActivityDto dto) {
        log.info("开始报名活动，contestId: {}, userId: {}, tenantId: {}", contestId, userId, tenantId);

        // 检查是否已报名
        Long existCount = contestRegistrationMapper.selectCount(
                new LambdaQueryWrapper<BizContestRegistration>()
                        .eq(BizContestRegistration::getContestId, contestId)
                        .eq(BizContestRegistration::getUserId, userId));
        if (existCount > 0) {
            throw new BusinessException(400, "您已报名该活动");
        }

        // 检查活动是否存在且可报名
        BizContest contest = contestMapper.selectById(contestId);
        if (contest == null) {
            throw new BusinessException(404, "活动不存在");
        }
        if (!"published".equals(contest.getContestState())) {
            throw new BusinessException(400, "活动未发布");
        }

        BizContestRegistration reg = new BizContestRegistration();
        reg.setContestId(contestId);
        reg.setUserId(userId);
        // 使用活动的授权租户ID（管理端按租户查询报名数据）
        if (contest.getContestTenants() != null && !contest.getContestTenants().isEmpty()) {
            reg.setTenantId(contest.getContestTenants().get(0).longValue());
        } else {
            reg.setTenantId(tenantId);
        }
        reg.setRegistrationType(contest.getContestType());
        reg.setParticipantType(dto.getParticipantType() != null ? dto.getParticipantType() : "self");
        reg.setChildId(dto.getChildId());
        reg.setTeamId(dto.getTeamId());
        reg.setRegistrationState(Boolean.TRUE.equals(contest.getRequireAudit()) ? "pending" : "passed");
        reg.setRegistrationTime(LocalDateTime.now());
        // 设置必填字段
        reg.setRegistrant(userId.intValue());
        reg.setAccountNo("user_" + userId);
        reg.setAccountName("user_" + userId);

        log.info("保存报名记录：{}", reg);
        contestRegistrationMapper.insert(reg);
        log.info("报名成功，ID: {}", reg.getId());
        return reg;
    }

    /**
     * 提交作品
     */
    @Transactional
    public BizContestWork submitWork(Long contestId, Long userId, Long tenantId, Map<String, Object> dto) {
        // 检查报名状态（区分不同状态给出明确提示）
        BizContestRegistration anyReg = contestRegistrationMapper.selectOne(
                new LambdaQueryWrapper<BizContestRegistration>()
                        .eq(BizContestRegistration::getContestId, contestId)
                        .eq(BizContestRegistration::getUserId, userId)
                        .last("LIMIT 1"));
        if (anyReg == null) {
            throw new BusinessException(400, "您尚未报名该活动，请先报名");
        }
        if (!"passed".equals(anyReg.getRegistrationState())) {
            String state = anyReg.getRegistrationState();
            String msg = switch (state) {
                case "pending" -> "报名审核中，请等待审核通过后再提交作品";
                case "rejected" -> "报名已被拒绝，无法提交作品";
                case "withdrawn" -> "报名已撤回，请重新报名";
                default -> "报名状态异常（" + state + "），无法提交作品";
            };
            throw new BusinessException(400, msg);
        }
        BizContestRegistration reg = anyReg;

        // 查询活动提交规则
        BizContest contest = contestMapper.selectById(contestId);
        String submitRule = contest != null ? contest.getSubmitRule() : "once";

        // 查询已有作品
        BizContestWork existingWork = contestWorkMapper.selectOne(
                new LambdaQueryWrapper<BizContestWork>()
                        .eq(BizContestWork::getContestId, contestId)
                        .eq(BizContestWork::getRegistrationId, reg.getId())
                        .eq(BizContestWork::getIsLatest, true)
                        .orderByDesc(BizContestWork::getVersion)
                        .last("LIMIT 1"));

        if (existingWork != null) {
            if ("once".equals(submitRule)) {
                throw new BusinessException(400, "该活动仅允许提交一次作品");
            }
            // resubmit 模式：将旧作品标记为非最新
            existingWork.setIsLatest(false);
            contestWorkMapper.updateById(existingWork);
        }

        int nextVersion = (existingWork != null) ? existingWork.getVersion() + 1 : 1;

        BizContestWork work = new BizContestWork();
        work.setContestId(contestId);
        work.setRegistrationId(reg.getId());
        // 使用报名记录的租户ID（已在 register 时设置为活动的租户，确保管理端可见）
        work.setTenantId(reg.getTenantId());
        work.setSubmitterUserId(userId);
        work.setStatus("submitted");
        work.setSubmitTime(LocalDateTime.now());
        work.setVersion(nextVersion);
        work.setIsLatest(true);

        // 从作品库选择作品提交（快照复制）
        if (dto.get("userWorkId") != null) {
            Long userWorkId = Long.valueOf(dto.get("userWorkId").toString());
            work.setUserWorkId(userWorkId);

            // 查询用户作品
            UgcWork ugcWork = ugcWorkMapper.selectById(userWorkId);
            if (ugcWork == null || ugcWork.getIsDeleted() == 1) {
                throw new BusinessException(404, "作品不存在");
            }
            if (!ugcWork.getUserId().equals(userId)) {
                throw new BusinessException(403, "无权使用该作品");
            }
            if ("rejected".equals(ugcWork.getStatus()) || "taken_down".equals(ugcWork.getStatus())) {
                throw new BusinessException(400, "该作品状态不可提交");
            }

            // 查询绘本分页
            List<UgcWorkPage> pages = ugcWorkPageMapper.selectList(
                    new LambdaQueryWrapper<UgcWorkPage>()
                            .eq(UgcWorkPage::getWorkId, userWorkId)
                            .orderByAsc(UgcWorkPage::getPageNo));

            // 复制快照字段
            work.setTitle(ugcWork.getTitle());
            work.setDescription(ugcWork.getDescription());
            work.setPreviewUrl(ugcWork.getCoverUrl());
            work.setAiModelMeta(ugcWork.getAiMeta());

            // previewUrls = 所有页面图片
            List<String> previewUrls = pages.stream()
                    .map(UgcWorkPage::getImageUrl)
                    .filter(Objects::nonNull)
                    .toList();
            work.setPreviewUrls(previewUrls);

            // files = 分页完整快照
            List<Map<String, Object>> filesSnapshot = pages.stream()
                    .map(p -> {
                        Map<String, Object> m = new LinkedHashMap<>();
                        m.put("pageNo", p.getPageNo());
                        m.put("imageUrl", p.getImageUrl());
                        m.put("text", p.getText());
                        m.put("audioUrl", p.getAudioUrl());
                        return m;
                    })
                    .toList();
            work.setFiles(filesSnapshot);
        } else {
            // 旧逻辑：直接上传
            work.setTitle((String) dto.get("title"));
            work.setDescription((String) dto.get("description"));
            work.setFiles(dto.get("files"));
        }
        contestWorkMapper.insert(work);
        return work;
    }
}
