package com.fsd.hellovelo.service;

import com.fsd.hellovelo.entity.Coupon;
import com.fsd.hellovelo.entity.Referral;
import com.fsd.hellovelo.entity.User;
import com.fsd.hellovelo.exceptions.ResourceNotFoundException;
import com.fsd.hellovelo.payload.request.CreateIndividualPromotionEmailRequest;
import com.fsd.hellovelo.repository.CouponRepository;
import com.fsd.hellovelo.repository.UserRepository;
import com.sendgrid.Method;
import com.sendgrid.Request;
import com.sendgrid.Response;
import com.sendgrid.SendGrid;
import com.sendgrid.helpers.mail.Mail;
import com.sendgrid.helpers.mail.objects.Content;
import com.sendgrid.helpers.mail.objects.Email;
import com.sendgrid.helpers.mail.objects.Personalization;
import com.stripe.Stripe;
import com.stripe.exception.StripeException;
import com.stripe.model.Discount;
import com.stripe.model.PromotionCode;
import com.stripe.param.PromotionCodeCreateParams;
import org.apache.tomcat.jni.Local;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;

@Service
public class SendGridEmailService {

    private final UserRepository userRepository;
    private final CouponRepository couponRepository;

    @Autowired
    public SendGridEmailService(UserRepository userRepository, CouponRepository couponRepository) {
        this.userRepository = userRepository;
        this.couponRepository = couponRepository;
    }

    public List<Long> sendDiscountEmail(CreateIndividualPromotionEmailRequest discountEmailData) {

        List<Long> unsentEmailsCustomerIds = new ArrayList<>();
        for (Long customerId : discountEmailData.getCustomerIds()) {
            try {
                User customer = userRepository.findById(customerId).orElseThrow(() -> new ResourceNotFoundException(""));
                Coupon coupon = couponRepository.findById(discountEmailData.getCouponId()).orElseThrow();
                String discountRate;
                if (coupon.getAmountOff() != null) {
                    discountRate = (coupon.getAmountOff() * 100) + "$";
                } else if (coupon.getPercentOff() != null) {
                    discountRate = coupon.getPercentOff() + "%";
                } else {
                    throw new IllegalArgumentException("Error: Internal error. Coupon discount not found.");
                }
                String code = createPromoCode(customer, discountEmailData, coupon);
                sendDiscountMail(customer, code, discountEmailData.getExpiresAt(), discountRate);
            } catch (IOException | ResourceNotFoundException | IllegalArgumentException ex) {
                ex.printStackTrace();
                unsentEmailsCustomerIds.add(customerId);
            }
        }
        return unsentEmailsCustomerIds;
    }

    public void sendReferralEmail(Referral referral) {
        try {
            String discountRate;
            Coupon coupon = couponRepository.findById(referral.getReferredDiscount().getCoupon().getId()).orElseThrow();
            if (coupon.getAmountOff() != null) {
                discountRate = (coupon.getAmountOff() / 100) + "$";
            } else if (coupon.getPercentOff() != null) {
                discountRate = coupon.getPercentOff() + "%";
            } else {
                throw new IllegalArgumentException("Error: Internal error. Coupon discount not found.");
            }

            Stripe.apiKey = "sk_test_51K6PnvAl7XnbPt50bAvU4L3nGTDI8nXn8a4nPhjTcbznNDfW3j7sBL1UqmL2x5yUVXygbNJ6o32Gg01juu76NkbJ00ereY9xEJ";
            String code = PromotionCode.retrieve(referral.getReferredDiscount().getStripePromoCodeId()).getCode();

            sendReferralMail(referral.getReferralEmail(), code, discountRate);
        } catch (IOException | ResourceNotFoundException | StripeException ex) {
            ex.printStackTrace();
        }
    }

