package main

import (
	"encoding/json"
	"fmt"
	"github.com/stripe/stripe-go/v72"
	"github.com/stripe/stripe-go/v72/paymentintent"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strconv"
	"strings"
)

func getStripeKey() string {
	return os.Getenv("STRIPE_KEY")
}

func getStripePK() string {
	return os.Getenv("STRIPE_PK")
}

func getstripepaymentintentHandler(response http.ResponseWriter, request *http.Request) {
	name := getUserName(request)
	if name != "" {

		charge_data, ok := request.URL.Query()["charge_data"]
		if !ok || len(charge_data[0]) < 1 {
			log.Println("Url Param 'charge_data' is missing")
			fmt.Fprintf(response, "{ \"rc\": 1, \"msg\": \"charge_data must be specified in URL\" }")
			return
		}

		trackers := strings.Split(charge_data[0], ",")

		var abo_years = 0
		var items []string
		amount := 0
		for _, tracker := range trackers {
			items = strings.Split(tracker, ":")
			if len(items) >= 2 {
				abo_count, err := strconv.Atoi(items[1])
				if err == nil {
					abo_years += abo_count
					amount += (abo_count * getYearlyAboCost(items[0]))
				}
			}
		}
		abo_amount := int64(amount)

		stripe.Key = getStripeKey()

		params := &stripe.PaymentIntentParams{
			Amount:       stripe.Int64(abo_amount),
			Currency:     stripe.String(string(stripe.CurrencyCHF)),
			ReceiptEmail: stripe.String(name),
		}
		params.AddMetadata("charge_data", charge_data[0])
		params.AddMetadata("login_user", name)
		paymentintent, err := paymentintent.New(params)

		if err != nil {
			fmt.Fprintf(response, "{ \"rc\": 5, \"stripeclientsecret\": \"%s\" }\n", err)
		} else {
			fmt.Fprintf(response, "{ \"rc\": 0, \"stripeclientsecret\": \"%s\" }\n", paymentintent.ClientSecret)
		}

	} else {
		fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"Only available for logged in users\" }")
	}
}

func HandlePayment(user string, charge_data string, amount int64) {
	fmt.Printf("HandlePayment for %s (charge_data: %s, amount: %d)!\n", user, charge_data, amount)
	charge_data_email_text := fmt.Sprintf("%-30s %20s %10s\n", "Alias", "verlängern bis", "Betrag")
	charge_data_email_text = charge_data_email_text + strings.Repeat("-", 62) + "\n"
	for _, token := range strings.Split(charge_data, ",") {
		res := strings.Split(token, ":")
		if (len(res)) == 3 {
			deveui := res[0]
			years, _ := strconv.Atoi(res[1])
			amount, _ := strconv.Atoi(res[2])
			fmt.Printf("prolongActivation %s: %d\n", deveui, years)
			prolongActivation(deveui, years)
			line := fmt.Sprintf("%-30s %20s %10.2f\n", getDevAlias(deveui), getActiveUntil(deveui), float64(amount/100))
			charge_data_email_text = charge_data_email_text + line
		}
	}
	charge_data_email_text = charge_data_email_text + strings.Repeat("-", 62) + "\n"
	charge_data_email_text = charge_data_email_text + fmt.Sprintf("%-30s %20s %10.2f\n", "Total CHF", "", float64(amount/100))
	sendPaymentConfirmationEmail(user, charge_data_email_text, amount)
}

func stripeWebhookHandler(w http.ResponseWriter, req *http.Request) {
	const MaxBodyBytes = int64(65536)
	req.Body = http.MaxBytesReader(w, req.Body, MaxBodyBytes)
	payload, err := ioutil.ReadAll(req.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error reading request body: %v\n", err)
		w.WriteHeader(http.StatusServiceUnavailable)
		return
	}

	event := stripe.Event{}

	if err := json.Unmarshal(payload, &event); err != nil {
		fmt.Fprintf(os.Stderr, "Failed to parse webhook body json: %v\n", err.Error())
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	// Unmarshal the event data into an appropriate struct depending on its Type
	switch event.Type {
	case "payment_intent.succeeded":
		var paymentIntent stripe.PaymentIntent
		err := json.Unmarshal(event.Data.Raw, &paymentIntent)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Error parsing webhook JSON: %v\n", err)
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		fmt.Printf("PaymentIntent was successful (charge_data: %s, amount: %d)!\n", paymentIntent.Metadata["charge_data"], paymentIntent.Amount)
		HandlePayment(paymentIntent.ReceiptEmail, paymentIntent.Metadata["charge_data"], paymentIntent.Amount)
	// ... handle other event types
	default:
		fmt.Fprintf(os.Stderr, "Unexpected event type: %s\n", event.Type)
		w.WriteHeader(http.StatusBadRequest)
		return
	}

	w.WriteHeader(http.StatusOK)
}
