package com.bezkoder.spring.files.upload.controller;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;

import com.bezkoder.spring.files.upload.message.ResponseMessage;
import com.bezkoder.spring.files.upload.model.FileInfo;
import com.bezkoder.spring.files.upload.service.FilesStorageService;
import com.fasterxml.jackson.databind.ObjectMapper;

////Added 07.10.202

import java.io.File;
import java.io.IOException;
//import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.util.EntityUtils;

@CrossOrigin(origins = "*", allowedHeaders = "*") 
@RestController
public class FilesController {
	  @Value("${ser_url}") 
	  String ser_url;
	 @Value("${callser_url}") 
	 String callser_url;
	Logger logger = LogManager.getLogger(FilesController.class);
  @Autowired
  FilesStorageService storageService;
  
  public static void uploadFileRemServer(String serverUrl, String filePath, MultipartFile multipartFile) throws IOException {
      CloseableHttpClient httpClient = HttpClients.createDefault();
      HttpPost httpPost = new HttpPost(serverUrl);
      
      //Create folder make it a function passwing folder nmaes
      String serverUrlFolder = serverUrl + "/FHC";
      
      HttpClient httpClientFolder = HttpClients.createDefault();
      HttpPut httpPut = new HttpPut(serverUrlFolder);
      
      try {
          // Set the content type to text/plain or application/xml, depending on your needs
          httpPut.setHeader("Content-Type", "text/plain");
          
          // Execute the request
          HttpResponse response = httpClientFolder.execute(httpPut);
          
          // Check the HTTP response status
          int statusCode = response.getStatusLine().getStatusCode();
          if (statusCode == org.apache.http.HttpStatus.SC_CREATED) {
              System.out.println("Folder created successfully.");
          } else {
              System.err.println("Failed to create the folder. Status code: " + statusCode);
              org.apache.http.HttpEntity entity = response.getEntity();
              if (entity != null) {
                  String responseContent = EntityUtils.toString(entity);
                  System.err.println("Response content: " + responseContent);
              }
          }
      } catch (Exception e) {
          e.printStackTrace();
      } finally {
          httpPut.releaseConnection();
      }
      
      

      // Create a multipart entity to hold the file
      MultipartEntityBuilder builder = MultipartEntityBuilder.create();
      File file = new File(filePath);
      //builder.addBinaryBody("file", file);
      
      builder.addBinaryBody(
              "file", // The field name for the file upload (you can change this)
              multipartFile.getBytes(),
              ContentType.MULTIPART_FORM_DATA, // Content type for the file
              multipartFile.getOriginalFilename() // The original filename
          );
      

      org.apache.http.HttpEntity multipart = builder.build();
      httpPost.setEntity(multipart);

      try {
          // Execute the request and get the response
          HttpResponse response = httpClient.execute(httpPost);

          // Handle the response, e.g., check for success or print the response content
          if (response.getStatusLine().getStatusCode() == 200) {
              System.out.println("File uploaded successfully.");
          } else {
              System.err.println("File upload failed. Server returned: " + response.getStatusLine());
          }
      } 
      catch (ClientProtocolException e)
      {
          e.printStackTrace();
      } 
      finally 
      {
          httpClient.close();
      }
  }
  
  
  
  
  @RequestMapping(value = "/fundprocess", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE },produces="application/json;charset=utf-8")
