package com.lesingle.modules.leai.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lesingle.common.enums.Visibility;
import com.lesingle.modules.leai.enums.LeaiCreationStatus;
import com.lesingle.modules.leai.util.LeaiUtil;
import com.lesingle.modules.sys.entity.SysUser;
import com.lesingle.modules.sys.mapper.SysUserMapper;
import com.lesingle.modules.ugc.entity.UgcWork;
import com.lesingle.modules.ugc.entity.UgcWorkPage;
import com.lesingle.modules.ugc.enums.WorkPublishStatus;
import com.lesingle.modules.ugc.mapper.UgcWorkMapper;
import com.lesingle.modules.ugc.mapper.UgcWorkPageMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * V4.0 状态同步核心服务
 * Webhook 和 B3 对账共用此服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LeaiSyncService implements ILeaiSyncService {

    private final UgcWorkMapper ugcWorkMapper;
    private final UgcWorkPageMapper ugcWorkPageMapper;
    private final LeaiApiClient leaiApiClient;
    private final SysUserMapper sysUserMapper;

    /**
     * V4.0 核心同步逻辑
     * <p>
     * 同步规则：
     * - remoteStatus == -1  → 强制更新（FAILED）
     * - remoteStatus == 2   → 强制更新（PROCESSING 进度变化）
     * - remoteStatus > localStatus → 全量更新（状态前进）
     * - else                → 忽略
     *
     * @param remoteWorkId 乐读派作品ID
     * @param remoteData   远程作品数据（来自 Webhook payload 或 B2/B3 查询结果）
     * @param source       来源标识（用于日志，如 "Webhook[work.status_changed]"）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void syncWork(String remoteWorkId, Map<String, Object> remoteData, String source) {
        int remoteStatus = LeaiUtil.toInt(remoteData.get("status"), 0);
        String phone = LeaiUtil.toString(remoteData.get("phone"), null);

        // 查找本地作品（通过 remoteWorkId）
        UgcWork localWork = findByRemoteWorkId(remoteWorkId);

        if (localWork == null) {
            // ★ 新作品：首次收到此 remoteWorkId，创建本地记录
            insertNewWork(remoteWorkId, remoteData, phone);
            log.info("[{}] 新增作品 remoteWorkId={}, status={}, phone={}", source, remoteWorkId, remoteStatus, phone);
            return;
        }

        int localLeaiStatus = localWork.getLeaiStatus() != null ? localWork.getLeaiStatus() : 0;

        if (remoteStatus == LeaiCreationStatus.FAILED) {
            // ★ FAILED(-1): 创作失败，强制更新
            updateFailed(localWork, remoteData);
            log.info("[{}] 强制更新(FAILED) remoteWorkId={}", source, remoteWorkId);
            return;
        }

        if (remoteStatus == LeaiCreationStatus.PROCESSING) {
            // ★ PROCESSING(2): 创作进行中，强制更新进度
            updateProcessing(localWork, remoteData);
            log.info("[{}] 强制更新(PROCESSING) remoteWorkId={}, progress={}",
                    source, remoteWorkId, remoteData.get("progress"));
            return;
        }

        if (remoteStatus > localLeaiStatus) {
            // ★ 状态前进: 全量更新
            // leaiStatus=3(COMPLETED): pageList 包含图片 URL
            // leaiStatus=4(CATALOGED): title/author 已更新
            // leaiStatus=5(DUBBED): pageList 中 audioUrl 已填充
            updateStatusForward(localWork, remoteData, remoteStatus);
            log.info("[{}] 状态更新 remoteWorkId={}: {} -> {}", source, remoteWorkId, localLeaiStatus, remoteStatus);
            return;
        }

        // 旧数据或重复推送，忽略状态更新
        // 但如果 remoteStatus >= 3 且本地缺少页面数据，需要补充拉取
        if (remoteStatus >= LeaiCreationStatus.COMPLETED && !hasPages(localWork.getId())) {
            log.info("[{}] 状态未变但页面缺失，补充拉取: remoteWorkId={}, status={}", source, remoteWorkId, remoteStatus);
            ensurePagesSaved(localWork.getId(), remoteWorkId, remoteData.get("pageList"));
        } else {
            log.debug("[{}] 跳过 remoteWorkId={}, remote={} <= local={}", source, remoteWorkId, remoteStatus, localLeaiStatus);
        }
    }

    /**
     * 新增作品记录
     */
    private void insertNewWork(String remoteWorkId, Map<String, Object> remoteData, String phone) {
        UgcWork work = new UgcWork();
        work.setRemoteWorkId(remoteWorkId);
        work.setTitle(LeaiUtil.toString(remoteData.get("title"), "未命名作品"));
        int leaiStatus = LeaiUtil.toInt(remoteData.get("status"), LeaiCreationStatus.PENDING);
        work.setLeaiStatus(leaiStatus);
        // 本地发布状态：编目完成(CATALOGED)起视为可入库「未发布」，与 EditInfo 保存/直接发布一致
        work.setStatus(leaiStatus >= LeaiCreationStatus.CATALOGED
                ? WorkPublishStatus.UNPUBLISHED.getValue()
                : WorkPublishStatus.DRAFT.getValue());
        work.setVisibility(Visibility.PRIVATE.getValue());
        work.setIsDeleted(0);
        work.setIsRecommended(false);
        work.setViewCount(0);
        work.setLikeCount(0);
        work.setFavoriteCount(0);
        work.setCommentCount(0);
        work.setShareCount(0);
        work.setProgress(LeaiUtil.toInt(remoteData.get("progress"), 0));
        work.setProgressMessage(LeaiUtil.toString(remoteData.get("progressMessage"), null));
        work.setStyle(LeaiUtil.toString(remoteData.get("style"), null));
        work.setAuthorName(LeaiUtil.toString(remoteData.get("author"), null));
        work.setFailReason(LeaiUtil.toString(remoteData.get("failReason"), null));
        work.setCreateTime(LocalDateTime.now());
        work.setModifyTime(LocalDateTime.now());

        // 设置原始图片，同时同步到封面图
        Object originalImageUrl = remoteData.get("originalImageUrl");
        if (originalImageUrl == null) originalImageUrl = remoteData.get("original_image_url");
        if (originalImageUrl != null) {
            work.setOriginalImageUrl(originalImageUrl.toString());
            work.setCoverUrl(originalImageUrl.toString());
        }

        // 如果远程数据单独提供了封面图，优先使用
        Object coverUrl = remoteData.get("coverUrl");
        if (coverUrl == null) coverUrl = remoteData.get("cover_url");
        if (coverUrl != null) work.setCoverUrl(coverUrl.toString());

        // 兜底：如果 originalImageUrl 没传但 coverUrl 传了，把 coverUrl 也写入 originalImageUrl
        // 当前 leai webhook 大多只传 coverUrl（实际就是用户上传的原图），不传独立的 originalImageUrl 字段
        // 这里兜底让前端 PIP / 详情页「画作原图」卡片能正确展示
        if (originalImageUrl == null && coverUrl != null) {
            work.setOriginalImageUrl(coverUrl.toString());
        }

        // 通过手机号查找用户ID（多租户场景）
        if (phone != null && work.getUserId() == null) {
            Long userId = findUserIdByPhone(phone);
            if (userId != null) {
                work.setUserId(userId);
            } else {
                log.warn("通过手机号未找到对应用户，作品将无法关联用户: remoteWorkId={}, phone={}", remoteWorkId, phone);
            }
        } else if (phone == null) {
            log.warn("Webhook回调中手机号为空，无法关联用户: remoteWorkId={}", remoteWorkId);
        }

        ugcWorkMapper.insert(work);

        // 如果 leaiStatus >= 3，确保页面数据已保存
        if (work.getLeaiStatus() != null && work.getLeaiStatus() >= LeaiCreationStatus.COMPLETED) {
            ensurePagesSaved(work.getId(), remoteWorkId, remoteData.get("pageList"));
        }
    }

    /**
     * 更新失败状态
     */
    private void updateFailed(UgcWork work, Map<String, Object> remoteData) {
        LambdaUpdateWrapper<UgcWork> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(UgcWork::getId, work.getId())
               .set(UgcWork::getLeaiStatus, LeaiCreationStatus.FAILED)
               .set(UgcWork::getFailReason, LeaiUtil.toString(remoteData.get("failReason"), "未知错误"))
               .set(UgcWork::getModifyTime, LocalDateTime.now());
        ugcWorkMapper.update(null, wrapper);
    }

    /**
     * 更新处理中状态（进度变化）
     */
    private void updateProcessing(UgcWork work, Map<String, Object> remoteData) {
        LambdaUpdateWrapper<UgcWork> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(UgcWork::getId, work.getId())
               .set(UgcWork::getLeaiStatus, LeaiCreationStatus.PROCESSING);

        if (remoteData.containsKey("progress")) {
            wrapper.set(UgcWork::getProgress, LeaiUtil.toInt(remoteData.get("progress"), 0));
        }
        if (remoteData.containsKey("progressMessage")) {
            wrapper.set(UgcWork::getProgressMessage, LeaiUtil.toString(remoteData.get("progressMessage"), null));
        }
        // 同步原始图片，同时更新封面图
        Object originalImageUrl = remoteData.get("originalImageUrl");
        if (originalImageUrl == null) originalImageUrl = remoteData.get("original_image_url");
        if (originalImageUrl != null) {
            String imageUrl = originalImageUrl.toString();
            wrapper.set(UgcWork::getOriginalImageUrl, imageUrl);
            wrapper.set(UgcWork::getCoverUrl, imageUrl);
        }
        // 如果远程数据单独提供了封面图，优先使用（覆盖 originalImageUrl 的值）
        Object coverUrl = remoteData.get("coverUrl");
        if (coverUrl == null) coverUrl = remoteData.get("cover_url");
        if (coverUrl != null) {
            wrapper.set(UgcWork::getCoverUrl, coverUrl.toString());
        }
        // 兜底：originalImageUrl 没传但 coverUrl 传了，把 coverUrl 也写入 originalImageUrl
        if (originalImageUrl == null && coverUrl != null) {
            wrapper.set(UgcWork::getOriginalImageUrl, coverUrl.toString());
        }
        wrapper.set(UgcWork::getModifyTime, LocalDateTime.now());

        ugcWorkMapper.update(null, wrapper);
    }

    /**
     * 状态前进：全量更新
     */
    private void updateStatusForward(UgcWork work, Map<String, Object> remoteData, int remoteStatus) {
        // CAS 乐观锁：确保并发安全，只有当前 leaiStatus < remoteStatus 时才更新
        LambdaUpdateWrapper<UgcWork> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(UgcWork::getId, work.getId())
               .lt(UgcWork::getLeaiStatus, remoteStatus)
               .set(UgcWork::getLeaiStatus, remoteStatus);

        // 编目完成(CATALOGED)起且当前仍为 draft → 升为 unpublished（配音为可选步骤）
        if (remoteStatus >= LeaiCreationStatus.CATALOGED
                && WorkPublishStatus.DRAFT.getValue().equals(work.getStatus())) {
            wrapper.set(UgcWork::getStatus, WorkPublishStatus.UNPUBLISHED.getValue());
        }

        // 更新可变字段
        if (remoteData.containsKey("title")) {
            wrapper.set(UgcWork::getTitle, LeaiUtil.toString(remoteData.get("title"), null));
        }
        if (remoteData.containsKey("progress")) {
            wrapper.set(UgcWork::getProgress, LeaiUtil.toInt(remoteData.get("progress"), 0));
        }
        if (remoteData.containsKey("progressMessage")) {
            wrapper.set(UgcWork::getProgressMessage, LeaiUtil.toString(remoteData.get("progressMessage"), null));
        }
        if (remoteData.containsKey("style")) {
            wrapper.set(UgcWork::getStyle, LeaiUtil.toString(remoteData.get("style"), null));
        }
        if (remoteData.containsKey("author")) {
            wrapper.set(UgcWork::getAuthorName, LeaiUtil.toString(remoteData.get("author"), null));
        }
        if (remoteData.containsKey("failReason")) {
            wrapper.set(UgcWork::getFailReason, LeaiUtil.toString(remoteData.get("failReason"), null));
        }
        // 同步原始图片，同时更新封面图
        Object originalImageUrl = remoteData.get("originalImageUrl");
        if (originalImageUrl == null) originalImageUrl = remoteData.get("original_image_url");
        if (originalImageUrl != null) {
            String imageUrl = originalImageUrl.toString();
            wrapper.set(UgcWork::getOriginalImageUrl, imageUrl);
            wrapper.set(UgcWork::getCoverUrl, imageUrl);
        }
        // 如果远程数据单独提供了封面图，优先使用（覆盖 originalImageUrl 的值）
        Object coverUrl = remoteData.get("coverUrl");
        if (coverUrl == null) coverUrl = remoteData.get("cover_url");
        if (coverUrl != null) {
            wrapper.set(UgcWork::getCoverUrl, coverUrl.toString());
        }
        // 兜底：originalImageUrl 没传但 coverUrl 传了，把 coverUrl 也写入 originalImageUrl
        if (originalImageUrl == null && coverUrl != null) {
            wrapper.set(UgcWork::getOriginalImageUrl, coverUrl.toString());
        }

        wrapper.set(UgcWork::getModifyTime, LocalDateTime.now());

        int updated = ugcWorkMapper.update(null, wrapper);
        if (updated == 0) {
            log.warn("CAS乐观锁冲突，跳过更新: remoteWorkId={}, remoteStatus={}", work.getRemoteWorkId(), remoteStatus);
            return;
        }

        // leaiStatus >= 3 时确保页面数据已保存
        if (remoteStatus >= LeaiCreationStatus.COMPLETED) {
            ensurePagesSaved(work.getId(), work.getRemoteWorkId(), remoteData.get("pageList"));
        }
    }

    /**
     * 保存作品页面数据
     * status=3(COMPLETED): pageList 包含 imageUrl
     * status=5(DUBBED): pageList 中 audioUrl 已填充
     */
    @SuppressWarnings("unchecked")
    private void savePageList(Long workId, Object pageListObj) {
        if (pageListObj == null) return;

        List<Map<String, Object>> pageList;
        if (pageListObj instanceof List) {
            pageList = (List<Map<String, Object>>) pageListObj;
        } else {
            return;
        }

        if (pageList.isEmpty()) return;

        // 先删除旧页面数据
        LambdaQueryWrapper<UgcWorkPage> deleteWrapper = new LambdaQueryWrapper<>();
        deleteWrapper.eq(UgcWorkPage::getWorkId, workId);
        ugcWorkPageMapper.delete(deleteWrapper);

        // 插入新页面数据
        for (int i = 0; i < pageList.size(); i++) {
            Map<String, Object> pageData = pageList.get(i);
            UgcWorkPage page = new UgcWorkPage();
            page.setWorkId(workId);
            page.setPageNo(i + 1);
            page.setImageUrl(LeaiUtil.toString(pageData.get("imageUrl"), null));
            page.setText(LeaiUtil.toString(pageData.get("text"), null));
            page.setAudioUrl(LeaiUtil.toString(pageData.get("audioUrl"), null));
            ugcWorkPageMapper.insert(page);
        }

        // 列表封面与前端创作页一致：使用 pageList[0] 插画，而非远程 originalImageUrl/coverUrl 元数据
        String firstCover = LeaiUtil.toString(pageList.get(0).get("imageUrl"), null);
        if (firstCover != null && !firstCover.isEmpty()) {
            LambdaUpdateWrapper<UgcWork> uw = new LambdaUpdateWrapper<>();
            uw.eq(UgcWork::getId, workId)
                    .set(UgcWork::getCoverUrl, firstCover)
                    .set(UgcWork::getModifyTime, LocalDateTime.now());
            ugcWorkMapper.update(null, uw);
        }

        log.info("[乐读派] 保存作品页面数据: workId={}, 页数={}", workId, pageList.size());
    }

    /**
     * 检查本地是否已有页面记录
     */
    private boolean hasPages(Long workId) {
        LambdaQueryWrapper<UgcWorkPage> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UgcWorkPage::getWorkId, workId);
        return ugcWorkPageMapper.selectCount(wrapper) > 0;
    }

    /**
     * 确保页面数据已保存
     * 如果传入的 pageListObj 不为空 → 直接保存
     * 如果为空 → 主动调用 B2 接口拉取完整数据，再保存页面
     */
    private void ensurePagesSaved(Long workId, String remoteWorkId, Object pageListObj) {
        if (pageListObj != null) {
            savePageList(workId, pageListObj);
            return;
        }

        // 本地已有页面数据，无需补充拉取
        if (hasPages(workId)) {
            log.debug("[乐读派] 本地已有页面数据，跳过补充拉取: workId={}", workId);
            return;
        }

        // pageListObj 为空且本地无页面 → 主动拉取完整数据
        log.info("[乐读派] 页面数据缺失，主动拉取完整数据: workId={}, remoteWorkId={}", workId, remoteWorkId);
        Map<String, Object> fullData = leaiApiClient.fetchWorkDetail(remoteWorkId);
        if (fullData != null) {
            savePageList(workId, fullData.get("pageList"));
        } else {
            log.warn("[乐读派] 补充拉取页面数据失败: workId={}, remoteWorkId={}", workId, remoteWorkId);
        }
    }

    /**
     * 通过 remoteWorkId 查找本地作品
     */
    private UgcWork findByRemoteWorkId(String remoteWorkId) {
        LambdaQueryWrapper<UgcWork> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UgcWork::getRemoteWorkId, remoteWorkId)
               .eq(UgcWork::getIsDeleted, 0);
        return ugcWorkMapper.selectOne(wrapper);
    }

    /**
     * 通过手机号查找用户ID
     */
    private Long findUserIdByPhone(String phone) {
        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getPhone, phone)
               .last("LIMIT 1");
        SysUser user = sysUserMapper.selectOne(wrapper);
        return user != null ? user.getId() : null;
    }
}
