package com.hepl.tunefortwo.controller;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.sound.sampled.UnsupportedAudioFileException;

import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.web.bind.annotation.DeleteMapping;
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.RequestBody;
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.server.ResponseStatusException;

import com.hepl.tunefortwo.config.i18n.Translator;
import com.hepl.tunefortwo.dto.GenericData;
import com.hepl.tunefortwo.dto.GenericResponse;
import com.hepl.tunefortwo.dto.PaymentDto;
import com.hepl.tunefortwo.entity.FileType;
import com.hepl.tunefortwo.service.FileService;
import com.hepl.tunefortwo.service.PaymentService;
import com.hepl.tunefortwo.utils.AppMessages;
import com.hepl.tunefortwo.utils.JwtUtils;

import io.jsonwebtoken.Claims;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.mail.MessagingException;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;

@Tag(name = "Create and Manage Payment", description = "")
//@SecurityRequirement(name = "Bearer Authentication")
@RestController
@RequestMapping("/v1/payment")
@Slf4j
public class PaymentController {
	
	private final PaymentService paymentService;
	private final Translator translator;
	private final FileService fileService;
	private final JwtUtils jwtUtils;
	
	public PaymentController(PaymentService paymentService, Translator translator, FileService fileService,JwtUtils jwtUtils) {
		this.paymentService = paymentService;
		this.translator = translator;
		this.fileService = fileService;
		this.jwtUtils = jwtUtils;
	}
	
	@PostMapping(consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
	public GenericResponse addPayemnt(@ModelAttribute PaymentDto data,Authentication authentication)
			throws MessagingException, IOException {
		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");
	    }
		log.info("Adding Payment");
		if (data.getFile() != null) {
			String originalFilename = data.getFile().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");
                }
            }
			 
			data.setFilePath(fileService.uploadFile(data.getFile(), FileType.PAYMENT));
		}
		paymentService.savepayment(data);
		GenericResponse response = new GenericResponse(true);
		response.setMessage(translator.toLocale(AppMessages.PAYMENT_SAVED));
		return response;
	}
	
	@GetMapping("/{id}")
    public GenericResponse getPaymentById(@PathVariable String id) {
        log.info("Get Payment");
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
        data.setPaymentDto(paymentService.getPaymentById(id));
        response.setData(data);
        return response;
    }
	
@GetMapping("/")
    public GenericResponse getAllPayments() {
        log.info("Get All Payment");
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
        data.setPayments(paymentService.getAllPayments());
        response.setData(data);
        return response;
    }
	
//	@Operation(description = "Update Payment based on id")
//	@PutMapping(value="/original/{id}", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
//	public GenericResponse updatePayment(@PathVariable String id,
//			@Valid @ModelAttribute PaymentDto payment) throws IOException {
//		log.info("Update payment ... {}", id);
//		if(payment.getFile()!=null) {
//		payment.setFilePath(fileService.uploadFile(payment.getFile(), FileType.PAYMENT));
//		}
//		paymentService.updatePayment(payment, id);
//		GenericResponse response = new GenericResponse(true);
//		response.setMessage(translator.toLocale(AppMessages.INSTRUMENT_UPDATED_SUCCESSFULLY));
//		return response;
//	}
	@Operation(description = "")
	@PutMapping(value = "/{id}", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
	public GenericResponse updatePayment(@PathVariable String id, @Valid @ModelAttribute PaymentDto payment,Authentication authentication)
			throws IOException {
		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");
	    }
		log.info("Update payment ... {}", id);
		if (payment.getFile() != null && !payment.getFile().isEmpty()) {
			String originalFilename = payment.getFile().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");
                }
            }

			payment.setFilePath(fileService.uploadFile(payment.getFile(), FileType.PAYMENT));
		}
		paymentService.updatePayment(payment, id);
		GenericResponse response = new GenericResponse(true);
		response.setMessage(translator.toLocale(AppMessages.PAYMENT_UPDATED_SUCCESSFULLY));
		return response;
	}
	
	
	
	
	
	@Operation(description = "Delete Payment based on id")
	@DeleteMapping("/{id}")
	public GenericResponse deletePayment(@PathVariable String id) throws IOException {
		log.info("Delete payment ... {}", id);
		paymentService.delete(id);
		GenericResponse response = new GenericResponse(true);
		response.setMessage(translator.toLocale(AppMessages.PAYMENT_DELETED));
		return response;
	}
	
    @GetMapping("/upi/{filename}")
    public ResponseEntity<byte[]> serveFile(@PathVariable String filename) throws IOException, UnsupportedAudioFileException {
        log.info("Get filename .. {}", filename);
        Resource file = fileService.loadAsResource(filename, FileType.PAYMENT);

        if (file == null)
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, AppMessages.FILE_NOT_FOUND);

        // Get audio duration
//        Path filePath = Paths.get(file.getURI());
//        double durationInSeconds = audioService.getAudioDuration(filePath.toFile());
//System.out.println(durationInSeconds);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
//                .header("Audio-Duration", String.valueOf(durationInSeconds)) // Add duration to headers
                .body(file.getContentAsByteArray());
    }
    
    @GetMapping("/calculatedeliverypayment")
    public GenericResponse getCalculatePremiumPayment(@RequestParam LocalDate date) {
        log.info("Get DeliveryPayment Calculation");
        GenericResponse response = new GenericResponse(true);
        GenericData data = new GenericData();
        data.setDeliveryPayment(paymentService.calculateDeliveryPayment(date));
        response.setData(data);
        return response;
    }
}
