package com.friday.tooldriver.controller.external;

import com.friday.base.common.response.DubboResult;
import com.friday.base.web.response.ResponseAspect;
import com.friday.base.web.service.WebFileService;
import com.friday.operation.api.keepalive.constant.taieoc.TaieOcConstants;
import com.friday.operation.api.keepalive.dto.smartrpa.DownLoadFileReqDto;
import com.friday.operation.api.keepalive.dto.smartrpa.MachineLicenseAcquireReqDto;
import com.friday.operation.api.keepalive.dto.smartrpa.MachineLicenseAuthReqDto;
import com.friday.operation.api.keepalive.dto.smartrpa.ProcessVersionQueryDto;
import com.friday.operation.api.keepalive.dto.taieoc.MachineInfoDto;
import com.friday.operation.api.tooldriver.dto.rpa.CodePackageDto;
import com.friday.operation.api.tooldriver.dto.rpa.CodePackageFilter;
import com.friday.operation.api.tooldriver.dto.rpa.ReleaseDto;
import com.friday.operation.api.tooldriver.dto.rpa.ReleaseFilter;
import com.friday.operation.api.tooldriver.service.IEnvironment;
import com.friday.operation.api.tooldriver.service.ILicense;
import com.friday.operation.api.tooldriver.service.IProcess;
import com.friday.tooldriver.constants.DriverSystemCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;

@RestController
@RequestMapping(value = "/driver/smart-rpa/admin")
@Slf4j
public class DigitalAdminController {
    @Autowired
    private ResponseAspect responseAspect;

    @Autowired
    private IProcess processManager;

    @Autowired
    private ILicense licenseManager;

    @Autowired
    private IEnvironment environmentManage;