//@PostMapping(value="/uploadn")
public String uploadFile(@RequestParam String data,@RequestParam("file") MultipartFile file,HttpServletRequest request, HttpServletResponse response) {
	  LocalTime now = LocalTime.now();
	  System.out.println("Start Tme:  "+now);
	  System.out.println("Params are"+data);
	  //System.out.println("Service link"+ser_url);
	  //System.out.println("Fall back Service link"+callser_url);
	  JSONObject requestJSON=null;
	  JSONObject requestJSONvalid= new JSONObject();
	  JSONObject responseJSON= new JSONObject();
	  String result= "";
	  String val;
	  JSONObject obj=new JSONObject();
	  
	  if (file.getSize() > 0) 
	  {
		  try {
			      requestJSON= new JSONObject(data);
				  obj=new JSONObject(data); 
				  val=validateRequestData(data);
				  System.out.println("val"+val);
				  requestJSONvalid=new JSONObject(val);
				  String valid_status=requestJSONvalid.getString("status_description").toString();
				  if (requestJSON.has("fundus_file_id"))
				  	responseJSON.put("Fundus_File_id", requestJSON.getString("fundus_file_id"));
				  if (requestJSON.has("fhc_id"))
					responseJSON.put("fhc_id", requestJSON.getString("fhc_id"));
				  if (requestJSON.has("uhid"))
					responseJSON.put("uhid", requestJSON.getString("uhid"));
				  if (requestJSON.has("capture_date_time"))
					responseJSON.put("capture_date_time", requestJSON.getString("capture_date_time")); 
					responseJSON.put("Status", "1");
					
				  if(valid_status.equalsIgnoreCase("TRUE"))
				  {  
					  
					  String fhcid = obj.getString("fhc_id");
					  String uhid = obj.getString("uhid");
					  String date = obj.getString("capture_date_time");
					  fhcid=fhcid.trim();
					  uhid=uhid.trim();
					  date=date.trim();
					  System.out.println("fhcid: " +fhcid );
					  // String datenew= //date.substring(0, date.indexOf(' '));
					 // String[] parts = date.split(" "); System.out.println("Date: " + parts[1]);
					  LocalDate daten = LocalDate.now();
					  DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
					  String datenew = daten.format(dateTimeFormatter);
					  DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("HH:mm:ss:nnn");
					  String time= now.format(dateTimeFormatter1);
				 System.out.println("time: " +time );
				 
				 //Added begin
				 
				 String serverUrl = "http://localhost:9091/fundimages"; // Replace with your server's upload endpoint
			        String filePath = "path/to/your/file.txt"; // Replace with the path to the file you want to upload

			        try {
			        	uploadFileRemServer(serverUrl, filePath,file);
			        } catch (IOException e) {
			            e.printStackTrace();
			        }
				  
				 
				 //Added end
				    String img_path=storageService.save(file,fhcid,uhid,datenew,time);
				    //JSONArray fld_retake = new JSONArray();
				    //requestJSON.put("field_to_retake",fld_retake);
				    LocalTime end = LocalTime.now();
					int seconds = (int) ChronoUnit.MILLIS.between(now, end);
					 System.out.println("Upoad Time taken for appln: "+seconds+" Millisec");
					 obj.put("proces_start_time", now);
					 obj.put("upload_time", seconds);
					 obj.put("image_path",img_path);
					 //obj.put("image_path","E:\\CDAC\\apache-tomcat-9.0.62\\webapps\\IDRSTEST\\scripts\\dwvimg\\FHC0001\\09112022\\UHID001\\img_131540.jpg");
				   // System.out.println("requestJSON"+requestJSON);
				    System.out.println("requestJSON"+obj.toString());
				  
				    try {
					    String url=ser_url; //"http://10.176.15.140:8081/DigiPathoDrishti/Fundus/uploadservive/fundus_gddrservice";
					    RestTemplate restTemplate = new RestTemplate();
					    HttpHeaders headers = new HttpHeaders();
					    headers.setContentType(MediaType.APPLICATION_JSON);
					
					    HttpEntity<String> entity = new HttpEntity<String>(obj.toString(),headers);
					    //ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, Object.class);
					    result = restTemplate.postForObject(url, entity, String.class);
					   // ResponseEntity<String> response = restTemplate.put(url, entity);
					    //result = restTemplate.postForObject(uri, requestJSON.toString(), String.class);
					    System.out.println(result);
					    //return result;
					    responseJSON=new JSONObject(result);
				    }
				    catch (Exception ex) {
				    	response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
				    	responseJSON.put("Status_description", "could not connect to service: ");
						}
				}
				  else
				  {
					  response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
						responseJSON.put("Status_description", requestJSONvalid.getString("status_description").toString());
				  }		   
		  } catch (JSONException e) {
			  	 response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
			  	responseJSON.put("Status", "1");
			  	responseJSON.put("Status_description", "Please insert a valid json data");
				
		    }
	 }
	 else
	 {
		 	response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
			responseJSON.put("Status_description", "Please Upload the file");
		 		 
	 }
	  LocalTime last = LocalTime.now();
	  System.out.println("End Tme:  "+last);
	  return responseJSON.toString();
	  
}
  
  

  @RequestMapping(value = "/callback", method = RequestMethod.POST, consumes = { MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE },produces="application/json;charset=utf-8")
