package cn.com.qmth.examcloud.tool.service.export_student_photo;

import ch.qos.logback.classic.LoggerContext;
import cn.com.qmth.examcloud.tool.service.export_student_photo.vo.StudentInfo;
import cn.com.qmth.examcloud.tool.utils.FileHelper;
import cn.com.qmth.examcloud.tool.utils.HttpHelper;
import cn.com.qmth.examcloud.tool.utils.SignUtils;
import cn.com.qmth.examcloud.tool.vo.SignRequest;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

public class DownloadStudentPhoto {

    private final static Logger log = LoggerFactory.getLogger(DownloadStudentPhoto.class);

    public static void main(String[] args) {
        LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
        loggerContext.getLogger("cn").setLevel(ch.qos.logback.classic.Level.INFO);
        loggerContext.getLogger("com").setLevel(ch.qos.logback.classic.Level.INFO);
        loggerContext.getLogger("org").setLevel(ch.qos.logback.classic.Level.INFO);

        SignRequest signReq = new SignRequest();
        // signReq.setServerUrl("https://www.exam-cloud.cn");
        // signReq.setServerUrl("http://192.168.10.41:8007");
        signReq.setServerUrl("http://192.168.10.39:8007");
        signReq.setRootOrgId(0L);
        signReq.setAppId("11");
        signReq.setSecretKey("123456");

        String exportDir = "D:/home/data/todo";
        List<StudentInfo> students = loadStudentFromExcel(signReq, exportDir + "/students.xlsx");
        downloadImages(students, exportDir);
    }

    private static void downloadImages(List<StudentInfo> students, String exportDir) {
        long startTime = System.currentTimeMillis();
        AtomicInteger finishAc = new AtomicInteger(), successAc = new AtomicInteger(), failAc = new AtomicInteger();
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        final int totalCount = students.size();
        for (StudentInfo student : students) {
            executorService.execute(() -> {
                String photoSuffix = FileHelper.getFileSuffix(student.getPhotoUrl());
                String savePhotoPath = String.format("%s/images/%s%s", exportDir, student.getIdentityNumber(), photoSuffix);

                try {
                    if (new File(savePhotoPath).exists()) {
                        log.debug("【图片下载】已处理！{} {}", savePhotoPath, student.getPhotoUrl());
                    } else {
                        FileHelper.saveImageToFile(student.getPhotoUrl(), savePhotoPath);
                    }
                    successAc.incrementAndGet();
                } catch (Exception e) {
                    log.error("【图片下载】 {} err:{}", student.getPhotoUrl(), e.getMessage());
                    failAc.incrementAndGet();
                }

                int finishCount = finishAc.incrementAndGet();
                if (finishCount % 100 == 0) {
                    float finishRate = finishCount * 100f / totalCount;
                    long cost = Math.max((System.currentTimeMillis() - startTime) / 1000, 1);
                    float speed = (float) finishCount / cost;
                    log.info("【图片下载】总数:{} 成功数:{} 失败数:{} 进度:{}% 速度:约{}个每秒 已耗时:{}秒",
                            totalCount, successAc.get(), failAc.get(), finishRate, speed, cost);
                }
            });
        }

        executorService.shutdown();
        while (!executorService.isTerminated()) {
            // ignore
        }

        log.info("【图片下载】已执行完成！");
    }

    private static List<StudentInfo> loadStudentFromExcel(SignRequest signReq, String dataFilePath) {
        long startTime = System.currentTimeMillis();
        List<StudentInfo> list = new ArrayList<>();
        try {
            EasyExcel.read(dataFilePath, StudentInfo.class, new AnalysisEventListener<StudentInfo>() {
                        @Override
                        public void invoke(StudentInfo data, AnalysisContext analysisContext) {
                            list.add(data);
                        }

                        @Override
                        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                            // ignore
                        }
                    }
            ).sheet().doRead();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new RuntimeException("Excel内容解析错误，请使用标准模板！");
        }

        int noPhotoCount = 0;
        List<StudentInfo> hasPhotoStudents = new ArrayList<>();
        for (StudentInfo student : list) {
            String photoUrl = getPhotoUrl(signReq, student.getIdentityNumber());
            if (StringUtils.isEmpty(photoUrl)) {
                noPhotoCount++;
                continue;
            }

            // System.out.println(photoUrl);
            student.setPhotoUrl(photoUrl);
            hasPhotoStudents.add(student);
        }

        long cost = System.currentTimeMillis() - startTime;
        log.info("【获取学生照片】总数:{} 有底照数:{} 无底照数:{} 耗时:{}ms", list.size(), hasPhotoStudents.size(), noPhotoCount, cost);
        return hasPhotoStudents;
    }

    private static String getPhotoUrl(SignRequest signReq, String identityNumber) {
        long timestamp = System.currentTimeMillis();
        String accessToken = SignUtils.accessToken(signReq.getRootOrgId(), signReq.getAppId(), signReq.getSecretKey(), timestamp);

        Map<String, String> headers = new HashMap<>();
        headers.put("rootOrgId", String.valueOf(signReq.getRootOrgId()));
        headers.put("appId", signReq.getAppId());
        headers.put("access_token", accessToken);
        headers.put("timestamp", String.valueOf(timestamp));

        // String url = signReq.getServerUrl() + "/api/exchange/outer/face/getPhotoUrl?rootOrgId=" + signReq.getRootOrgId() + "&studentCode=" + studentCode;
        String url = signReq.getServerUrl() + "/api/exchange/outer/face/getPhotoUrl?rootOrgId=" + signReq.getRootOrgId() + "&identityNumber=" + identityNumber;
        try {
            return HttpHelper.post(url, headers, null);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

}
