package com.fsd.hellovelo.controller;

import com.fsd.hellovelo.exceptions.ResourceNotFoundException;
import com.fsd.hellovelo.payload.response.MessageResponse;
import com.fsd.hellovelo.security.services.UserDetailsImpl;
import com.fsd.hellovelo.service.StripeService;
import com.fsd.hellovelo.utility.StripeUtility;
import com.stripe.exception.StripeException;
import com.stripe.model.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import java.util.NoSuchElementException;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/stripe")
public class StripeController {

    private final StripeService stripeService;

    @Autowired
    public StripeController(StripeService stripeService){
        this.stripeService = stripeService;
    }

    /*Webhooks*/
    @PostMapping("/webhook/invoiceStatus")
    public ResponseEntity<?> processWebhook(@RequestBody String json, @RequestHeader("Stripe-Signature") String sigHeader){
        try{
            Event event = StripeUtility.getEvent(json, sigHeader, System.getenv("INVOICE_STATUS_KEY"));
            StripeObject stripeObject = StripeUtility.getStripeObject(event);
            stripeService.recordInvoiceChargeAttempt(event, stripeObject);
            return ResponseEntity.status(HttpStatus.OK).body("");
        }
        catch (IllegalArgumentException | StripeException | ResourceNotFoundException ex){
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
        }
    }

    @PostMapping("/webhook/setDefaultPayment")
    public ResponseEntity<?> setDefaultPayment(@RequestBody String json, @RequestHeader("Stripe-Signature") String sigHeader){
        try{
            Event event = StripeUtility.getEvent(json, sigHeader, System.getenv("DEFAULT_PAYMENT_KEY"));
            StripeObject stripeObject = StripeUtility.getStripeObject(event);
            stripeService.setDefaultPayment(stripeObject);
            return ResponseEntity.status(HttpStatus.OK).body("");
        }
        catch (IllegalArgumentException | ResourceNotFoundException | StripeException ex){
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
        }
    }

    @PostMapping("/webhook/invoiceCreated")
    public ResponseEntity<?> addDiscounts(@RequestBody String json, @RequestHeader("Stripe-Signature") String sigHeader){
        try{
            Event event = StripeUtility.getEvent(json, sigHeader, System.getenv("INVOICE_CREATED_KEY"));
            StripeObject stripeObject = StripeUtility.getStripeObject(event);
            stripeService.recordInvoice(stripeObject);
            stripeService.addDiscountsWhenInvoiceCreated(stripeObject);
//            stripeService.recordLastInvoice(stripeObject);
            return ResponseEntity.status(HttpStatus.OK).body("");
        }
        catch (IllegalArgumentException | ResourceNotFoundException | StripeException ex){
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
        }
    }

    @PostMapping("/webhook/provisionAccess")
    public ResponseEntity<?> provisionAccess(@RequestBody String json, @RequestHeader("Stripe-Signature") String sigHeader){
        try{
            Event event = StripeUtility.getEvent(json, sigHeader, System.getenv("PROVISION_KEY"));
            StripeObject stripeObject = StripeUtility.getStripeObject(event);
            stripeService.provisionAccess(event, stripeObject);
            return ResponseEntity.status(HttpStatus.OK).body("");
        }
        catch (IllegalArgumentException | ResourceNotFoundException ex){
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ex.getMessage());
        }
    }

    @PostMapping("/createSubscription")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> createSubscription(@RequestBody (required=false) String promoCode){
        UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        try {
            if(promoCode != null){
                promoCode = promoCode.replace("=", "");
            }
            return ResponseEntity.ok().body(stripeService.createSubscription(userDetails, promoCode));
        } catch (StripeException | ResourceNotFoundException | IllegalArgumentException e) {
            System.out.println(e.getMessage());
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        }
    }

    @DeleteMapping("/cancelSubscription")
    @PreAuthorize("hasRole('USER')")
    public ResponseEntity<?> cancelSubscription(){
        UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        try {
            stripeService.deleteSubscription(userDetails.getId());
            return ResponseEntity.ok().body("");
        } catch (StripeException | ResourceNotFoundException | IllegalArgumentException | NoSuchElementException e) {
            System.out.println(e.getMessage());
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
        }
    }

    @GetMapping("/getSubscription")
    public ResponseEntity<?> getSubscription() {
        UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        try{
            return ResponseEntity.status(HttpStatus.OK).body(stripeService.getSubscription(userDetails.getId()));
        } catch (ResourceNotFoundException | StripeException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(e.getMessage()));

        }
    }

//    @GetMapping("/updatePaymentMethod")
//    public ResponseEntity<?> getUpdatePage() {
//        try{
//            return ResponseEntity.status(HttpStatus.OK).body(stripeService.updatePaymentRequest());
//        } catch (ResourceNotFoundException e) {
//            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new MessageResponse(e.getMessage()));
//        }
//    }
}
