package com.backendsys.modules.crt.service.impl;

import com.backendsys.exception.CustException;
import com.backendsys.modules.common.config.security.enums.SecurityEnum;
import com.backendsys.modules.common.config.security.utils.SecurityUtil;
import com.backendsys.modules.common.enums.MatchType;
import com.backendsys.modules.crt.dao.CrtDramaProjectDao;
import com.backendsys.modules.crt.dao.CrtDramaProjectSettingsDao;
import com.backendsys.modules.crt.dao.CrtDramaProjectStoryboardDao;
import com.backendsys.modules.crt.entity.CrtDramaProject;
import com.backendsys.modules.crt.entity.CrtDramaProjectSettings;
import com.backendsys.modules.crt.entity.CrtDramaProjectStoryboard;
import com.backendsys.modules.crt.enums.AspectRatioEnums;
import com.backendsys.modules.crt.enums.ProjectSettingTypeEnums;
import com.backendsys.modules.crt.service.CrtDramaProjectService;
import com.backendsys.utils.response.PageEntity;
import com.backendsys.utils.response.PageInfoResult;
import com.backendsys.utils.v2.PageUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Service
public class CrtDramaProjectServiceImpl implements CrtDramaProjectService {

    @Autowired
    private SecurityUtil securityUtil;
    @Autowired
    private CrtDramaProjectDao crtDramaProjectDao;
    @Autowired
    private CrtDramaProjectSettingsDao crtDramaProjectSettingsDao;
    @Autowired
    private CrtDramaProjectStoryboardDao crtDramaProjectStoryboardDao;

    // 获取短剧创作-项目列表
    @Override
    public PageEntity selectCrtDramaProjectList(CrtDramaProject crtDramaProject) {
        PageUtils.startPage();  // 分页
        List<Map<String, Object>> list = crtDramaProjectDao.selectCrtDramaProjectList(crtDramaProject);
        return new PageInfoResult(list).toEntity();
    }

