package com.eactive.eai.rms.ext.kakaocard.cm;

import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;

@Controller
@RequestMapping("/deployresource")
public class TempController implements InterceptorSkipController {
   
   @Autowired
   private S3Client s3Client;
   
   @Autowired @Qualifier("monitoringContext")
    private MonitoringContext monitoringContext;   
   
   @RequestMapping("/files.do")
   public ResponseEntity<String> temp() {
      
      Properties prop = monitoringContext.getProperties();
      String uploadPath   = prop.getProperty(MonitoringContext.CM_DEVELOPER_UPLOAD_PATH);
      String afterPath    = prop.getProperty(MonitoringContext.CM_DEVELOPER_AFTER_PATH);
      String backupPath   = prop.getProperty(MonitoringContext.CM_DEVELOPER_BACKUP_PATH);
      
      StringBuilder sb = new StringBuilder();
      
      sb.append(" - UPLOAD PATH").append(System.lineSeparator());
      sb.append(fileSystemEntryList(Paths.get(uploadPath))).append(System.lineSeparator());
      sb.append(" - AFTER PATH").append(System.lineSeparator());
      sb.append(fileSystemEntryList(Paths.get(afterPath))).append(System.lineSeparator());
      sb.append(" - BACKUP PATH").append(System.lineSeparator());
      sb.append(fileSystemEntryList(Paths.get(backupPath))).append(System.lineSeparator());

      return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(sb.toString());
   }
   
   private String fileSystemEntryList(Path path) {
      StringBuilder sb = new StringBuilder();
      try {
         Files.walkFileTree(path, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, new FileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
               sb.append(dir.toAbsolutePath().toString()).append(System.lineSeparator());
               return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
               sb.append(file.toAbsolutePath().toString()).append(System.lineSeparator());
               return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
               return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
               return FileVisitResult.CONTINUE;
            }
         });
      } catch (IOException e) {
         sb.append("ERROR: " + e.getMessage());
         e.printStackTrace();
      }
      return sb.toString();
   }
   
   @RequestMapping("/s3temp/listfiles.do")
   public ResponseEntity<Object> listFiles() {
      
      StringBuilder sb = new StringBuilder();
      
      try {
         String bucketName = monitoringContext.getStringProperty(MonitoringContext.AWS_S3_CM_BUCKET_NAME);
         sb.append("BUCKET : " + bucketName).append(System.lineSeparator());
         
         ListObjectsV2Request listObjectsReqManual = ListObjectsV2Request.builder()
                   .bucket(bucketName)
                   .maxKeys(1000)
                   .build();
         
         boolean done = false;
           while (!done) {
               ListObjectsV2Response listObjResponse = s3Client.listObjectsV2(listObjectsReqManual);
               
               for (S3Object content : listObjResponse.contents()) {
                  sb.append(content.key()).append(System.lineSeparator());
               }

               if (listObjResponse.nextContinuationToken() == null) {
                   done = true;
               }

               listObjectsReqManual = ListObjectsV2Request.builder()
                       .bucket(bucketName)
                       .continuationToken(listObjResponse.nextContinuationToken())
                       .build();
           }

         
      } catch (Exception e) {
         e.printStackTrace();
         sb.append("ERROR:"+e.getMessage()).append(System.lineSeparator());
      }
      
      return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(sb.toString());
      
   }
   
   @RequestMapping("/s3temp/download.do")
   public ResponseEntity<Object> temp(String objectKey) {

      try {
         String bucketName = monitoringContext.getStringProperty(MonitoringContext.AWS_S3_CM_BUCKET_NAME);

         GetObjectRequest getObjectRequest = GetObjectRequest.builder().bucket(bucketName).key(objectKey).build();

         ResponseBytes<GetObjectResponse> objectAsBytes = s3Client.getObjectAsBytes(getObjectRequest);

         return ResponseEntity.ok().header("Content-Disposition", "attachment; filename=TEMP.zip").body(objectAsBytes.asByteArray());
      } catch (Exception e) {
         e.printStackTrace();
         return ResponseEntity.ok().contentType(new MediaType("text", "plain", StandardCharsets.UTF_8)).body(e.getMessage());
      }

   }
   
   @RequestMapping("/sessionTest.do")
   public ResponseEntity<String> session(Integer startIndex) throws Exception {
      
      Integer url2s = startIndex+1;
      
      URL url =  new URL("https://card-ems-"+startIndex+".card-ems.card.svc.cluster.local:8080/monitoring/getId.jsp");
      URL url2 =  new URL("https://card-ems-"+url2s+".card-ems.card.svc.cluster.local:8080/monitoring/getId.jsp");
      
      return ResponseEntity.ok(new StringBuilder().append(getBody(url)).append(System.lineSeparator()).append(getBody(url2)).toString());
   }
   
   private String getBody(URL url) throws IOException {
      
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      connection.setRequestMethod("GET");
      
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
      
      String line;
      StringBuilder response = new StringBuilder();
      while((line = bufferedReader.readLine()) != null) {
         response.append(line);
      }
      response.append(line);
      
      bufferedReader.close();
      
      return response.toString();
   }
   
//   @Autowired @Qualifier("serverService")
//   private ServerService serverService;
   
   @RequestMapping("k8sMergeTest.do")
   public ResponseEntity<String> test1() {
      
      String result = "";
      
      DataSourceContextHolder.setDataSourceType(DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.EAI));
      
      try {
         
         List<Map<String, String>> paramList = new ArrayList<>();
         
         paramList.add(new HashMap<String,String>() {{ put("eaiSevrInstncName", "card-internal-runtime-7f85458c98-cc2z9"); put("sevrLsnPortName", "30510"); put("flovrSevrName", ""); put("hostName", "JOHNCCNS-F6363B"); put("eaiSevrIp", "172.27.176.1"); }});
         paramList.add(new HashMap<String,String>() {{ put("eaiSevrInstncName", "newone"); put("sevrLsnPortName", "1234"); put("flovrSevrName", ""); put("hostName", "sunwookPC"); put("eaiSevrIp", "127.0.0.1"); }});
         
//         serverService.transactionMergeServerList(paramList);
         result = "success";
         
      } catch (Exception e) {
//         System.out.println(e);
         result = e.getMessage();
      }
      
      return ResponseEntity.ok(result);
   }

}