package io.renren.modules.sys.controller.algs;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.minio.errors.*;
import io.renren.common.annotation.SysLog;
import io.renren.common.utils.Constant;
import io.renren.common.utils.MinIoUtils;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.R;
import io.renren.common.validator.ValidatorUtils;
import io.renren.common.validator.group.AddGroup;
import io.renren.common.validator.group.UpdateGroup;
import io.renren.modules.sys.entity.algs.Algorithm;
import io.renren.modules.sys.entity.algs.Algorithm_Vo;
import io.renren.modules.sys.entity.algs.FileTest;
import io.renren.modules.sys.entity.algs.Version;
import io.renren.modules.sys.service.AlgsService;
import io.renren.modules.sys.service.VersionService;
import io.renren.modules.sys.service.impl.AlgsServiceImpl;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static io.renren.common.utils.ShiroUtils.getUserId;

/**
 * @Author: Ivan Q
 * @Date: 2021/6/17 11:38
 */
@RestController
@RequestMapping("/version")
public class versionController {
    @Autowired
    VersionService versionService;

    @Autowired
    AlgsService algsService;


    /**
     * 所有列表
     */
    @GetMapping("/list/{algorithmNameToVersion}")
    @RequiresPermissions("version:list")
    public R list(@RequestParam Map<String, Object> params,@PathVariable("algorithmNameToVersion") Long algorithmNameToVersion){
        params.put("algorithmNameToVersion",algorithmNameToVersion);
        PageUtils page = versionService.queryPageOnUse(params);

        return R.ok().put("page", page);
    }

    /**
     * 信息
     */
    @GetMapping("/info/{versionId}")
    @RequiresPermissions("version:info")
    public R info(@PathVariable("versionId") Long versionId){
        Version version = versionService.getById(versionId);
        if(version.getVersionStatus() != (byte)1)  return R.ok().put("version", version);
        else return  R.error("已删除，请联系管理员");
    }

    /***
     * 根据算法id查询已有版本
     */
    @GetMapping("/select/{algId}")
    //@RequiresPermissions("version:info")
    public R select(@PathVariable("algId") Long algId){
        System.out.println("获取算法已有版本");
       List<Version> versions= versionService.list(new QueryWrapper<Version>()
               .eq(algId > 0, "algorithm_id", algId)
               .eq(true,"delete_status", (byte)0)
       );
        return R.ok().put("versions", versions);
    }

    /**
     * 保存版本
     *
     */
    @SysLog("保存版本")
    @PostMapping("/save")
    @RequiresPermissions("version:save")
    public R save(@RequestBody Version version) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InternalException {
        ValidatorUtils.validateEntity(version, AddGroup.class);
//        List<Version> list = versionService.list();
//        for(Version version1 : list){
//            if(version1.getVersionName().equals(version.getVersionName())) return R.error("已经存在重复名称的版本");
//        }
        version.setVersionName(algsService.getById(version.getAlgorithmId()).getAlgorithmName() + "#" + (versionService.getMaxId() + 1));
        version.setCreationTime(new Date());
        version.setVersionStatus((byte) 0);
        version.setDeleteStatus((byte) 0);

        //若有父版本，把父版本的文件全部拷过来
        if(version.getFatherversionId()!=null){
            List<FileTest> fileList=MinIoUtils.listFiles("algorithm","alg"+version.getAlgorithmId()+"/version"+version.getFatherversionId());
            for(FileTest file:fileList){
                MinIoUtils.copyFile("algorithm","alg"+version.getAlgorithmId()+"/version"+(versionService.getMaxId() + 1)+"/"+file.getFilename(),"algorithm","alg"+version.getAlgorithmId()+"/version"+version.getFatherversionId()+"/"+file.getFilename());
            }
        }
        versionService.save(version);
//        更新算法的版本数量
        Algorithm tempA = algsService.getById(version.getAlgorithmId());
        tempA.setNumber(tempA.getNumber() + 1);
        algsService.update(tempA);
        return R.ok();
    }

    /**
     * 修改版本
     */
    @SysLog("修改版本")
    @PostMapping("/update")
    @RequiresPermissions("version:update")
    public R update(@RequestBody Version version){
        ValidatorUtils.validateEntity(version, UpdateGroup.class);
        versionService.update(version);

        return R.ok();
    }

    /**
     * 删除版本
     */
    @SysLog("删除版本")
    @PostMapping("/delete")
    @RequiresPermissions("version:delete")
    public R delete(@RequestBody Long[] versionIds) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InternalException {
//        假删
        for(Long id : versionIds){
            Version tmp = versionService.getById(id);
            tmp.setDeleteStatus((byte)1);
            versionService.update(tmp);

            //     更新算法数量
            Algorithm tempA = algsService.getById(tmp.getAlgorithmId());
            tempA.setNumber(tempA.getNumber() - 1);
            algsService.update(tempA);

            //minio里删除该算法版本中的文件
            MinIoUtils.deleteFilesByPrefix("algorithm","alg"+tmp.getAlgorithmId()+"/version"+id);
        }
//        真删
//        versionService.deleteBatch(versionIds);

        return R.ok();
    }

    /**
     * Description 根据algId和versionId查找对应位置的文件
     * @param params
     * @return
     */
    @GetMapping("/listFiles")
    public R listFiles(@RequestParam Map<String,Object> params) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InternalException {
        String algorithmNameToVersion=String.valueOf(params.get("algorithmNameToVersion"));
        String verisionToFile=String.valueOf(params.get("verisionToFile"));

        List<FileTest> fileList= MinIoUtils.listFiles("algorithm","alg"+algorithmNameToVersion+"/version"+verisionToFile);
        return R.ok().put("fileList",fileList);
    }

    @GetMapping("/listTraFiles")
    public R listTraFiles(@RequestParam Map<String,Object> params) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InternalException {
        String algorithmNameToVersion=String.valueOf(params.get("algorithmNameToVersion"));
        List<FileTest> fileList= MinIoUtils.listFiles("algorithm","alg"+algorithmNameToVersion);
        return R.ok().put("fileList",fileList);
    }

    /**
     * Description:上传文件到指定算法版本
     * @param request
     * @return
     */
    @PostMapping("/uploadFile")
    public R uploadFile(MultipartHttpServletRequest request) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, ErrorResponseException, XmlParserException, InvalidBucketNameException, InternalException {
        String algId=request.getParameter("algorithmNameToVersion");
        String versionId=request.getParameter("versionToFile");
        List<MultipartFile> files=request.getFiles("file");

        //下面进行重名判断
        List<String> fileTestNames=MinIoUtils.listFiles("algorithm","alg"+algId+"/version"+versionId)
                .stream().map(FileTest::getFilename).collect(Collectors.toList());//抽取Filetest中的getFilename字段构造list
        HashSet<String> fileSet=new HashSet<>(fileTestNames);//将fileTestLists转换为HashSet
        for(MultipartFile file:files){
            if(file.isEmpty())  break;
            if(fileSet.contains(file.getOriginalFilename()))    return R.error("存在重复文件:"+file.getOriginalFilename());
        }


        for(MultipartFile file:files){
            if(file.isEmpty())  break;
            MinIoUtils.uploadMultipartFile(file,"algorithm","alg"+algId+"/version"+versionId+"/"+file.getOriginalFilename());
        }
        return R.ok();
    }

}