public String callback(@RequestParam String data,@RequestParam("file") MultipartFile file,HttpServletRequest request, HttpServletResponse response) {
	  LocalTime now = LocalTime.now();
	  System.out.println("Start Tme:  "+now);
	  System.out.println("Params are"+data);
	  //System.out.println("Service link"+ser_url);
	  //System.out.println("Fall back Service link"+callser_url);
	  JSONObject requestJSON=null;
	  JSONObject requestJSONvalid= new JSONObject();
	  JSONObject responseJSON= new JSONObject();
	  String result= "";
	  String val;
	  JSONObject obj=new JSONObject();
	  
	  if (file.getSize() > 0) 
	  {
		  try {
			      requestJSON= new JSONObject(data);
				  obj=new JSONObject(data); 
				  val=validateRequestData(data);
				  System.out.println("val"+val);
				  requestJSONvalid=new JSONObject(val);
				  String valid_status=requestJSONvalid.getString("status_description").toString();
				  if (requestJSON.has("fundus_file_id"))
				  	responseJSON.put("Fundus_File_id", requestJSON.getString("fundus_file_id"));
				  if (requestJSON.has("fhc_id"))
					responseJSON.put("fhc_id", requestJSON.getString("fhc_id"));
				  if (requestJSON.has("uhid"))
					responseJSON.put("uhid", requestJSON.getString("uhid"));
				  if (requestJSON.has("capture_date_time"))
					responseJSON.put("capture_date_time", requestJSON.getString("capture_date_time")); 
					responseJSON.put("Status", "1");
					
				  if(valid_status.equalsIgnoreCase("TRUE"))
				  {  
					  
					  String fhcid = obj.getString("fhc_id");
					  String uhid = obj.getString("uhid");
					  String date = obj.getString("capture_date_time");
//					  String datenew=date.substring(0, date.indexOf(' '));
//					  String[] parts = date.split(" "); System.out.println("Date: " + parts[1]);
//					  String time=parts[1];
					  LocalDate daten = LocalDate.now();
					  DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
					  String datenew = daten.format(dateTimeFormatter);
					  DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("HH:mm:ss:nnn");
					  String time= now.format(dateTimeFormatter1);
				  //System.out.println("Date: " +date.substring(0, date.indexOf(' ')) );
				    String img_path=storageService.save(file,fhcid,uhid,datenew,time);
				    //JSONArray fld_retake = new JSONArray();
				    //requestJSON.put("field_to_retake",fld_retake);
				    LocalTime end = LocalTime.now();
					int seconds = (int) ChronoUnit.MILLIS.between(now, end);
					 System.out.println("Upoad Time taken for appln: "+seconds+" Millisec");
					 obj.put("proces_start_time", now);
					 obj.put("upload_time", seconds);
					 obj.put("image_path",img_path);
					 //obj.put("image_path","E:\\CDAC\\apache-tomcat-9.0.62\\webapps\\IDRSTEST\\scripts\\dwvimg\\FHC0001\\09112022\\UHID001\\img_131540.jpg");
				   // System.out.println("requestJSON"+requestJSON);
				    System.out.println("requestJSON"+obj.toString());
				  
				    try {
					    String url=callser_url; //"http://10.176.15.140:8081/DigiPathoDrishti/Fundus/uploadservive/fundus_gddrservice";
					    RestTemplate restTemplate = new RestTemplate();
					    HttpHeaders headers = new HttpHeaders();
					    headers.setContentType(MediaType.APPLICATION_JSON);
					
					    HttpEntity<String> entity = new HttpEntity<String>(obj.toString(),headers);
					    //ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.POST, entity, Object.class);
					    result = restTemplate.postForObject(url, entity, String.class);
					   // ResponseEntity<String> response = restTemplate.put(url, entity);
					    //result = restTemplate.postForObject(uri, requestJSON.toString(), String.class);
					    System.out.println(result);
					    //return result;
					    responseJSON=new JSONObject(result);
				    }
				    catch (Exception ex) {
				    	response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
				    	responseJSON.put("Status_description", "could not connect to service: ");
						}
				}
				  else
				  {
					  response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
						responseJSON.put("Status_description", requestJSONvalid.getString("status_description").toString());
				  }		   
		  } catch (JSONException e) {
			  	 response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
			  	responseJSON.put("Status", "FAILURE");
			  	responseJSON.put("Status_description", "Please insert a valid json data");
				
		    }
	 }
	 else
	 {
		 	response.setStatus( HttpServletResponse.SC_BAD_REQUEST);
			responseJSON.put("Status_description", "Please Upload the file");
		 		 
	 }
	  LocalTime last = LocalTime.now();
	  System.out.println("End Tme:  "+last);
	  return responseJSON.toString();  
} 
  
 
  
  
  
  
 public static String validateRequestData(String datanew)
 {
	 JSONObject requestJSON= new JSONObject(datanew);
	 JSONObject responseJSON=new JSONObject();
	 System.out.println("In validation" );
	 
	 if (requestJSON.has("fundus_file_id")) {
	 String fundus_file_id = requestJSON.getString("fundus_file_id");
		 if (fundus_file_id.trim().equals(""))
		 {
			 System.out.println("fundus_file_id" );
			 responseJSON.put("status_description", "Please insert value of fundus_file_id");	
			 return responseJSON.toString();
		 }
	 }
	 else
	 {
		responseJSON.put("status_description", "fundus_file_id is undefined");
	 	return responseJSON.toString();
 	 }
	 
	 
	 if (requestJSON.has("fhc_id")) {	 
		 String fhc_id = requestJSON.getString("fhc_id");
		 if (fhc_id.trim().equals(""))
		 {
			 System.out.println("fhc_id" );
			 responseJSON.put("status_description", "Please insert value of fhc_id");	
			 return responseJSON.toString();
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "fhc_id is undefined");
	 	return responseJSON.toString();
 	 }
	 
	 if (requestJSON.has("uhid")) {
		 String uhid = requestJSON.getString("uhid");
		 if (uhid.trim().equals(""))
		 {
			 System.out.println("uhid" );
			 responseJSON.put("status_description", "Please insert value of uhid");
			 return responseJSON.toString();
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "uhid is undefined");
	 	return responseJSON.toString();
 	 }
	 
	 if (requestJSON.has("patient_name")) {
		 String patient_name = requestJSON.getString("patient_name");
		 if (patient_name.trim().equals(""))
		 {
			 System.out.println("patient_name" );
			 responseJSON.put("status_description", "Please insert valid patient_name");
			 return responseJSON.toString();
		 }
		 else
		 {
			boolean valid=patient_name.matches("(?i)(^[a-z])((?![ .,'-]$)[a-z .,'-]){0,24}$");
			if(valid==false)
			{
				responseJSON.put("status_description", "Please insert valid patient_name");
				 return responseJSON.toString();
			}
			//System.out.println("patient_name" +valid);
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "patient_name is undefined");
		 return responseJSON.toString();
	 }
	 
	 if (requestJSON.has("date_of_birth")) {
		 String date_of_birth = requestJSON.getString("date_of_birth");
		 if (date_of_birth.trim().equals(""))
		 {
			 System.out.println("date_of_birth" );
			 responseJSON.put("status_description", "Please insert value of date_of_birth in dd-MM-yyyy format");
			 return responseJSON.toString();
		 }
		 else
		 {
			 //System.out.println("date_of_birth format" );
			 SimpleDateFormat sdfrmt = new SimpleDateFormat("dd-MM-yyyy");
			 sdfrmt.setLenient(false);
			 try {
				 sdfrmt.parse(date_of_birth);
		        } catch (ParseException e) {
		        	responseJSON.put("status_description", "date_of_birth should be in dd-MM-yyyy format");	
		        	 return responseJSON.toString();
		        }
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "date_of-birth is undefined");
		 return responseJSON.toString();
	 }
	 
	 if (requestJSON.has("capture_date_time")) {
		 String capture_date_time = requestJSON.getString("capture_date_time");
		 if (capture_date_time.trim().equals(""))
		 {
			 System.out.println("capture_date_time" );
			 responseJSON.put("status_description", "Please insert value of capture_date_time in dd-MM-yyyy HH:mm:ss format");	
			 return responseJSON.toString();
		 }
		 else
		 {
			 //System.out.println("date_of_birth format" );
			 SimpleDateFormat sdfrmt = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
			 sdfrmt.setLenient(false);
			 try {
				 sdfrmt.parse(capture_date_time);
		        } catch (ParseException e) {
		        	responseJSON.put("status_description", "capture_date_time should be in dd-MM-yyyy HH:mm:ss format");	
		        	 return responseJSON.toString();
		        }
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "capture_date_time is undefined");
		 return responseJSON.toString();
	 }
	 
	 if (requestJSON.has("retake")) {
		 String retake = requestJSON.getString("retake");
		 if (retake.trim().equals(""))
		 {
			 System.out.println("retake" );
			 responseJSON.put("status_description", "Please insert value of retake(Y/N)");	
			 return responseJSON.toString();
		 }
		 else
		 {
			 if (!(retake.equals("Y") || retake.equals("N")))
			 {
				 responseJSON.put("status_description", "Please insert valid value (Y/N) of retake");
				 return responseJSON.toString();
			 }
		 }
	  }
	 else
	 {
		 responseJSON.put("status_description", "retake is undefined");
		 return responseJSON.toString();
	 }
	 
	 if (requestJSON.has("field_definition_info")) {
		 String field_definition_info = requestJSON.getString("field_definition_info");
		 if (field_definition_info.trim().equals(""))
		 {
			 System.out.println("field_definition_info" );
			 responseJSON.put("status_description", "Please insert value of field_definition_info {LD,LF,RD,RF}");
			 return responseJSON.toString();
		 }
		 else
		 {
			 if (!(field_definition_info.equals("LD") || field_definition_info.equals("LF") || field_definition_info.equals("RF") ||field_definition_info.equals("RD")))
			 {
				 responseJSON.put("status_description", "Please insert valid value {LD,LF,RD,RF} of field_definition_info");
				 return responseJSON.toString();
			 }
			 
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "field_definition_info is undefined");
		 return responseJSON.toString();
	 }
	 
	 if (requestJSON.has("last_image_of_patient")) {
		 String last_image_of_patient = requestJSON.getString("last_image_of_patient");	
		 if (last_image_of_patient.trim().equals(""))
		 {
			 System.out.println("last_image_of_patient" );
			 responseJSON.put("status_description", "Please insert value of last_image_of_patient(Y/N)");
			 return responseJSON.toString();
		 }
		 else
		 {
			 if (!(last_image_of_patient.equals("Y") || last_image_of_patient.equals("N")))
			 {
				 responseJSON.put("status_description", "Please insert valid value (Y/N) of last_image_of_patient");
				 return responseJSON.toString();
			 }
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "last_image_of_patient is undefined");
		 return responseJSON.toString();
	 }
	 				
	 if (requestJSON.has("total_image_count")) {
		 String total_image_count = requestJSON.getString("total_image_count");	
		 if (total_image_count.trim().equals(""))
		 {
			 System.out.println("total_image_count" );
			 responseJSON.put("status_description", "Please insert value of total_image_count");	
			 return responseJSON.toString();
		 }
		 else
		 {
			 if(!(total_image_count.matches("[0-9]+")))
			 {
				 responseJSON.put("status_description", "Please insert valid no: of total_image_count");	
				 return responseJSON.toString();
			 }
		 }
	 }
	 else
	 {
		 responseJSON.put("status_description", "total_image_count is undefined");
		 return responseJSON.toString();
	 }
	 
	
	
	// System.out.println("success validation" );
	 responseJSON.put("status_description", "TRUE");	
	 return responseJSON.toString();
 }
	/* @GetMapping("/files") public ResponseEntity<List<FileInfo>> getListFiles() {
	 List<FileInfo> fileInfos = storageService.loadAll().map(path -> { String
	 filename = path.getFileName().toString(); String url =
	 MvcUriComponentsBuilder .fromMethodName(FilesController.class, "getFile",
	 path.getFileName().toString()).build().toString();
	 
	 return new FileInfo(filename, url); }).collect(Collectors.toList());
	 
	 return ResponseEntity.status(HttpStatus.OK).body(fileInfos); }
	

  @GetMapping("/files/{filename:.+}")
  public ResponseEntity<Resource> getFile(@PathVariable String filename) {
    Resource file = storageService.load(filename);
    return ResponseEntity.ok()
        .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
  }*/
}
