package geoip

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"sort"
	"strings"

	geoip2 "github.com/oschwald/geoip2-golang"
)

const RootURL = "https://git.paulbsd.com/paulbsd/GeoLite.mmdb/releases/download/%s/%s"
const APIUrl = "https://git.paulbsd.com/api/v1/repos/paulbsd/GeoLite.mmdb/releases"

const CityFilename = "GeoLite2-City.mmdb"
const ASNFilename = "GeoLite2-ASN.mmdb"

func GetLastVersion() string {
	var apiresults []struct {
		Tag string `json:"tag_name"`
	}
	res, err := http.Get(APIUrl)
	if err != nil {
		log.Println(err)
	}
	body, err := io.ReadAll(res.Body)
	if err != nil {
		log.Println(err)
	}
	err = json.Unmarshal(body, &apiresults)
	if err != nil {
		log.Println(err)
	}

	var tags []string
	for _, t := range apiresults {
		tags = append(tags, t.Tag)
	}
	sort.Sort(sort.Reverse(sort.StringSlice(tags)))

	return tags[0]
}

func InitGeoIP() (citydb *geoip2.Reader, asndb *geoip2.Reader, err error) {
	var version = GetLastVersion()
	var dbs map[string]string = map[string]string{
		"city": fmt.Sprintf(RootURL, version, CityFilename),
		"asn":  fmt.Sprintf(RootURL, version, ASNFilename)}
	log.Printf("Fetching GeoLite.mmdb version %s\n", version)
	citydb, err = FetchDB(dbs["city"], version)
	if err != nil {
		return
	}
	asndb, err = FetchDB(dbs["asn"], version)
	if err != nil {
		return
	}
	return
}

func FetchDB(db string, version string) (reader *geoip2.Reader, err error) {
	if _, err := os.Stat("geoip"); err != nil {
		os.MkdirAll("geoip", 0777)
	}

	splited := strings.Split(db, "/")
	filename := strings.Replace(splited[len(splited)-1], ".", fmt.Sprintf("-%s.", version), 1)
	dbpath := fmt.Sprintf("%s/%s", "geoip", filename)

	if _, err := os.Stat(dbpath); err != nil {
		resp, err := http.Get(db)
		if err != nil {
			return nil, nil
		}
		file, err := os.Create(dbpath)
		if err != nil {
			return nil, nil
		}
		_, err = io.Copy(file, resp.Body)
		if err != nil {
			return nil, nil
		}
	}

	return geoip2.Open(dbpath)
}