    private void sendDiscountMail(User customer, String code, LocalDate expiresAt, String discountRate) throws IOException {
        Email from = new Email("unilogak@gmail.com", "Hello Velo");
        String subject = "We Miss You!";
        Email to = new Email(customer.getEmail(), customer.getFirstName());
        Content content = new Content("text/html", "Come back to Hello Velo with discount code " + code);
        Mail mail = new Mail(from, subject, to, content);

        mail.setTemplateId("d-1b376198e06f4faab9fd35200052f301");
        Personalization personalization = new Personalization();
        personalization.addDynamicTemplateData("couponCode", code);
        personalization.addDynamicTemplateData("expirationDate", expiresAt.toString());
        personalization.addDynamicTemplateData("discountRate", discountRate);
        sendMail(to, mail, personalization);
    }

    private void sendReferralMail(String email, String code, String discountRate) throws IOException {
        Email from = new Email("unilogak@gmail.com", "Hello Velo");
        String subject = "Come join us!";
        Email to = new Email(email);
        Content content = new Content("text/html", "Join Hello Velo with code " + code);
        Mail mail = new Mail(from, subject, to, content);

        mail.setTemplateId("d-ac46fc8f4efd45c2b1c5121f74b4e21a");
        Personalization personalization = new Personalization();
        personalization.addDynamicTemplateData("couponCode", code);
        personalization.addDynamicTemplateData("discountRate", discountRate);
        System.out.println(code);
        sendMail(to, mail, personalization);
        System.out.println("sent");
    }

    public void sendMail(Email to, Mail mail, Personalization personalization) throws IOException {
        personalization.addTo(to);
        mail.personalization.add(personalization);
        SendGrid sendGrid = new SendGrid(System.getenv("SENDGRID_KEY"));
        Request request = new Request();
        try {
            request.setMethod(Method.POST);
            request.setEndpoint("mail/send");
            request.setBody(mail.build());
            Response response = sendGrid.api(request);
            System.out.println(response.getBody());
        } catch (IOException ex) {
            ex.printStackTrace();
            throw new IOException("Error: Email could not be sent.");
        }
    }

    private String createPromoCode(User customer, CreateIndividualPromotionEmailRequest discountEmailData, Coupon coupon) {
        coupon = couponRepository.findById(discountEmailData.getCouponId()).orElseThrow(() -> new ResourceNotFoundException(""));

        Stripe.apiKey = "sk_test_51K6PnvAl7XnbPt50bAvU4L3nGTDI8nXn8a4nPhjTcbznNDfW3j7sBL1UqmL2x5yUVXygbNJ6o32Gg01juu76NkbJ00ereY9xEJ";
        PromotionCodeCreateParams promotionCodeCreateParams = new PromotionCodeCreateParams.Builder()
                .setCoupon(coupon.getStripeCouponId())
                .setCustomer(customer.getStripeUserId())
                .setExpiresAt(discountEmailData.getExpiresAt().toEpochSecond(LocalTime.MIDNIGHT, ZoneOffset.UTC))
                .build();
        try {
            PromotionCode promotionCode = PromotionCode.create(promotionCodeCreateParams);
            return promotionCode.getCode();

        } catch (StripeException ex) {
            throw new IllegalArgumentException("Error: Promo code could not be created." + ex.getMessage());
        }
    }

//    private String createPromoCode(Coupon coupon) {
//        Stripe.apiKey = "sk_test_51K6PnvAl7XnbPt50bAvU4L3nGTDI8nXn8a4nPhjTcbznNDfW3j7sBL1UqmL2x5yUVXygbNJ6o32Gg01juu76NkbJ00ereY9xEJ";
//
//        PromotionCodeCreateParams promotionCodeCreateParams = new PromotionCodeCreateParams.Builder()
//                .setCoupon(coupon.getStripeCouponId())
//                .setRestrictions(PromotionCodeCreateParams.Restrictions.builder().setFirstTimeTransaction(true).build())
//                .build();
//        try {
//            PromotionCode promotionCode = PromotionCode.create(promotionCodeCreateParams);
//            System.out.println("Code : " + promotionCode.getCode());
//            return promotionCode.getCode();
//
//        } catch (StripeException ex) {
//            throw new IllegalArgumentException("Error: Promo code could not be created.");
//        }
//    }
}
