package sgc.portal.base.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import sgc.portal.SgcPortalProperties;
import sgc.portal.base.exception.BusinessException;
import sgc.portal.base.storage.StorageException;
import sgc.portal.base.storage.SubpathFactory;
import sgc.portal.base.storage.model.FileBucket;
import sgc.portal.base.storage.persistence.StorageMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <pre>
 * 시스템명   : Common
 * 프로그램ID :
 * 프로그램명  :
 * 설명 :
 * </pre>
 *
 * @author 이범근
 * @version 2020.04.08
 * @see kr.co.sgc.com.cmm.service
 * @since JDK1.8
 */
@Slf4j
@Service
@Transactional
public class ReportToFileService {

    @Autowired
    private StorageMapper mapper;

    @Autowired
    private SgcPortalProperties props;

    public FileBucket makeFile(String fileId, String ozrName, String[] ozrParamVal, String odiName, String[] odiParamVal, String exportFormat, String exportFileName){


        String uri = props.getReport().getServerUrl() + props.getReport().getDirectExportUri();


        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, Object> map= new LinkedMultiValueMap<>();


        map.add("ozrName", ozrName);
        map.add("odiName", odiName);
        map.add("exportFormat", exportFormat);
        map.add("exportFileName", exportFileName);

        for (String value : ozrParamVal) {
            map.add("ozrParamVal", value);
        }
        for (String s : odiParamVal) {
            map.add("odiParamVal", s);
        }


        map.add("serverUrl", props.getReport().getServerUrl() + "/server");
        map.add("schedulerIp", props.getReport().getSchedulerIp());
        map.add("schedulerPort", props.getReport().getSchedulerPort());

        HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);

        ResponseEntity<String> response = getRestTemplate().postForEntity( uri, request , String.class );

        Map<String, Object> resultMap = new HashMap<>();


        try {
            ObjectMapper objectMapper = new ObjectMapper();

            resultMap = objectMapper.readValue(response.getBody(), HashMap.class);
        } catch (IOException e) {
            log.error(e.getMessage());
        }

        return store(fileId, resultMap);

    }

    private FileBucket store(String fileId, Map<String, Object> fileInfo){
        //파일 저장 정보 생성
        if (StringUtils.isEmpty(fileId)) {
            fileId = RandomStringUtils.randomAlphanumeric(30);
        }

        FileBucket fileBucket = new FileBucket();

        String filePath = fileInfo.get("filePath").toString();

        File file = FileUtils.getFile(filePath);

        if(!file.exists()){
            throw new BusinessException("파일 생성에 실패 하였습니다.");
        }


        fileBucket.setId(fileId);
        fileBucket.setBackNumber(Integer.parseInt(RandomStringUtils.randomNumeric(7)));
        fileBucket.setChangedFilename(fileBucket.getId() + fileBucket.getBackNumber());



        String fileName = file.getName();

        fileBucket.setOriginalFilename(fileName);

        fileBucket.setFileSize(file.length());

        String[] others = {"report"};

        List<String> partial = SubpathFactory.create("date", others).resolve();
        partial.add(fileBucket.getChangedFilename());
        Path path = Paths.get(props.getStorage().getLocation(), partial.toArray(new String[partial.size()]));
        fileBucket.setLocation(path.getParent().toString());


        try {
            Files.createDirectories(path.getParent());
            try(InputStream is = Files.newInputStream(file.toPath())) {
                Files.copy(is, path);
            }
            mapper.insert(fileBucket);

            //임시 생성 파일 삭제
            FileUtils.forceDelete(file);
        } catch (Exception e) {
            try {
                Files.deleteIfExists(path);
                FileUtils.forceDelete(file);
            } catch (IOException ioe) {
                throw new StorageException("exception.storage", ioe.getMessage());
            }
            throw new StorageException("exception.storage", e.getMessage());
        }


        return fileBucket;
    }
    /**
     * Rest template Getting
     * @return RestTemplate
     */
    private RestTemplate getRestTemplate() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectTimeout(40*1000);
        factory.setReadTimeout(40*1000);
        return new RestTemplate(factory);
    }
}
