package main

import (
	"context"
	"fmt"
	"io"
	"net"
	"strconv"
	"time"

	"github.com/fastly/compute-sdk-go/configstore"
	"github.com/fastly/compute-sdk-go/fsthttp"
)

const BackendName = "origin_0"

func main() {
	fsthttp.ServeFunc(func(ctx context.Context, w fsthttp.ResponseWriter, r *fsthttp.Request) {
		// This example assumes that the banned IP addresses are stored in the
		// configstore called "ban_dict" as unix timestamps. See fiddle tests
		// for this example to see an example of the configstore.
		config, err := configstore.Open("ban_dict")
		if err != nil {
			w.WriteHeader(fsthttp.StatusInternalServerError)
			fmt.Fprintln(w, err.Error())
			return
		}

		ip := net.ParseIP(r.RemoteAddr)
		if ip == nil {
			w.WriteHeader(fsthttp.StatusInternalServerError)
			fmt.Fprintln(w, "unable to parse the client IP %q", r.RemoteAddr)
			return
		}
		fmt.Println("Client IP is", ip)

		// Retrieve expiration timestamp from the configstore and parse it into
		// a time value.
		expireValue, err := config.Get(ip.String())
		if err != nil {
			// default to 0 if the IP can't be found in the dictionary.
			expireValue = "0"
		}
		expireTimestamp, err := strconv.ParseInt(expireValue, 10, 64)
		if err != nil {
			w.WriteHeader(fsthttp.StatusInternalServerError)
			fmt.Fprintln(w, err.Error())
			return
		}
		expireTime := time.Unix(expireTimestamp, 0)

		if expireTime != time.Unix(0, 0) {
			fmt.Println("Client IP is banned until", expireTime.String())
		}

		// Deny access if the IP address is banned and the ban hasn't expired
		// yet.
		if expireTime.After(time.Now()) {
			w.WriteHeader(fsthttp.StatusForbidden)
			fmt.Fprintln(w, "Your IP address is banned until %s", expireTime.String())
			return
		}

		// Proceed with the request, if the IP address is not banned.
		resp, err := r.Send(ctx, BackendName)
		if err != nil {
			w.WriteHeader(fsthttp.StatusBadGateway)
			fmt.Fprintln(w, err.Error())
			return
		}

		w.Header().Reset(resp.Header)
		w.WriteHeader(resp.StatusCode)
		io.Copy(w, resp.Body)
	})
}