package internal

import (
	"crypto/sha1"
	"encoding/hex"
	"fmt"
	"io"
	"time"
)

func authToken(userName string, wapiPass string) string {
	return sha1string(userName + sha1string(wapiPass) + czechHourString())
}

func sha1string(txt string) string {
	h := sha1.New()
	_, _ = io.WriteString(h, txt)
	return hex.EncodeToString(h.Sum(nil))
}

func czechHourString() string {
	return formatHour(czechHour())
}

func czechHour() int {
	tryZones := []string{"Europe/Prague", "Europe/Paris", "CET"}

	for _, zoneName := range tryZones {
		loc, err := time.LoadLocation(zoneName)
		if err == nil {
			return time.Now().In(loc).Hour()
		}
	}

	// hopefully this will never be used
	// this is fallback for containers without tzdata installed
	return utcToCet(time.Now().UTC()).Hour()
}

func utcToCet(utc time.Time) time.Time {
	// https://en.wikipedia.org/wiki/Central_European_Time
	// As of 2011, all member states of the European Union observe Summer Time (daylight saving time),
	// from the last Sunday in March to the last Sunday in October.
	// States within the CET area switch to Central European Summer Time (CEST -- UTC+02:00) for the summer.[1]
	utcMonth := utc.Month()
	if utcMonth < time.March || utcMonth > time.October {
		return utc.Add(time.Hour)
	}
	if utcMonth > time.March && utcMonth < time.October {
		return utc.Add(time.Hour * 2)
	}

	dayOff := 0
	breaking := time.Date(utc.Year(), utcMonth+1, dayOff, 1, 0, 0, 0, time.UTC)
	for {
		if breaking.Weekday() == time.Sunday {
			break
		}
		dayOff--
		breaking = time.Date(utc.Year(), utcMonth+1, dayOff, 1, 0, 0, 0, time.UTC)
		if dayOff < -7 {
			panic("safety exit to avoid infinite loop")
		}
	}

	if (utcMonth == time.March && utc.Before(breaking)) || (utcMonth == time.October && utc.After(breaking)) {
		return utc.Add(time.Hour)
	}
	return utc.Add(time.Hour * 2)
}

func formatHour(hour int) string {
	return fmt.Sprintf("%02d", hour)
}