package com.sqx.modules.course.controller;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.OSSObjectSummary;
import com.aliyun.oss.model.ObjectListing;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.COSObjectSummary;
import com.qcloud.cos.region.Region;
import com.sqx.common.utils.DateUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.course.entity.Course;
import com.sqx.modules.course.entity.CourseDetails;
import com.sqx.modules.course.service.CourseDetailsService;
import com.sqx.modules.course.service.CourseService;
import com.volcengine.tos.TOSV2;
import com.volcengine.tos.TOSV2ClientBuilder;
import com.volcengine.tos.model.object.ListObjectsType2Input;
import com.volcengine.tos.model.object.ListObjectsType2Output;
import com.volcengine.tos.model.object.ListedCommonPrefix;
import com.volcengine.tos.model.object.ListedObjectV2;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@RestController
@Api(value = "读取短剧", tags = {"读取短剧"})
@Slf4j
@RequestMapping(value = "/aliossCourse")
public class AliossCourseController {

    @Autowired
    private CourseService courseService;
    @Autowired
    private CourseDetailsService courseDetailsService;
    @Autowired
    private CommonInfoService commonInfoService;
    static boolean flag=false;
    Pattern pattern = Pattern.compile("\\d+"); // 正则表达式匹配一个或多个数字
    /**
     * 创建线程池
     */
    private ExecutorService newCachedThreadPool = new ThreadPoolExecutor(30, 100, 0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(1024),
            Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());