    /**
     * 创建短剧创作-项目
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> createCrtDramaProject(CrtDramaProject crtDramaProject) {

        // 创建项目 (此处不判断LoRA有效性，在调用的时候再判断)
        crtDramaProjectDao.insert(crtDramaProject);

        // 创建项目配置 (生图、生视频配置)
        Long project_id = crtDramaProject.getId();
        CrtDramaProjectSettings settings_image = new CrtDramaProjectSettings();
        settings_image.setDrama_project_id(project_id);
        settings_image.setDrama_project_setting_type(ProjectSettingTypeEnums.GENERATE_IMAGE.getKey());   // 项目配置类型
        settings_image.setAspect_ratio(AspectRatioEnums.RATIO_16_9.getKey());                            // 画面比例
        settings_image.setModel_id(1L);
        settings_image.setLora_style_id(1L);
        settings_image.setLora_style_strength(1.0f);
        crtDramaProjectSettingsDao.insert(settings_image);

        CrtDramaProjectSettings settings_video = new CrtDramaProjectSettings();
        settings_video.setDrama_project_id(project_id);
        settings_video.setDrama_project_setting_type(ProjectSettingTypeEnums.GENERATE_VIDEO.getKey());   // 项目配置类型
        settings_video.setAspect_ratio(AspectRatioEnums.RATIO_16_9.getKey());                            // 画面比例
        crtDramaProjectSettingsDao.insert(settings_video);

        return Map.of("drama_project_id", project_id);
    }

    /**
     * 编辑项目
     */
    @Override
    public Map<String, Object> updateCrtDramaProject(CrtDramaProject crtDramaProject) {

        Long project_id = crtDramaProject.getDrama_project_id();
        CrtDramaProject projectDetail = crtDramaProjectDao.selectById(project_id);
        if (projectDetail == null)  throw new CustException("项目不存在");

        // 是否 [项目] 拥有者，权限：
        // - 编辑自己的 (需 36.1.4.1 权限)
        // - 编辑自己及他人的 (需要 36.1.4 权限或超级管理员)
        Boolean isOwner = projectDetail.getUser_id() == SecurityUtil.getUserId();
        if (isOwner && !securityUtil.hasPermissions(Arrays.asList("36.1.4", "36.1.4.1"), MatchType.OR)) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        if (!isOwner && !securityUtil.hasPermission("36.1.4")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        // ---------------------------------------------------------------------------

        // [DB] 更新项目
        crtDramaProjectDao.update(crtDramaProject, new LambdaQueryWrapper<CrtDramaProject>()
                .eq(CrtDramaProject::getId, crtDramaProject.getDrama_project_id()));
        return Map.of("drama_project_id", crtDramaProject.getDrama_project_id());

    }




    /**
     * 编辑项目生图/生视频配置
     */
    @Override
    public Map<String, Object> updateDramaProjectSettings(CrtDramaProjectSettings crtDramaProjectSettings) {

        Long project_id = crtDramaProjectSettings.getDrama_project_id();
        CrtDramaProject projectDetail = crtDramaProjectDao.selectById(project_id);
        if (projectDetail == null)  throw new CustException("项目不存在");

        // 是否 [项目] 拥有者，权限：
        // - 编辑自己的 (需 36.2.3.1 权限)
        // - 编辑自己及他人的 (需要 36.2.3 权限或超级管理员)
        Boolean isOwner = projectDetail.getUser_id() == SecurityUtil.getUserId();
        if (isOwner && !securityUtil.hasPermissions(Arrays.asList("36.2.3", "36.2.3.1"), MatchType.OR)) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        if (!isOwner && !securityUtil.hasPermission("36.2.3")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        // ---------------------------------------------------------------------------

        // 项目配置类型 (1: 生图配置, 2: 生视频配置)
        Integer setting_type = crtDramaProjectSettings.getDrama_project_setting_type();

        // 查询条件
        LambdaQueryWrapper<CrtDramaProjectSettings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CrtDramaProjectSettings::getDrama_project_id, crtDramaProjectSettings.getDrama_project_id());
        wrapper.eq(CrtDramaProjectSettings::getDrama_project_setting_type, setting_type);

        // 更新字段
        CrtDramaProjectSettings entity = new CrtDramaProjectSettings();
        entity.setAspect_ratio(crtDramaProjectSettings.getAspect_ratio());

        // 生图配置：基础模型、风格LoRA、风格LoRA强度
        if (setting_type == 1) {
            entity.setModel_id(crtDramaProjectSettings.getModel_id());
            entity.setLora_style_id(crtDramaProjectSettings.getLora_style_id());
            entity.setLora_style_strength(crtDramaProjectSettings.getLora_style_strength());
        }

        crtDramaProjectSettingsDao.update(entity, wrapper);
        return Map.of("drama_project_id", crtDramaProjectSettings.getDrama_project_id());

    }


    /**
     * 删除项目
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> deleteCrtDramaProject(CrtDramaProject crtDramaProject) {

        Long project_id = crtDramaProject.getDrama_project_id();
        CrtDramaProject projectDetail = crtDramaProjectDao.selectById(project_id);
        if (projectDetail == null)  throw new CustException("项目不存在");

        // 是否 [项目] 拥有者，权限：
        // - 编辑自己的 (需 36.1.6.1 权限)
        // - 编辑自己及他人的 (需要 36.1.6 权限或超级管理员)
        Boolean isOwner = projectDetail.getUser_id() == SecurityUtil.getUserId();
        if (isOwner && !securityUtil.hasPermissions(Arrays.asList("36.1.6", "36.1.6.1"), MatchType.OR)) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        if (!isOwner && !securityUtil.hasPermission("36.1.6")) {
            throw new CustException(SecurityEnum.NOAUTH);
        }
        // ---------------------------------------------------------------------------

        // [DB] 删除 [项目]，同时删除 [项目配置]、[项目分集/分镜]
        crtDramaProjectDao.delete(new LambdaQueryWrapper<CrtDramaProject>().eq(CrtDramaProject::getId, project_id));
        crtDramaProjectSettingsDao.delete(new LambdaQueryWrapper<CrtDramaProjectSettings>()
            .eq(CrtDramaProjectSettings::getDrama_project_id, project_id));
        crtDramaProjectStoryboardDao.delete(new LambdaQueryWrapper<CrtDramaProjectStoryboard>()
            .eq(CrtDramaProjectStoryboard::getDrama_project_id, project_id));

        return Map.of("drama_project_id", crtDramaProject.getDrama_project_id());
    }

}
