package top.continew.admin.business.service.impl;

import cn.crane4j.core.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import top.continew.admin.business.mapper.DigitalHumanMapper;
import top.continew.admin.business.mapper.EffectMapper;
import top.continew.admin.business.mapper.SubtitleItemMapper;
import top.continew.admin.business.mapper.SubtitleStyleMapper;
import top.continew.admin.business.model.entity.*;
import top.continew.admin.business.model.query.DigitalHumanPageQuery;
import top.continew.admin.business.model.query.DigitalHumanQuery;
import top.continew.admin.business.model.req.DigitalHumanReq;
import top.continew.admin.business.model.resp.DigitalHumanDetailResp;
import top.continew.admin.business.model.resp.DigitalHumanResp;
import top.continew.admin.business.service.DigitalHumanService;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.service.impl.BaseServiceImpl;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 数字人服务实现类
 *
 * @author 王志维
 * @since 2025/12/29
 */
@Service
@RequiredArgsConstructor
public class DigitalHumanServiceImpl extends BaseServiceImpl<DigitalHumanMapper, DigitalHuman, DigitalHumanResp, DigitalHumanDetailResp, DigitalHumanQuery, DigitalHumanReq> implements DigitalHumanService {

    private final DigitalHumanMapper digitalHumanMapper;
    private final SubtitleStyleMapper subtitleStyleMapper;
    private final SubtitleItemMapper subtitleItemMapper;
    private final EffectMapper effectMapper;

    @Override
    public List<DigitalHumanResp> list(DigitalHumanQuery query,
                                       top.continew.starter.extension.crud.model.query.SortQuery sortQuery) {
        LambdaQueryWrapper<DigitalHuman> wrapper = new LambdaQueryWrapper<>();
        if (query.getUserId() != null) {
            wrapper.eq(DigitalHuman::getUserId, query.getUserId());
        }
        if (query.getCopywriting() != null) {
            wrapper.like(DigitalHuman::getCopywriting, query.getCopywriting());
        }
        if (query.getGeneratedVoiceUrl() != null) {
            wrapper.eq(DigitalHuman::getGeneratedVoiceUrl, query.getGeneratedVoiceUrl());
        }
        if (query.getGeneratedFrameImageUrl() != null) {
            wrapper.eq(DigitalHuman::getGeneratedFrameImageUrl, query.getGeneratedFrameImageUrl());
        }
        if (query.getGeneratedVideoUrl() != null) {
            wrapper.eq(DigitalHuman::getGeneratedVideoUrl, query.getGeneratedVideoUrl());
        }

        return digitalHumanMapper.selectList(wrapper).stream().map(this::convertToResp).collect(Collectors.toList());
    }

    @Override
    public top.continew.starter.extension.crud.model.resp.PageResp<DigitalHumanResp> pageList(DigitalHumanQuery query,
                                                                                              DigitalHumanPageQuery pageQuery) {
        LambdaQueryWrapper<DigitalHuman> wrapper = new LambdaQueryWrapper<>();
        //query.setUserId(LoginHelper.getUserId().toString());
        if (query.getUserId() != null) {
            wrapper.eq(DigitalHuman::getUserId, query.getUserId());
        }
        if (query.getCopywriting() != null) {
            wrapper.like(DigitalHuman::getCopywriting, query.getCopywriting());
        }
        if (query.getGeneratedVoiceUrl() != null) {
            wrapper.eq(DigitalHuman::getGeneratedVoiceUrl, query.getGeneratedVoiceUrl());
        }
        if (query.getGeneratedFrameImageUrl() != null) {
            wrapper.eq(DigitalHuman::getGeneratedFrameImageUrl, query.getGeneratedFrameImageUrl());
        }
        if (query.getGeneratedVideoUrl() != null) {
            wrapper.eq(DigitalHuman::getGeneratedVideoUrl, query.getGeneratedVideoUrl());
        }

        wrapper.orderByDesc(DigitalHuman::getCreateTime);

        Page<DigitalHuman> page = new Page<>(pageQuery.getPage(), pageQuery.getSize());
        Page<DigitalHuman> result = digitalHumanMapper.selectPage(page, wrapper);

        PageResp<DigitalHumanResp> pageResp = new PageResp();
        pageResp.setTotal(result.getTotal());
        pageResp.setList(result.getRecords().stream().map(this::convertToResp).toList());
        return pageResp;
    }

    @Override
    public Long add(DigitalHumanReq req) {
        DigitalHuman digitalHuman = new DigitalHuman();
        BeanUtils.copyProperties(req, digitalHuman);
        digitalHuman.setCreateTime(java.time.LocalDateTime.now());
        digitalHuman.setUpdateTime(java.time.LocalDateTime.now());
        digitalHumanMapper.insert(digitalHuman);
        return digitalHuman.getId();
    }

    @Override
    public void delete(List<Long> ids) {
        digitalHumanMapper.deleteBatchIds(ids);
    }

    @Override
    public void update(DigitalHumanReq req, Long id) {
        DigitalHuman digitalHuman = new DigitalHuman();
        BeanUtils.copyProperties(req, digitalHuman);
        digitalHuman.setId(id);
        digitalHuman.setUpdateTime(java.time.LocalDateTime.now());
        digitalHumanMapper.updateById(digitalHuman);
    }

    private DigitalHumanResp convertToResp(DigitalHuman digitalHuman) {
        DigitalHumanResp resp = new DigitalHumanResp();
        BeanUtils.copyProperties(digitalHuman, resp);
        // 处理关联数据
        List<SubtitleStyle> subtitleStyles = subtitleStyleMapper.selectList(new LambdaQueryWrapper<SubtitleStyle>()
            .eq(SubtitleStyle::getDigitalHumanId, digitalHuman.getId()));
        resp.setSubtitleStyle(CollectionUtils.isNotEmpty(subtitleStyles) ? subtitleStyles.get(0) : null);
        resp.setEffects(effectMapper.selectList(new LambdaQueryWrapper<Effect>()
            .eq(Effect::getDigitalHumanId, digitalHuman.getId())));
        resp.setSubtitles(subtitleItemMapper.selectList(new LambdaQueryWrapper<SubtitleItem>()
            .eq(SubtitleItem::getDigitalHumanId, digitalHuman.getId())));
        return resp;
    }
}