package com.hepl.tunefortwo.controller;

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.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import javax.sound.sampled.UnsupportedAudioFileException;

import org.springframework.cglib.core.Local;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.util.StreamUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import com.hepl.tunefortwo.config.i18n.Translator;
import com.hepl.tunefortwo.dto.ContactDto;
import com.hepl.tunefortwo.dto.FormRequestDto;
import com.hepl.tunefortwo.dto.GenericData;
import com.hepl.tunefortwo.dto.GenericResponse;
import com.hepl.tunefortwo.dto.OrderPosition;
import com.hepl.tunefortwo.dto.OrderTrackerDto;
import com.hepl.tunefortwo.entity.Contact;
import com.hepl.tunefortwo.entity.FileType;
import com.hepl.tunefortwo.entity.Form;
import com.hepl.tunefortwo.entity.MasterPayment;
import com.hepl.tunefortwo.service.AudioService;
import com.hepl.tunefortwo.service.ContactService;
import com.hepl.tunefortwo.service.FileService;
import com.hepl.tunefortwo.service.FormService;
import com.hepl.tunefortwo.service.OtpService;
import com.hepl.tunefortwo.utils.AppMessages;
import com.hepl.tunefortwo.utils.JwtUtils;
import com.hepl.tunefortwo.utils.ValidPhoneNumber;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.log.SysoCounter;

import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.mail.MessagingException;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.ConstraintViolationException;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;


@Tag(name = "Create and Manage Form", description = "")
//@SecurityRequirement(name = "Bearer Authentication")
@RestController
@RequestMapping("/v1/form")
@Slf4j

public class FormController {
	private final Translator translator;
    private final FormService formService;
    private final FileService fileService;
    private final AudioService audioService;
    private final ContactService contactService;
    private final JwtUtils jwtUtils;
    private final OtpService otpService;
    
    public FormController(Translator translator, FormService formService,FileService fileService, AudioService audioService,ContactService contactService,JwtUtils jwtUtils,OtpService otpService) {
		this.translator = translator;
		this.formService = formService;
		this.fileService = fileService;
		this.audioService = audioService;
		this.contactService = contactService;
		this.jwtUtils = jwtUtils;
		this.otpService = otpService;
	}
    
