package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/cookiejar"
	"regexp"
	"strings"
	"time"

	"github.com/golang/glog"
)

func init() {
	flag.Set("logtostderr", "true")
}

var (
	flagListen string

	reVoucher = regexp.MustCompile("[A-Z0-9]+")
)

type voucherstatus int

const (
	statusUnknown voucherstatus = iota
	statusInvalid
	statusUnused
	statusUsed
	statusCart
)

func (v voucherstatus) String() string {
	switch v {
	case statusInvalid:
		return "INVALID"
	case statusUnused:
		return "UNUSED"
	case statusUsed:
		return "USED"
	case statusCart:
		return "INCART"
	}
	return "UNKNOWN"
}

type vouchercache struct {
	status  voucherstatus
	expires time.Time
}

func (c *vouchercache) fresh() bool {
	if c.status == statusUsed {
		return true
	}
	if c.expires.Before(time.Now()) {
		return false
	}
	return true
}

type statusReq struct {
	voucher string
	res     chan voucherstatus
}

type refreshRes struct {
	voucher string
	status  voucherstatus
}

type service struct {
	statusReq chan *statusReq

	pretixSem chan struct{}
}

func newService() *service {
	return &service{
		statusReq: make(chan *statusReq),
		pretixSem: make(chan struct{}, 3),
	}
}

func (s *service) worker(ctx context.Context) error {
	cache := make(map[string]*vouchercache)
	waiters := make(map[string][]chan voucherstatus)
	refreshes := make(chan *refreshRes)

	for {
		select {
		case <-ctx.Done():
			return ctx.Err()

		// is there a refresh pending?
		case ref := <-refreshes:
			glog.Infof("cache feed: %v is %v", ref.voucher, ref.status)
			expires := 30 * time.Minute
			if ref.status == statusInvalid {
				expires = 48 * time.Hour
			}
			cache[ref.voucher] = &vouchercache{
				status:  ref.status,
				expires: time.Now().Add(expires),
			}
			for _, w := range waiters[ref.voucher] {
				w := w
				go func() {
					w <- ref.status
				}()
			}
			delete(waiters, ref.voucher)

		// is there a new request?
		case req := <-s.statusReq:
			// return cache if fresh
			if el, ok := cache[req.voucher]; ok && el.fresh() {
				go func() {
					glog.Infof("cache hit: %v is %v", req.voucher, el.status)
					req.res <- el.status
				}()
				continue
			}
			// is someone waiting for a refresh already?
			if _, ok := waiters[req.voucher]; ok {
				glog.Infof("cache miss, secondary: %v", req.voucher)
				waiters[req.voucher] = append(waiters[req.voucher], req.res)
				continue
			}
			// request refresh
			glog.Infof("cache miss, primary: %v", req.voucher)
			waiters[req.voucher] = []chan voucherstatus{req.res}
			go func() {
				s := s.getStatus(ctx, req.voucher)
				refreshes <- &refreshRes{
					voucher: req.voucher,
					status:  s,
				}
			}()
		}
	}
}

func (s *service) run() {
	mux := http.NewServeMux()
	mux.HandleFunc("/status", s.handlerStatus)

	ctx := context.Background()
	go s.worker(ctx)

	glog.Infof("Listening on %s...", flagListen)
	if err := http.ListenAndServe(flagListen, mux); err != nil {
		glog.Exitf("could not listen: %v", err)
	}
}

func (s *service) handlerStatus(w http.ResponseWriter, r *http.Request) {
	status := statusUnknown
	defer func() {
		e := json.NewEncoder(w)
		e.Encode(struct {
			Status string
		}{
			Status: status.String(),
		})
	}()

	voucher := r.URL.Query().Get("voucher")
	if voucher == "" || !strings.HasPrefix(voucher, "CHAOS") {
		status = statusInvalid
		return
	}
	if !reVoucher.MatchString(voucher) {
		status = statusInvalid
		return
	}

	resC := make(chan voucherstatus)
	s.statusReq <- &statusReq{
		voucher: voucher,
		res:     resC,
	}
	status = <-resC
}

func (s *service) getStatus(ctx context.Context, voucher string) voucherstatus {
	s.pretixSem <- struct{}{}
	defer func() {
		<-s.pretixSem
	}()

	cookieJar, _ := cookiejar.New(nil)
	client := &http.Client{
		Jar: cookieJar,
	}

	res, err := client.Get(fmt.Sprintf("https://tickets.events.ccc.de/36c3/redeem/?voucher=%s&subevent=&hello=this-is-q3k-at-hackerspace-pl-we-use-this-for-voucher-distribution", voucher))
	if err != nil {
		glog.Errorf("Getting main page: %v", err)
		return statusUnknown
	}
	defer res.Body.Close()

	data, err := ioutil.ReadAll(res.Body)
	if err != nil {
		glog.Errorf("Reading result page: %v", err)
		return statusUnknown
	}

	if strings.Contains(string(data), "not known") {
		return statusInvalid
	}
	if strings.Contains(string(data), "already been") {
		return statusUsed
	}
	if strings.Contains(string(data), "You entered a voucher code that allows you ") {
		return statusUnused
	}
	if strings.Contains(string(data), "voucher code is currently locked") {
		return statusCart
	}

	glog.Errorf("Unexpected result for %s", voucher)
	glog.Infof("%s", data)
	status := statusUnknown

	return status
}

func main() {
	flag.StringVar(&flagListen, "listen", ":8081", "Listen address")
	flag.Parse()

	s := newService()
	s.run()
}
