package main

import (
	"bytes"
	"context"
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
	"path"
	"sync"

	"golang.org/x/oauth2/clientcredentials"

	"srs.epita.fr/fic-server/libfic"
)

var (
	teams_scores = map[string]float64{}

	base_URL = "https://api.well-played.gg"
	eventId  = ""
	roundId  = ""

	TokenURL = "https://idp.well-played.gg/oauth/token"

	configOauth = clientcredentials.Config{}

	lock sync.Mutex
)

func getTeams(pathname string) (teams map[string]fic.ExportedTeam, err error) {
	var cnt_raw []byte
	if cnt_raw, err = ioutil.ReadFile(pathname); err != nil {
		return
	}

	if err = json.Unmarshal(cnt_raw, &teams); err != nil {
		return
	}

	return
}

func treatAll(pathname string) {
	teams, err := getTeams(pathname)
	if err != nil {
		log.Printf("[ERR] %s\n", err)
	}

	for tid, team := range teams {
		treat(team, tid)
	}
}

func treatDiff(pathname string) {
	teams, err := getTeams(pathname)
	if err != nil {
		log.Printf("[ERR] %s\n", err)
	}

	for tid, team := range teams {
		if v, ok := teams_scores[tid]; !ok || v != team.Points {
			treat(team, tid)
		}
	}
}

type ZQDSScore struct {
	Score int64 `json:"score"`
}

func treat(team fic.ExportedTeam, tid string) {
	lock.Lock()
	defer lock.Unlock()

	log.Printf("Syncing score for %q: %d\n", team.Name, int64(team.Points))

	// Save in memory what is the team's score
	teams_scores[tid] = team.Points

	if u, err := url.Parse(base_URL); err != nil {
		log.Println(err.Error())
	} else {
		u.Path = path.Join(u.Path, "rank", "score", roundId, team.ExternalId)

		body, err := json.Marshal(ZQDSScore{int64(team.Points * 10)})
		if err != nil {
			log.Println("[ERR] Unable to create JSON from Score")
			return
		}

		client := configOauth.Client(context.Background())

		req, err := http.NewRequest("PUT", u.String(), bytes.NewReader(body))
		if err != nil {
			log.Println("[ERR] Unable to send request: ", err.Error())
			return
		}

		req.Header.Add("Content-Type", "application/json")

		resp, err := client.Do(req)
		if err != nil {
			log.Println("[ERR] Error during request execution: ", err.Error())
			return
		}

		if resp.StatusCode != http.StatusOK {
			if v, err := ioutil.ReadAll(resp.Body); err != nil {
				log.Println("An error occurs when trying to send scores, then decoding response: %w", err)
			} else {
				log.Printf("An error occurs when trying to send scores: %s", string(v))
			}
		}
	}
}
