package com.starry.admin.modules.clerk.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
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.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.clerk.enums.ClerkMediaUsage;
import com.starry.admin.modules.clerk.mapper.PlayClerkDataReviewInfoMapper;
import com.starry.admin.modules.clerk.module.entity.PlayClerkDataReviewInfoEntity;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
import com.starry.admin.modules.clerk.module.enums.ClerkDataType;
import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewQueryVo;
import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewReturnVo;
import com.starry.admin.modules.clerk.module.vo.PlayClerkDataReviewStateEditVo;
import com.starry.admin.modules.clerk.service.IPlayClerkDataReviewInfoService;
import com.starry.admin.modules.clerk.service.IPlayClerkMediaAssetService;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.media.entity.PlayMediaEntity;
import com.starry.admin.modules.media.enums.MediaKind;
import com.starry.admin.modules.media.enums.MediaOwnerType;
import com.starry.admin.modules.media.enums.MediaStatus;
import com.starry.admin.modules.media.service.IPlayMediaService;
import com.starry.common.enums.ClerkReviewState;
import com.starry.common.utils.IdUtils;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;

/**
 * 店员资料审核Service业务层处理
 *
 * @author admin
 * @since 2024-05-19
 */
@Service
public class PlayClerkDataReviewInfoServiceImpl
        extends
            ServiceImpl<PlayClerkDataReviewInfoMapper, PlayClerkDataReviewInfoEntity>
        implements
            IPlayClerkDataReviewInfoService {
    @Resource
    private PlayClerkDataReviewInfoMapper playClerkDataReviewInfoMapper;

    @Resource
    private IPlayClerkUserInfoService playClerkUserInfoService;

    @Resource
    private IPlayClerkMediaAssetService clerkMediaAssetService;

    @Resource
    private IPlayMediaService mediaService;

    /**
     * 查询店员资料审核
     *
     * @param id
     *            店员资料审核主键
     * @return 店员资料审核
     */
    @Override
    public PlayClerkDataReviewInfoEntity selectPlayClerkDataReviewInfoById(String id) {
        LambdaQueryWrapper<PlayClerkDataReviewInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PlayClerkDataReviewInfoEntity::getId, id);
        PlayClerkDataReviewInfoEntity entity = this.baseMapper.selectOne(queryWrapper);
        if (entity == null) {
            throw new CustomException("对象不存在");
        }
        return entity;
    }

    @Override
    public List<PlayClerkDataReviewInfoEntity> queryByClerkId(String clerkId, String reviewState) {
        LambdaQueryWrapper<PlayClerkDataReviewInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PlayClerkDataReviewInfoEntity::getClerkId, clerkId);
        queryWrapper.eq(PlayClerkDataReviewInfoEntity::getReviewState, reviewState);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public PlayClerkDataReviewInfoEntity queryByClerkId(String clerkId, String dataType, String reviewState) {
        LambdaQueryWrapper<PlayClerkDataReviewInfoEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PlayClerkDataReviewInfoEntity::getClerkId, clerkId);
        queryWrapper.eq(PlayClerkDataReviewInfoEntity::getReviewState, reviewState);
        queryWrapper.eq(PlayClerkDataReviewInfoEntity::getDataType, dataType);
        return this.baseMapper.selectOne(queryWrapper);
    }

    /**
     * 查询店员资料审核列表
     *
     * @param vo
     *            店员资料审核
     * @return 店员资料审核
     */
    @Override
    public IPage<PlayClerkDataReviewReturnVo> selectByPage(PlayClerkDataReviewQueryVo vo) {
        MPJLambdaWrapper<PlayClerkDataReviewInfoEntity> lambdaQueryWrapper = new MPJLambdaWrapper<>();
        lambdaQueryWrapper.orderByDesc(PlayClerkDataReviewInfoEntity::getAddTime);
        lambdaQueryWrapper.selectAll(PlayClerkDataReviewInfoEntity.class);
        // 店员表
        lambdaQueryWrapper.selectAs(PlayClerkUserInfoEntity::getAvatar, "clerkAvatar")
                .selectAs(PlayClerkUserInfoEntity::getNickname, "clerkNickname");
        lambdaQueryWrapper.leftJoin(PlayClerkUserInfoEntity.class, PlayClerkUserInfoEntity::getId,
                PlayClerkUserReviewInfoEntity::getClerkId);
        if (StrUtil.isNotBlank(vo.getClerkId())) {
            lambdaQueryWrapper.eq(PlayClerkDataReviewInfoEntity::getClerkId, vo.getClerkId());
        }
        if (StrUtil.isNotBlank(vo.getDataType())) {
            lambdaQueryWrapper.eq(PlayClerkDataReviewInfoEntity::getDataType, vo.getDataType());
        }
        if (StrUtil.isNotBlank(vo.getReviewState())) {
            lambdaQueryWrapper.like(PlayClerkDataReviewInfoEntity::getReviewState, vo.getReviewState());
        }
        if (vo.getAddTime() != null && vo.getAddTime().size() == 2) {
            lambdaQueryWrapper.between(PlayClerkDataReviewInfoEntity::getAddTime, vo.getAddTime().get(0),
                    vo.getAddTime().get(1));
        }
        IPage<PlayClerkDataReviewReturnVo> page = this.baseMapper.selectJoinPage(
                new Page<>(vo.getPageNum(), vo.getPageSize()), PlayClerkDataReviewReturnVo.class,
                lambdaQueryWrapper);
        enrichDataContentWithMediaPreview(page);
        return page;
    }

    /**
     * 新增店员资料审核
     *
     * @param playClerkDataReviewInfo
     *            店员资料审核
     * @return 结果
     */
    @Override
    public boolean create(PlayClerkDataReviewInfoEntity playClerkDataReviewInfo) {
        if (StrUtil.isBlankIfStr(playClerkDataReviewInfo.getId())) {
            playClerkDataReviewInfo.setId(IdUtils.getUuid());
        }
        if (StrUtil.isBlankIfStr(playClerkDataReviewInfo.getAddTime())) {
            playClerkDataReviewInfo.setAddTime(LocalDateTime.now());
        }
        return save(playClerkDataReviewInfo);
    }

    /**
     * 为头像 / 相册审核记录补充可预览的 URL。
     *
     * <p>dataContent 中现在可能是媒资 ID（mediaId）或历史 URL，这里做一次向前兼容：
     * <ul>
     *   <li>如果是 mediaId，则解析到 play_media 记录，并返回封面或原始 URL；</li>
     *   <li>如果查不到媒资，则保留原值。</li>
     * </ul>
     * 这样 PC 端审核页面始终可以正确预览图片/视频。</p>
     */
    private void enrichDataContentWithMediaPreview(IPage<PlayClerkDataReviewReturnVo> page) {
        if (page == null || page.getRecords() == null || page.getRecords().isEmpty()) {
            return;
        }
        for (PlayClerkDataReviewReturnVo row : page.getRecords()) {
            ClerkDataType type = row.getDataTypeEnum();
            if (type == null) {
                continue;
            }
            if (type == ClerkDataType.AVATAR || type == ClerkDataType.PHOTO_ALBUM) {
                List<String> content = row.getDataContent();
                if (CollectionUtil.isEmpty(content)) {
                    continue;
                }
                List<String> previewUrls = new ArrayList<>();
                List<String> videoUrls = new ArrayList<>();
                for (String value : content) {
                    if (StrUtil.isBlank(value)) {
                        continue;
                    }
                    MediaPreviewPair pair = resolvePreviewPair(value);
                    if (pair == null || StrUtil.isBlank(pair.getPreviewUrl())) {
                        continue;
                    }
                    previewUrls.add(pair.getPreviewUrl());
                    videoUrls.add(pair.getVideoUrl());
                }
                row.setDataContent(previewUrls);
                row.setMediaVideoUrls(videoUrls);
            }
        }
    }

    private MediaPreviewPair resolvePreviewPair(String value) {
        if (StrUtil.isBlank(value)) {
            return null;
        }
        PlayMediaEntity media = mediaService.getById(value);
        if (media == null) {
            MediaPreviewPair fallback = new MediaPreviewPair();
            fallback.setPreviewUrl(value);
            fallback.setVideoUrl(null);
            return fallback;
        }
        MediaPreviewPair pair = new MediaPreviewPair();
        if (MediaKind.VIDEO.getCode().equals(media.getKind())) {
            String coverUrl = StrUtil.isNotBlank(media.getCoverUrl()) ? media.getCoverUrl() : media.getUrl();
            pair.setPreviewUrl(coverUrl);
            pair.setVideoUrl(media.getUrl());
        } else {
            pair.setPreviewUrl(media.getUrl());
            pair.setVideoUrl(null);
        }
        return pair;
    }

    @Override
    public void updateDataReviewState(PlayClerkDataReviewStateEditVo vo) {
        PlayClerkDataReviewInfoEntity entity = this.selectPlayClerkDataReviewInfoById(vo.getId());
        ClerkReviewState reviewState = vo.getReviewState();
        entity.setReviewState(reviewState != null ? reviewState.getCode() : null);
        entity.setReviewCon(vo.getReviewCon());
        entity.setReviewTime(vo.getReviewTime() != null ? vo.getReviewTime() : LocalDateTime.now());
        this.update(entity);
        if (ClerkReviewState.APPROVED.equals(reviewState)) {
            PlayClerkUserInfoEntity userInfo = new PlayClerkUserInfoEntity();
            userInfo.setId(entity.getClerkId());
            if ("0".equals(entity.getDataType())) {
                userInfo.setNickname(entity.getDataContent().isEmpty() ? null : entity.getDataContent().get(0));
            }
            if ("1".equals(entity.getDataType())) {
                userInfo.setAvatar(entity.getDataContent().get(0));
            }
            if ("2".equals(entity.getDataType())) {
                userInfo.setAlbum(new ArrayList<>());
                synchronizeApprovedAlbumMedia(entity);
            }
            if ("3".equals(entity.getDataType())) {
                userInfo.setAudio(entity.getDataContent().get(0));
            }
            if ("4".equals(entity.getDataType())) {
                userInfo.setSex(entity.getDataContent().isEmpty() ? null : entity.getDataContent().get(0));
            }
            playClerkUserInfoService.update(userInfo);
        }
    }

    private void synchronizeApprovedAlbumMedia(PlayClerkDataReviewInfoEntity reviewInfo) {
        PlayClerkUserInfoEntity clerkInfo = playClerkUserInfoService.getById(reviewInfo.getClerkId());
        if (clerkInfo == null) {
            throw new CustomException("店员信息不存在，无法同步媒资");
        }

        List<String> rawContent = reviewInfo.getDataContent();
        List<String> sanitized = CollectionUtil.isEmpty(rawContent)
                ? Collections.emptyList()
                : rawContent.stream().filter(StrUtil::isNotBlank).map(String::trim).distinct()
                        .collect(Collectors.toList());

        List<String> resolvedMediaIds = new ArrayList<>();
        for (String value : sanitized) {
            PlayMediaEntity media = resolveMediaEntity(clerkInfo, value);
            if (media == null) {
                continue;
            }
            clerkMediaAssetService.linkDraftAsset(clerkInfo.getTenantId(), clerkInfo.getId(), media.getId(),
                    ClerkMediaUsage.PROFILE);
            resolvedMediaIds.add(media.getId());
        }

        clerkMediaAssetService.applyReviewDecision(clerkInfo.getId(), ClerkMediaUsage.PROFILE, resolvedMediaIds,
                reviewInfo.getId(), reviewInfo.getReviewCon());
    }

    private PlayMediaEntity resolveMediaEntity(PlayClerkUserInfoEntity clerkInfo, String value) {
        if (StrUtil.isBlank(value)) {
            return null;
        }
        PlayMediaEntity media = mediaService.getById(value);
        if (media != null) {
            return media;
        }
        media = mediaService.lambdaQuery()
                .eq(PlayMediaEntity::getOwnerType, MediaOwnerType.CLERK)
                .eq(PlayMediaEntity::getOwnerId, clerkInfo.getId())
                .eq(PlayMediaEntity::getUrl, value)
                .last("limit 1")
                .one();
        if (media != null) {
            return media;
        }
        return createMediaFromLegacyUrl(clerkInfo, value);
    }

    private PlayMediaEntity createMediaFromLegacyUrl(PlayClerkUserInfoEntity clerkInfo, String url) {
        PlayMediaEntity media = new PlayMediaEntity();
        media.setId(IdUtils.getUuid());
        media.setTenantId(clerkInfo.getTenantId());
        media.setOwnerType(MediaOwnerType.CLERK);
        media.setOwnerId(clerkInfo.getId());
        media.setKind(MediaKind.IMAGE.getCode());
        media.setStatus(MediaStatus.READY.getCode());
        media.setUrl(url);
        Map<String, Object> metadata = new HashMap<>();
        metadata.put("legacySource", "album_review");
        media.setMetadata(metadata);
        mediaService.normalizeAndSave(media);
        media.setStatus(MediaStatus.READY.getCode());
        mediaService.updateById(media);
        return media;
    }

    /**
     * 修改店员资料审核
     *
     * @param playClerkDataReviewInfo
     *            店员资料审核
     * @return 结果
     */
    @Override
    public boolean update(PlayClerkDataReviewInfoEntity playClerkDataReviewInfo) {
        return updateById(playClerkDataReviewInfo);
    }

    /**
     * 批量删除店员资料审核
     *
     * @param ids
     *            需要删除的店员资料审核主键
     * @return 结果
     */
    @Override
    public int deletePlayClerkDataReviewInfoByIds(String[] ids) {
        return playClerkDataReviewInfoMapper.deleteBatchIds(Arrays.asList(ids));
    }

    /**
     * 删除店员资料审核信息
     *
     * @param id
     *            店员资料审核主键
     * @return 结果
     */
    @Override
    public int deletePlayClerkDataReviewInfoById(String id) {
        return playClerkDataReviewInfoMapper.deleteById(id);
    }

    /**
     * 简单的预览地址 / 视频地址对，避免在主体逻辑中使用 Map 或魔法下标。
     */
    private static class MediaPreviewPair {
        private String previewUrl;
        private String videoUrl;

        String getPreviewUrl() {
            return previewUrl;
        }

        void setPreviewUrl(String previewUrl) {
            this.previewUrl = previewUrl;
        }

        String getVideoUrl() {
            return videoUrl;
        }

        void setVideoUrl(String videoUrl) {
            this.videoUrl = videoUrl;
        }
    }
}