    @GetMapping("/sysnAliOssCourse")
    @ApiOperation("同步短剧")
    public Result sysnAliOssCourse(Integer type,String filePath, Integer freeNum, BigDecimal coursePrice,Integer maxGood,Integer minGood){
        if(flag){
            return Result.error("短剧正在同步中！");
        }
        Map<String, Object> alioss = null;
        //读取oss或cos短剧信息
        if(type==1){
            alioss = alioss(filePath);
        }else if(type==2){
            alioss = txCos(filePath);
        }else{
            alioss = dyOss(filePath);
        }

        if(alioss==null){
            return Result.error("读取oss短剧失败，请检查配置！");
        }
        Map<String, List<String>> videoFile=(Map<String, List<String>>)alioss.get("videoFile");
        if(videoFile==null || videoFile.size()==0){
            return Result.error("读取oss短剧失败，请检查配置！");
        }
        Map<String, String> imageFile=(Map<String, String>)alioss.get("imageFile");

        flag=true;
        newCachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    String url =null;
                    Random rand = new Random();
                    if(type==1){
                        url = commonInfoService.findOne(73).getValue();
                        if(StringUtils.isEmpty(url)){
                            url = commonInfoService.findOne(72).getValue();
                        }
                    }else if(type==2){
                        url = commonInfoService.findOne(883).getValue();
                        if(StringUtils.isEmpty(url)){
                            url = commonInfoService.findOne(804).getValue();
                        }
                    }else{
                        url = commonInfoService.findOne(891).getValue();
                    }

                    for (String key : videoFile.keySet()) {
//                System.err.println("短剧名称: " + key);
                        String image = url+"/"+imageFile.get(key);
                        String value = commonInfoService.findOne(887).getValue();
                        String[] split = value.split(",");
                        int min = 0; // 指定范围的最小值（包含）
                        int max = split.length-1; // 指定范围的最大值（包含）
                        int randomNum1 = min + rand.nextInt(max - min + 1);
                        int randomNum2 = min + rand.nextInt(max - min + 1);
                        int randomNum3 = min + rand.nextInt(max - min + 1);
                        String courseLabel=split[randomNum1]+","+split[randomNum2]+","+split[randomNum3];
                        Course course = courseService.getOne(new QueryWrapper<Course>().eq("title", key).eq("is_delete",0));
                        if(course==null){
                            course=new Course();
                            course.setTitle(key);
                            course.setTitleImg(image);
                            course.setPrice(coursePrice);
                            course.setCourseLabel(courseLabel);
                            course.setPayNum(0);
                            course.setImg(image);
                            course.setDetails(key);
                            course.setIsDelete(0);
                            course.setCreateTime(DateUtils.format(new Date()));
                            course.setUpdateTime(course.getCreateTime());
                            course.setIsRecommend(0);
                            course.setStatus(1);
                            course.setIsPrice(1);
                            course.setViewCounts(0);
                            course.setIsOver(1);
                            courseService.save(course);
                        }else{
                            course.setTitleImg(image);
                            course.setImg(image);
                            courseService.updateById(course);
                        }
                        List<String> valueList = videoFile.get(key);
                        valueList.sort(Comparator.comparingInt(this::extractNumberFromFileName));
                        int i=1;
                        int priceNum=valueList.size()-freeNum;
                        BigDecimal courseDetailsPrice = BigDecimal.ZERO;
                        if(priceNum>0){
                            courseDetailsPrice = coursePrice.divide(BigDecimal.valueOf(priceNum), 2, BigDecimal.ROUND_UP);
                        }
                        for(String str:valueList){
                            String[] splits = str.split("/");
                            String fileName=splits[splits.length-1];
                            String substring = fileName.substring(0, fileName.lastIndexOf("."));
                            Matcher matcher = pattern.matcher(substring);
                            Integer num=0;
                            if(matcher.find()){
                                num = Integer.parseInt(matcher.group());
                            }
                            String courseDetailsName=key+"-第"+num+"集";

                            CourseDetails courseDetails = courseDetailsService.getOne(new QueryWrapper<CourseDetails>()
                                    .eq("course_id",course.getCourseId()).eq("course_details_name", courseDetailsName));
                            if(courseDetails==null){
                                int goodNum = minGood + rand.nextInt(maxGood - minGood + 1);
                                courseDetails=new CourseDetails();
                                courseDetails.setCourseId(course.getCourseId());
                                courseDetails.setCourseDetailsName(courseDetailsName);
                                courseDetails.setVideoUrl(url+"/"+str);
                                courseDetails.setCreateTime(DateUtils.format(new Date()));
                                courseDetails.setTitleImg(image);
                                courseDetails.setContent(courseDetailsName);
                                courseDetails.setGoodNum(goodNum);
                                courseDetails.setViewCount(0L);
                                courseDetails.setPlayCompleteCount(0L);
                                if(i<=freeNum){
                                    courseDetails.setPrice(BigDecimal.ZERO);
                                    courseDetails.setIsPrice(2);
                                }else{
                                    courseDetails.setPrice(courseDetailsPrice);
                                    courseDetails.setIsPrice(1);
                                }
                                courseDetails.setSort(num);
                                courseDetailsService.insert(courseDetails);
                            }else{
                                int goodNum = minGood + rand.nextInt(maxGood - minGood + 1);
                                courseDetails.setCourseId(course.getCourseId());
                                courseDetails.setCourseDetailsName(courseDetailsName);
                                courseDetails.setVideoUrl(url+"/"+str);
                                courseDetails.setCreateTime(DateUtils.format(new Date()));
                                courseDetails.setTitleImg(image);
                                courseDetails.setContent(courseDetailsName);
                                courseDetails.setGoodNum(goodNum);
                                if(i<=freeNum){
                                    courseDetails.setPrice(BigDecimal.ZERO);
                                    courseDetails.setIsPrice(2);
                                }else{
                                    courseDetails.setPrice(courseDetailsPrice);
                                    courseDetails.setIsPrice(1);
                                }
                                courseDetails.setSort(num);
                                courseDetailsService.updateById(courseDetails);
                            }
                            i++;
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                    log.error("同步短剧出错："+e.getMessage(),e);
                }finally {
                    flag=false;
                }
            }

            public int extractNumberFromFileName(String fileUrl) {
                String[] split = fileUrl.split("/");
                String fileName=split[split.length-1];
                String substring = fileName.substring(0, fileName.lastIndexOf("."));
                Matcher matcher = pattern.matcher(substring);
                Integer num=0;
                if(matcher.find()){
                    num = Integer.parseInt(matcher.group());
                }
                return num;
            }
        });

        return Result.success();
    }



    public Map<String,Object> alioss(String keyPrefix) {
        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
        String endpoint = commonInfoService.findOne(68).getValue();
        // 从环境变量中获取访问凭证。运行本代码示例之前，请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        DefaultCredentialProvider defaultCredentialProvider = CredentialsProviderFactory.newDefaultCredentialProvider(commonInfoService.findOne(69).getValue(), commonInfoService.findOne(70).getValue());
        // 填写Bucket名称，例如examplebucket。
        String bucketName = commonInfoService.findOne(71).getValue();
        // 指定前缀，例如exampledir/object。

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, defaultCredentialProvider);
//       设置每页列举200个文件。
        int maxKeys = 200;
        List<String> filePaths=new ArrayList<>();
        try {
            String nextMarker = null;
            ObjectListing objectListing;
            do {
                objectListing = ossClient.listObjects(new ListObjectsRequest(bucketName).withMarker(nextMarker).withMaxKeys(maxKeys).withPrefix(keyPrefix));
                List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
                for (OSSObjectSummary s : sums) {
                    filePaths.add(s.getKey());
                }
                nextMarker = objectListing.getNextMarker();

            } while (objectListing.isTruncated());

            Map<String, List<String>> videoFile = new HashMap<>();
            Map<String, String> imageFile = new HashMap<>();
            for (String filePath : filePaths) {
                if(filePath.contains(".")){
                    String[] split = filePath.split("/");
                    String directory = split[split.length-2];
                    String extension = filePath.substring(filePath.lastIndexOf('.') + 1);
                    switch (extension) {
                        case "mp4":
                        case "avi":
                        case "wmv":
                        case "flv":
                        case "m3u8":
                        case "mov":
                            List<String> videoList = videoFile.get(directory);
                            if(videoList==null){
                                videoList=new ArrayList<>();
                            }
                            videoList.add(filePath);
                            videoFile.put(directory,videoList);
                            break;
                        default:
                            String image = imageFile.get(directory);
                            if(StringUtils.isEmpty(image)){
                                imageFile.put(directory,filePath);
                            }
                            break;
                    }
                }
            }
            Map<String,Object> result=new HashMap<>();
            result.put("videoFile",videoFile);
            result.put("imageFile",imageFile);
            return result;
        } catch (Exception e) {
            log.error("阿里云读取oss报错："+e.getMessage(),e);
        }  finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return null;
    }


    public Map<String,Object> txCos(String keyPrefix) {
        COSClient cosClient = createCOSClient();
        // 存储桶的命名格式为 BucketName-APPID，此处填写的存储桶名称必须为此格式
        String bucketName = commonInfoService.findOne(803).getValue();

        com.qcloud.cos.model.ListObjectsRequest listObjectsRequest = new com.qcloud.cos.model.ListObjectsRequest();
        // 设置 bucket 名称
        listObjectsRequest.setBucketName(bucketName);
        // 设置列出的对象名以 prefix 为前缀
        listObjectsRequest.setPrefix(keyPrefix);
        // 保存列出的结果
        com.qcloud.cos.model.ObjectListing objectListing = null;
        String nextMarker = null;
        List<String> filePaths=new ArrayList<>();
        do {
            listObjectsRequest.setMarker(nextMarker);
            listObjectsRequest.setMaxKeys(100);
            try {
                objectListing = cosClient.listObjects(listObjectsRequest);
            } catch (CosServiceException e) {
                e.printStackTrace();
            } catch (CosClientException e) {
                e.printStackTrace();
            }

            List<COSObjectSummary> cosObjectSummaries = objectListing.getObjectSummaries();

            for (COSObjectSummary cosObjectSummary : cosObjectSummaries) {
                // 对象的 key
                String key = cosObjectSummary.getKey();
                filePaths.add(key);
            }
            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());


        // 确认本进程不再使用 cosClient 实例之后，关闭即可
        cosClient.shutdown();

        Map<String, List<String>> videoFile = new HashMap<>();
        Map<String, String> imageFile = new HashMap<>();
        for (String filePath : filePaths) {
            if(filePath.contains(".")){
                String[] split = filePath.split("/");
                String directory = split[split.length-2];
                String extension = filePath.substring(filePath.lastIndexOf('.') + 1);
                switch (extension) {
                    case "mp4":
                    case "avi":
                    case "wmv":
                    case "flv":
                    case "m3u8":
                    case "mov":
                        List<String> videoList = videoFile.get(directory);
                        if(videoList==null){
                            videoList=new ArrayList<>();
                        }
                        videoList.add(filePath);
                        videoFile.put(directory,videoList);
                        break;
                    default:
                        String image = imageFile.get(directory);
                        if(StringUtils.isEmpty(image)){
                            imageFile.put(directory,filePath);
                        }
                        break;
                }
            }
        }
        Map<String,Object> result=new HashMap<>();
        result.put("videoFile",videoFile);
        result.put("imageFile",imageFile);
        return result;
    }


    // 创建 COSClient 实例，这个实例用来后续调用请求
    public COSClient createCOSClient() {
        // 设置用户身份信息。
        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
        String secretId = commonInfoService.findOne(800).getValue();//用户的 SecretId，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
        String secretKey = commonInfoService.findOne(801).getValue();//用户的 SecretKey，建议使用子账号密钥，授权遵循最小权限指引，降低使用风险。子账号密钥获取可参见 https://cloud.tencent.com/document/product/598/37140
        COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);


        // ClientConfig 中包含了后续请求 COS 的客户端设置：
        ClientConfig clientConfig = new ClientConfig();


        // 设置 bucket 的地域
        // COS_REGION 请参见 https://cloud.tencent.com/document/product/436/6224
        clientConfig.setRegion(new Region(commonInfoService.findOne(802).getValue()));


        // 设置请求协议, http 或者 https
        // 5.6.53 及更低的版本，建议设置使用 https 协议
        // 5.6.54 及更高版本，默认使用了 https
        clientConfig.setHttpProtocol(HttpProtocol.https);


        // 以下的设置，是可选的：


        // 设置 socket 读取超时，默认 30s
        clientConfig.setSocketTimeout(30*1000);
        // 设置建立连接超时，默认 30s
        clientConfig.setConnectionTimeout(30*1000);


        // 如果需要的话，设置 http 代理，ip 以及 port