    @Autowired
    private WebFileService webFileService;

    
    @RequestMapping(value = "/uploadProcessFile", method = RequestMethod.POST)
    public Object uploadProcessFile(@RequestParam("file")MultipartFile file, @RequestParam("processName") String processName,
                                    @RequestParam("machineCode") String machine,
                                    @RequestParam("machineUser") String machineUser,
                                    @RequestParam("fileType") String fileType) {
        try{
            CodePackageFilter filter = new CodePackageFilter();
            filter.setName(processName);
            filter.setFileType(fileType);
            DubboResult<String> DubboResult = processManager.obtainProcessMaxVersionFileKey(MachineInfoDto.builder()
                    .machineCode(machine)
                    .machineUser(machineUser)
                    .build(), filter);
            if(!DubboResult.success()){
                log.error(DubboResult.getMessage());
                return responseAspect.fail(DubboResult.getMessage());
            }
            String oldFileKey = DubboResult.getObject();
            if(!StringUtils.isEmpty(oldFileKey)){
                String oldFilePath = webFileService.getFilePath(oldFileKey);
                if(!StringUtils.isEmpty(oldFilePath)){
                    oldFilePath = oldFilePath.substring(0, oldFilePath.lastIndexOf(TaieOcConstants.EN_SLASH) + 1) + oldFileKey;
                }else{
                    oldFilePath = oldFileKey;
                }
                InputStream oldFileStream = Files.newInputStream(Paths.get(oldFilePath));
                if(webFileService.md5HashCode(oldFileStream).equals(webFileService.md5HashCode(file.getInputStream()))){
                    return responseAspect.fail(DriverSystemCode.PACKAGE_DUPLICATE_ERROR.getMessage());
                }
            }
            String fileKey = webFileService.fileUpload(file, "013056", true);
            DubboResult<CodePackageDto> result = processManager.uploadPackage(MachineInfoDto.builder()
                    .machineCode(machine).machineUser(machineUser)
                    .build(), CodePackageDto.builder()
                    .filePath(fileKey)
                    .fileType(fileType)
                    .name(processName)
                    .fileName(file.getOriginalFilename())
                    .build());
            return responseAspect.success(result);
        }catch(Exception e){
            log.error(DriverSystemCode.FAIL.toString(), e);
            return responseAspect.fail("访问/uploadProcessFile异常");
        }
    }

    
    @RequestMapping(value = "queryCurrentProcessVersion", method = RequestMethod.POST)
    public Object queryCurrentProcessVersion(@RequestBody ProcessVersionQueryDto dto){
        ReleaseFilter filter = new ReleaseFilter();
        filter.setName(dto.getProcessName());
        DubboResult<ArrayList<ReleaseDto>> result = processManager.queryProcessReleases(MachineInfoDto.builder()
                .machineCode(dto.getMachineCode()).machineUser(dto.getMachineUser())
                .build(), filter);
        return responseAspect.response(result);
    }

    
    @RequestMapping(value = "/downloadProcessFile", method = RequestMethod.POST)
    public Object downloadProcessFile(@RequestBody DownLoadFileReqDto reqDto, HttpServletResponse response, HttpServletRequest request){
        try{
            CodePackageFilter filter = new CodePackageFilter();
            filter.setName(reqDto.getProcessName());
            filter.setFileType(reqDto.getFileType());
            filter.setVersion(reqDto.getProcessVersion());
            DubboResult<ArrayList<CodePackageDto>> listDubboResult = processManager.queryPackages(MachineInfoDto.builder()
                    .machineCode(reqDto.getMachineCode()).machineUser(reqDto.getMachineUser())
                    .build(), filter);
            if(!listDubboResult.success()){
                throw new Exception(listDubboResult.getMessage());
            }
            ArrayList<CodePackageDto> resultDtos = listDubboResult.getObject();
            if(CollectionUtils.isEmpty(resultDtos)){
                return responseAspect.fail("获取流程文件信息为空");
            }
            resultDtos.forEach(e-> {
                try {
                    if(ObjectUtils.isEmpty(webFileService.getFilePath(e.getFilePath()))){
                        // 未通过文件服务，直接基于路径获取文件内容
                        response.setCharacterEncoding("UTF-8");
                        response.setContentType("*/*");
                        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(e.getFileName(), "UTF-8"));
                        OutputStream os = response.getOutputStream();
                        os.write(Files.readAllBytes(Paths.get(e.getFilePath())));
                        os.flush();
                    }else{
//                        response.setCharacterEncoding("UTF-8");
//                        response.setContentType("*/*");
//                        response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(e.getFileName(), "UTF-8"));
                        webFileService.downloadFile(response,e.getFilePath(), e.getFileName(), "013056");
                    }
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            });
            return responseAspect.success();
        }catch(Exception e){
            log.error(DriverSystemCode.FAIL.toString(), e);
            return responseAspect.fail("访问/downloadProcessFile异常");
        }

    }

    
    @RequestMapping(value = "/getMachineLicense", method = RequestMethod.POST)
    public Object getMachineLicense(@RequestBody MachineLicenseAcquireReqDto reqDto){
            return responseAspect.response(licenseManager.getLicense(reqDto));
    }

    
    @RequestMapping(value = "/verifyMachineLicense", method = RequestMethod.POST)
    public Object verifyMachineLicense(@RequestBody MachineLicenseAuthReqDto reqDto){
        return responseAspect.response(licenseManager.verifyLicense(reqDto));
    }
    
    @RequestMapping(value = "/queryProcessFileInfo", method = RequestMethod.POST)
    public Object queryProcessFileInfo(@RequestBody ProcessVersionQueryDto dto) {
        try{
            CodePackageFilter filter = new CodePackageFilter();
            filter.setName(dto.getProcessName());
            filter.setFileType(dto.getFileType());
            return responseAspect.response(processManager.queryPackages(
                    MachineInfoDto.builder()
                            .machineCode(dto.getMachineCode()).machineUser(dto.getMachineUser())
                            .build(), filter));
        }catch (Exception e){
            log.error(DriverSystemCode.FAIL.toString(),e);
            return responseAspect.fail(e.getMessage());
        }
    }
    
    @RequestMapping(value = "/queryEnvironmentInfo", method = RequestMethod.GET)
    public Object queryEnvironmentInfo(@RequestParam("currentEnv") String currentEnv){
        return responseAspect.response(environmentManage.queryEnvInfo(currentEnv));
    }


    @RequestMapping(value = "/getExistLicenseOnly", method = RequestMethod.POST)
    public Object getExistLicenseOnly(@RequestBody MachineLicenseAcquireReqDto reqDto){
        return responseAspect.response(licenseManager.getExistLicenseOnly(reqDto));
    }

}