    @PostMapping(consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
    public GenericResponse addUser(@Valid @ModelAttribute FormRequestDto formRequestDto)
            throws MessagingException, IOException {
        log.info("Adding Songs for  Form");
        String phoneNumber = formRequestDto.getPhonenumber();

        // Extract the country code and national number
        String[] phoneComponents = formService.extractCountryCodeAndNationalNumber(phoneNumber);
        String countryCode = phoneComponents[0];
        String nationalNumber = phoneComponents[1];

        if (countryCode == null || nationalNumber == null || !formService.validateMobileNumber(countryCode, nationalNumber)) {
            // Return an error response with appropriate message
            GenericResponse response = new GenericResponse(false); // Set status to false
            response.setMessage("Invalid mobile number format or number");
            response.setErrorType("INVALID_PHONE_NUMBER"); // Optional: Define error type if needed
            return response;
        }
        if (formRequestDto.getClip() != null) {
        	
                 String originalFilename = formRequestDto.getClip().getOriginalFilename();
                 if (originalFilename != null) {
                     String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                     List<String> allowedExtensions = Arrays.asList("mp3", "wav","OGG","AAC");
                     if (!allowedExtensions.contains(fileExtension.toLowerCase())) {
                         throw new MessagingException("Only MP3,AAC, and WAV files are allowed");
                     }
                 }
              
        	String filename=fileService.uploadFile(formRequestDto.getClip() , FileType.CLIP);
        	Resource file = fileService.loadAsResource(filename, FileType.CLIP);
           formRequestDto.setClipPath(filename);    
           Path filePath = Paths.get(file.getURI());
           System.out.println("FilePath while posting---"+filePath);
           double durationInSecondsOne = audioService.getAudioDuration(filePath.toFile());
           formRequestDto.setClipDuration(durationInSecondsOne);
           long durationRoundOne = (long)Math.floor(durationInSecondsOne);
           long inMinutes = durationRoundOne/60;
           long inSeconds = durationRoundOne%60;
           String inFormattedTime = String.format("%02d:%02d", inMinutes, inSeconds);
           formRequestDto.setDurationInMMSS(inFormattedTime);
           if(formRequestDto.getClipDuration() == null) {
	           double durationInSeconds = audioService.getAudioDuration(filePath.toFile());
	           formRequestDto.setClipDuration(durationInSeconds);
	           long durationRound = (long)Math.floor(durationInSeconds);
	           long minutes = durationRound/60;
	           long seconds = durationRound%60;
	           String formattedTime = String.format("%02d:%02d", minutes, seconds);
	           formRequestDto.setDurationInMMSS(formattedTime);
           }
           
        }
       Form form = formService.saveForm(formRequestDto);

        GenericResponse response = new GenericResponse(true);
        response.setMessage(translator.toLocale(AppMessages.SONG_SAVED)+"id : "+form.getId());
        return response;
    }

    @GetMapping("/paginated")
    public GenericResponse getAllForms(
////    		@RequestParam(defaultValue = "0") int page,
////            @RequestParam(defaultValue = "10") int sizePerPage,
//            @RequestParam(defaultValue = "DESC", value = "sortDirection") Sort.Direction sortDirection,
//            @RequestParam(defaultValue = "") String query,
    		  @RequestParam(defaultValue = "0") int page,
    	      @RequestParam(defaultValue = "10") int size,
    	      @RequestParam(defaultValue = "orderPosition.updatedDate") String sortBy,
    	      @RequestParam(defaultValue = "desc") String sortDirection,
    	      @RequestParam(value = "query", required = false) String query,
    	      Authentication authentication) {
                if (authentication == null || !authentication.isAuthenticated()) {
    	        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Unauthorized");
    	    }
    	boolean isAdmin = false;
	    if (authentication instanceof JwtAuthenticationToken) {
	        JwtAuthenticationToken jwtAuthToken = (JwtAuthenticationToken) authentication;
	        Jwt jwt = jwtAuthToken.getToken();
	        String tokenValue = jwt.getTokenValue();
	        Claims claims = jwtUtils.extractClaims(tokenValue);
	        String email = claims.getSubject();
	        Map<String, Object> userDetails = (Map<String, Object>) claims.get("userDetails");
	        if (userDetails != null) {
	            String roleId = (String) userDetails.get("roleId");
	            String userId = (String) userDetails.get("id");
	            if (roleId.equals("1")) {
	                isAdmin = true;
	            }
	        }
	    }

//	    if (!isAdmin) {
//	        ResponseEntity<String> response = ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Unauthorized");
//	        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Unauthorized");
//	    }
    	
        Sort sort = Sort.by(sortDirection, "orderPosition.updatedDate");
        Sort.Direction direction = sortDirection.equalsIgnoreCase("desc") ? Sort.Direction.DESC : Sort.Direction.ASC;
        Pageable pageable = PageRequest.of(page, size,Sort.by(direction, sortBy));
        log.info("Fetching forms...");
        //Pageable pageable = PageRequest.of(page, sizePerPage,sort);
        //Pageable pageable = PageRequest.of(sort);
        //log.info("Pagination details: Page {}, SizePerPage {}, SortDirection {}.", page, sizePerPage, sortDirection);
        GenericResponse response = new GenericResponse(true);
//        Page<FormRequestDto> formsPage = formService.allForms(pageable, query);
        Map<String, Object> formsPage = formService.allForms(pageable,isAdmin,query);
        GenericData data = new GenericData();
        data.setFormRequestDtos(formsPage);
        response.setData(data);
        return response;
    }
    
    @GetMapping("/")
    public GenericResponse getAllFormsByStatus(@RequestParam OrderPosition position, Authentication authentication) {
        if (authentication == null || !authentication.isAuthenticated()) {
    	        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Unauthorized");
    	    }
        log.info("Fetching forms by orderPosition...");
        boolean isAdmin = false;// roles.contains("ROLE_ADMIN");
        boolean isUser = false;
        try {
        	String sortDirection = "DESC";
            // Extract roles from Authentication object
            if (authentication instanceof JwtAuthenticationToken) {
                JwtAuthenticationToken jwtAuthToken = (JwtAuthenticationToken) authentication;
                Jwt jwt = jwtAuthToken.getToken();
                String tokenValue = jwt.getTokenValue();
                Claims claims = jwtUtils.extractClaims(tokenValue);
                String email = claims.getSubject(); // Retrieve the email from the subject claim

                // Retrieve userDetails as a Map
                Map<String, Object> userDetails = (Map<String, Object>) claims.get("userDetails");

                if (userDetails != null) {
                    String roleId = (String) userDetails.get("roleId"); 
                    String userId = (String) userDetails.get("id"); 
                    if(roleId.equals("1")) {
                    	isAdmin=true;
                    }
                   
                } else {
                    System.out.println("No userDetails found in claims.");
                }
               
            }else {
            	log.debug("Not a valid JWT Token}");	
            }
         

            // Check roles and restrict fields accordingly
           // roles.contains("ROLE_USER");
        	Sort sort = Sort.by(Sort.Direction.fromString(sortDirection), "orderPosition.updatedDate");
        	 GenericResponse response = new GenericResponse(true);
        
        	 Map<String, Object> formsPage = formService.getFormsByOrderPosition(position,sort,isAdmin);
            GenericData data = new GenericData();
            data.setFormDtos(formsPage);
            response.setData(data);
            return response;
        	 
        	 
        } catch (Exception e) {
            log.error("Error occurred while fetching forms: {}", e.getMessage());
            System.out.println(e.getMessage());
            return new GenericResponse(false);
        }
    }
    
    @GetMapping("/{id}")
    public GenericResponse getAllFormsByStatus(@PathVariable String id) {
        log.info("Fetching forms by orderPosition...");
        GenericResponse response = new GenericResponse(true);
   	 	FormRequestDto formsPage = formService.getFormById(id);
   	 	GenericData data = new GenericData();
   	 	data.setFormRequestDto(formsPage);
   	 	response.setData(data);
   	 	return response;
    }
    
    @PutMapping(value = "/{id}", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
    public GenericResponse updateSongStatus(@RequestParam OrderPosition orderPosition,
                                            @RequestParam(value = "file", required = false) MultipartFile audio,
                                            @PathVariable("id") String id)
            throws IOException, DocumentException, MessagingException {
        log.info("Update song status");

        
        if (audio != null) {
            String originalFilename = audio.getOriginalFilename();
            if (originalFilename != null) {
                String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                List<String> allowedExtensions = Arrays.asList("mp3", "wav","OGG","AAC");
                if (!allowedExtensions.contains(fileExtension.toLowerCase())) {
                    throw new MessagingException("Only MP3,AAC,OGG, and WAV files are allowed");
                }
            }
        } else {
            
            if (orderPosition == OrderPosition.DELIVERED) {
                throw new MessagingException("For Delivered Orderposition, File attachment is necessary");
            }
        }
  
        
        String filePath = "";
        if (audio != null) {
            filePath = fileService.uploadFile(audio, FileType.CLIP);
        }


        String updatedStatus = formService.updateOrderPosition(orderPosition, id, filePath);

        
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
        data.setId(id);
        data.setStatus(orderPosition.toString());
        response.setData(data);

        String msg = "from : "+orderPosition.toString()+" to :"+" "+ updatedStatus;
        response.setMessage(translator.toLocale(AppMessages.SONG_STATUS_UPDATED_SUCCESSFULLY)+msg);

        return response;
    }

    @GetMapping("/song/{filename}")
    public ResponseEntity<StreamingResponseBody> serveFile(@PathVariable String filename, @RequestHeader HttpHeaders headers) throws IOException {
        log.info("Get filename .. {}", filename);

        Resource file = fileService.loadAsResource(filename, FileType.CLIP);
        if (file == null) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, AppMessages.FILE_NOT_FOUND);
        }

        Path filePath = Paths.get(file.getURI());
        if (!Files.exists(filePath)) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, AppMessages.FILE_NOT_FOUND);
        }

        String contentType = Files.probeContentType(filePath);
        if (contentType == null) {
            contentType = "application/octet-stream";
        }

        long fileLength = Files.size(filePath);
        long rangeStart = 0;
        long rangeEnd = fileLength - 1;

        String range = headers.getFirst(HttpHeaders.RANGE);
        if (range != null) {
            String[] ranges = range.replace("bytes=", "").split("-");
            rangeStart = Long.parseLong(ranges[0]);
            if (ranges.length > 1 && !ranges[1].isEmpty()) {
                rangeEnd = Long.parseLong(ranges[1]);
            }
        }

        
        rangeStart = Math.max(rangeStart, 0);
        rangeEnd = Math.min(rangeEnd, fileLength - 1);
        final long finalRangeStart = rangeStart;
        final long finalRangeEnd = rangeEnd;
        final long finalFileLength = fileLength;

        long contentLength = finalRangeEnd - finalRangeStart + 1;

        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add(HttpHeaders.CONTENT_TYPE, contentType);
        responseHeaders.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));
        responseHeaders.add(HttpHeaders.ACCEPT_RANGES, "bytes");
        responseHeaders.add(HttpHeaders.CONTENT_RANGE, String.format("bytes %d-%d/%d", finalRangeStart, finalRangeEnd, finalFileLength));

        StreamingResponseBody responseBody = outputStream -> {
            try (InputStream inputStream = Files.newInputStream(filePath)) {
                inputStream.skip(finalRangeStart);
                byte[] buffer = new byte[8192];
                long bytesToRead = contentLength;
                int bytesRead;
                while (bytesToRead > 0 && (bytesRead = inputStream.read(buffer, 0, (int) Math.min(buffer.length, bytesToRead))) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                    bytesToRead -= bytesRead;
                }
            }
        };

        return new ResponseEntity<>(responseBody, responseHeaders, HttpStatus.PARTIAL_CONTENT);
    }
    
    @GetMapping("/songDownload/{filename}")
    public ResponseEntity<byte[]> serveFile(@PathVariable String filename) throws IOException, UnsupportedAudioFileException {
        log.info("Get filename .. {}", filename);

        Resource file = fileService.loadAsResource(filename, FileType.CLIP);
        if (file == null) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, AppMessages.FILE_NOT_FOUND);
        }

        String fileNameNew = file.getFilename();
        String modifiedFilename = fileNameNew.replaceAll("^\\d+-", "");

        
        Path filePath = Paths.get(file.getURI());
        double durationInSeconds = audioService.getAudioDuration(filePath.toFile());
        System.out.println(durationInSeconds);

        
        String mimeType = Files.probeContentType(filePath);

        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + modifiedFilename + "\"")
                .header("Audio-Duration", String.valueOf(durationInSeconds))
                .contentType(MediaType.parseMediaType(mimeType != null ? mimeType : "application/octet-stream"))
                .body(file.getContentAsByteArray());
    }


    
    @PutMapping(value = "/form-update/{id}",consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
    public GenericResponse updateSong( @ModelAttribute FormRequestDto dto,
            @PathVariable("id") String id)
            throws IOException, DocumentException, MessagingException {
        log.info("Update song status");
        formService.updateForm(dto, id);
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
//        data.setId(id);
//        data.setStatus(dto.getOrderPosition().toString());
        response.setData(data);
        response.setMessage(translator.toLocale(AppMessages.SONG_UPDATED_SUCCESSFULLY));

        return response;
    }
    
    @GetMapping("/orderTracker")
    public GenericResponse getAllFormsByStatus(@RequestParam String mobileNumber, @RequestParam String orderNumber) {
        log.info("Fetching forms by orderPosition for mobile number: {} and order number: {}", mobileNumber, orderNumber);
        GenericResponse response = new GenericResponse(true);
        List<Object> formsPage = formService.trackerOrder(mobileNumber, orderNumber);
        GenericData data = new GenericData();
        data.setTracker(formsPage);
        response.setData(data);

        return response;
    }

    
    @PutMapping(value = "/add-screenshot/{orderNumber}")
    public GenericResponse addScreenShot( @RequestParam(value = "file",required = false) MultipartFile file,
            @PathVariable("orderNumber") String orderNumber)
            throws IOException, DocumentException {
        log.info("Update screenshot");
        String filePath = null;
        if (file != null) {
        	String originalFilename = file.getOriginalFilename();
            if (originalFilename != null) {
                String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                List<String> allowedExtensions = Arrays.asList("jpeg","png","jpg","BMP");
                if (!allowedExtensions.contains(fileExtension.toLowerCase())) {
                    throw new IOException("Only Jpeg,Jpg,BMP and Png files are supported");
                }
            }
            filePath =fileService.uploadFile(file , FileType.CLIP);
         }
        if (file == null || file.isEmpty()) {
            
            throw new IllegalArgumentException("No file provided for updating screenshot");
        }
        formService.addScreenShot(orderNumber, filePath);
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
        data.setId(orderNumber);
        response.setData(data);
        response.setMessage(translator.toLocale(AppMessages.SCREENSHOTADDED_SUCCESSFULLY));

        return response;
    }
    
    @PutMapping(value = "/add-comment/{orderNumber}")
    public GenericResponse addComment( @PathVariable("orderNumber") String orderNumber,
    		                           @RequestParam(value = "comment",required = false) String comment,
    		                           @RequestParam(value = "deliverydate", required = false) LocalDate date)
            throws IOException, DocumentException, MessagingException {
        log.info("Update comment");
        formService.addcomment(orderNumber, comment, date, orderNumber);
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
        data.setId(orderNumber);
        response.setData(data);
        response.setMessage(translator.toLocale(AppMessages.COMMENTS_ADDED_SUCCESSFULLY));
        return response;
    }
    
    
//	@PutMapping(value = "/rating-review/{id}",consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
//	public GenericResponse updateRatingAndReviewForForm(@PathVariable("id") String id,
//			@RequestParam(value = "rating",required =true) int rating, @RequestParam(value = "review",required =false) String review,
//			@RequestParam(required = false) MultipartFile image, @RequestParam(required = false) MultipartFile video)
//			throws IOException {
//		String imagepath = null, videopath = null;
//		if (image != null) {
//			imagepath = fileService.uploadFile(video, FileType.CLIP);
//		}
//		if (video != null) {
//			videopath = fileService.uploadFile(video, FileType.CLIP);
//		}
//		formService.updateRatingAndReview(rating, review, id, imagepath, videopath);
//		GenericResponse response = new GenericResponse(true);
//		GenericData data = new GenericData();
//		data.setId(id);
//		response.setData(data);
//		response.setMessage(translator.toLocale(AppMessages.RATINGANDREVIEW_UPDATED));
//		return response;
//	}
    @PutMapping(value = "/rating-review/{id}",consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
	public GenericResponse updateRatingAndReviewForForm(@PathVariable("id") String id,
			@RequestParam(value = "rating",required =true) int rating, @RequestParam(value = "review",required =false) String review,
			@RequestParam(required = false) List<MultipartFile> images, @RequestParam(required = false) MultipartFile video)
			throws IOException {
		List<String> imagePaths = new ArrayList();
		String videopath = null;
		if (images != null && images.size() > 0) {
            for (MultipartFile image : images) {
            	String originalFilename = image.getOriginalFilename();
                if (originalFilename != null) {
                    String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                    List<String> allowedExtensions = Arrays.asList("jpeg","png","jpg","BMP");
                    if (!allowedExtensions.contains(fileExtension.toLowerCase())) {
                        throw new IOException("Only Jpeg,Jpg,BMP and Png files are supported");
                    }
                }
            	String imagepathForOneImage = fileService.uploadFile(image, FileType.CLIP);
            	imagePaths.add(imagepathForOneImage);
            }
        }
		if (video != null) {
			String originalFilename = video.getOriginalFilename();
            if (originalFilename != null) {
                String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
                List<String> allowedExtensions = Arrays.asList("mp4","MKV","FLV","AVI","WMV");
                if (!allowedExtensions.contains(fileExtension.toLowerCase())) {
                    throw new IOException("Only MP4,WMV,MKV,FLV, and AVI files are supported");
                }
            }
			videopath = fileService.uploadFile(video, FileType.CLIP);
		}
		formService.updateRatingAndReview(rating, review, id, imagePaths, videopath);
		GenericResponse response = new GenericResponse(true);
		GenericData data = new GenericData();
		data.setId(id);
		response.setData(data);
		response.setMessage(translator.toLocale(AppMessages.RATINGANDREVIEW_UPDATED));
		return response;
	}
    
	@PostMapping(value = "/contactus",consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
    public GenericResponse addUser(@Valid @ModelAttribute ContactDto contactDto) throws MessagingException {
	 Contact newContact = new Contact();
	 newContact.setMail(contactDto.getEmail());
	 newContact.setMessage(contactDto.getMessage());
	 newContact.setName(contactDto.getName());
	 newContact.setPhonenumber(contactDto.getMobileNumber());
	 Contact savedContact = contactService.saveContact(newContact);
	 GenericResponse response = new GenericResponse(true);
	 GenericData data = new GenericData();
	 data.setContact(savedContact);
	 response.setMessage(" Contact Message Saved");
	 return response;
	 
	 
	}
	@GetMapping(value = "/rating-review/{id}")
	  public GenericResponse getRatingandReview(@PathVariable("id") String id)
				
				throws IOException{
		        String imagepath = null, videopath = null;
		        try {
			FormRequestDto formPage= formService.getRatingandReview(id);
			 GenericResponse response = new GenericResponse(true);
			 GenericData data = new GenericData();
			 data.setFormRequestDto(formPage);
			 response.setData(data);
			 return response;
		        }
		        catch(Exception e) {
		         log.error("Error occured while fetching form: {}", e.getMessage());	
		         System.out.println(e.getMessage());
		         return new GenericResponse(false);
		        }
				
	  }
	
	@PutMapping("/rejectForm/{id}")
	public GenericResponse rejectAForm(@PathVariable String id, @RequestParam String formStatus) {
		FormRequestDto modifiedStatusOfThForm = formService.rejectAFormByItsId(id, formStatus);
		GenericResponse response = new GenericResponse(true);
		 GenericData data = new GenericData();
		 data.setFormRequestDto(modifiedStatusOfThForm);
		 response.setData(data);
		 return response;
	}
        
    @GetMapping("/getrejectedforms")
    public GenericResponse getAllRejectedForms(@RequestParam String activeStatus) {
    	Map<String,Object> availableForms = formService.getAllRejectedForms(activeStatus);
    	GenericResponse response = new GenericResponse(true);
		 GenericData data = new GenericData();
		 data.setFormRequestDtos(availableForms);
		 response.setData(data);
		 return response;
    	
    }
    
//    @GetMapping("/export")
//    public void exportToExcel(
//        @RequestParam LocalDate startDate,
//        @RequestParam LocalDate endDate,
//        HttpServletResponse response
//    ) throws IOException {
//        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
//        response.setHeader("Content-Disposition", "attachment; filename=forms.xlsx");
//        formService.exportToExcel(startDate, endDate, response.getOutputStream());
//    }
    
    @PostMapping("/send-otp")
    public ResponseEntity<String> sendOtp(@RequestParam String email,String name) throws MessagingException {
        otpService.sendOtp(email,name);
        return ResponseEntity.ok("OTP sent to " + email);
    }

    @PostMapping("/verify-otp")
    public ResponseEntity<String> verifyOtp(@RequestParam String email, @RequestParam String otp) {
        boolean isValid = otpService.verifyOtp(email, otp);
        if (isValid) {
            return ResponseEntity.ok("OTP verified successfully!");
        } else {
            return ResponseEntity.badRequest().body("Invalid OTP.");
        }
    }
    
    @PostMapping("/resend-otp")
    public ResponseEntity<String> resendOtp(@RequestParam String email,String name) {
        try {
            otpService.resendOtp(email,name);
            return ResponseEntity.ok("OTP resent successfully.");
        } catch (IllegalStateException e) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
        } catch (MessagingException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to resend OTP.");
        }
    }
    
//    @GetMapping("/validatemobilenumber")
//    public ResponseEntity<String> validateNumber(@RequestParam @ValidPhoneNumber String mobileNumber) {
//        try {
//            // Your validation logic if needed; @ValidPhoneNumber should handle this
//            return ResponseEntity.ok("Phone number is valid");
//        } catch (ConstraintViolationException e) {
//            // Handle invalid phone number
//            return ResponseEntity.badRequest().body("Invalid phone number");
//        } catch (Exception e) {
//            // Handle other potential exceptions
//            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("An unexpected error occurred");
//        }
//    }
    
    @GetMapping("/validatemobilenumber")
    public ResponseEntity<String> validateNumber(@RequestParam String countryCode, @RequestParam String mobileNumber) {
        boolean isValid = formService.validateMobileNumber(countryCode, mobileNumber);
        
        if (isValid) {
            return ResponseEntity.ok("Valid mobile number");
        } else {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Invalid mobile number");
        }
    }
    
    @GetMapping("/mobile-number-info")
    public ResponseEntity<String> getNumberInfo(@RequestParam String countryCode, @RequestParam String mobileNumber){
    	return ResponseEntity.ok(formService.getNumberInfo(countryCode, mobileNumber));
    }
    
    @GetMapping("/genericFormSearch")
    public GenericResponse genericOrderSearch(@RequestParam("query") String query,
  	      Authentication authentication){
    	if (authentication == null || !authentication.isAuthenticated()) {
	        throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Unauthorized");
	    }
	boolean isAdmin = false;
    if (authentication instanceof JwtAuthenticationToken) {
        JwtAuthenticationToken jwtAuthToken = (JwtAuthenticationToken) authentication;
        Jwt jwt = jwtAuthToken.getToken();
        String tokenValue = jwt.getTokenValue();
        Claims claims = jwtUtils.extractClaims(tokenValue);
        String email = claims.getSubject();
        Map<String, Object> userDetails = (Map<String, Object>) claims.get("userDetails");
        if (userDetails != null) {
            String roleId = (String) userDetails.get("roleId");
            String userId = (String) userDetails.get("id");
            if (roleId.equals("1")) {
                isAdmin = true;
            }
        }
    }
    	
    	
    	 GenericResponse response = new GenericResponse(true);
       Map<String, Object> formsPage = formService.genericFormSearch(query,isAdmin);
       GenericData data = new GenericData();
       data.setFormRequestDtos(formsPage);
       response.setData(data);
       return response;

    }


}