//        clientConfig.setHttpProxyIp("httpProxyIp");
//        clientConfig.setHttpProxyPort(80);


        // 生成 cos 客户端。
        return new COSClient(cred, clientConfig);
    }

    public Map<String,Object> dyOss(String keyPrefix) {
        String endpoint = "tos-cn-beijing.volces.com";
        String region = "cn-beijing";
        String accessKey = commonInfoService.findOne(888).getValue();
        String secretKey = commonInfoService.findOne(889).getValue();

        String bucketName = commonInfoService.findOne(890).getValue();

        String delimiter = "/";

        TOSV2 tos = new TOSV2ClientBuilder().build(region, endpoint, accessKey, secretKey);
        try{
            String continuationToken = null;
            boolean isTruncated = true;
            Map<String, List<String>> videoFile = new HashMap<>();
            Map<String, String> imageFile = new HashMap<>();
            while (isTruncated) {
                ListObjectsType2Input input = new ListObjectsType2Input().setBucket(bucketName)
                        .setDelimiter(delimiter).setContinuationToken(continuationToken).setPrefix(keyPrefix+"/");
                ListObjectsType2Output output = tos.listObjectsType2(input);
                if (output.getCommonPrefixes() != null) {
                    for (int i = 0; i < output.getCommonPrefixes().size(); i++) {


                        ListedCommonPrefix commonPrefix = output.getCommonPrefixes().get(i);
                        //System.err.println("Listed commonPrefix is " + commonPrefix.getPrefix());
                        Map<String, Object> stringObjectMap = listCommonPrefix(bucketName, delimiter, commonPrefix.getPrefix(), tos,videoFile,imageFile);
                        videoFile = (Map<String, List<String>>)stringObjectMap.get("videoFile");
                        imageFile = (Map<String, String>)stringObjectMap.get("imageFile");
                    }
                }
                isTruncated = output.isTruncated();
                continuationToken = output.getNextContinuationToken();
            }
            Map<String,Object> result=new HashMap<>();
            result.put("videoFile",videoFile);
            result.put("imageFile",imageFile);
            return result;
        } catch (Exception e) {
            log.error("抖音云同步文件出错:"+e.getMessage(),e);
        }
        return null;
    }

    private static Map<String,Object> listCommonPrefix(String bucketName, String delimiter, String prefix, TOSV2 tos,
                                         Map<String, List<String>> videoFile,Map<String, String> imageFile) {
        boolean isTruncated = true;
        String continuationToken = null;
        List<String> videoList=new ArrayList<>();
        String image=null;
        String[] split = prefix.split("/");
        System.err.println(split[split.length-1]);
        while (isTruncated) {
            ListObjectsType2Input input = new ListObjectsType2Input().setBucket(bucketName)
                    .setDelimiter(delimiter).setContinuationToken(continuationToken).setPrefix(prefix);
            ListObjectsType2Output output = tos.listObjectsType2(input);
            if (output.getContents() != null) {
                for (int i = 0; i < output.getContents().size(); i++) {
                    ListedObjectV2 object = output.getContents().get(i);
                    if(object.getSize()>0){
                        String extension = object.getKey().substring(object.getKey().lastIndexOf('.') + 1);
                        switch (extension) {
                            case "mp4":
                            case "avi":
                            case "wmv":
                            case "flv":
                            case "m3u8":
                            case "mov":
                                videoList.add(object.getKey());
                                break;
                            default:
                                image=object.getKey();
                                break;
                        }

                    }
                }
            }
            isTruncated = output.isTruncated();
            continuationToken = output.getNextContinuationToken();
        }
        videoFile.put(split[split.length-1],videoList);
        imageFile.put(split[split.length-1],image);
        Map<String,Object> result=new HashMap<>();
        result.put("videoFile",videoFile);
        result.put("imageFile",imageFile);
        return result;
    }


}
