package account

import (
	"regexp"
	"strconv"
	"time"
)

// offsetZoneRe matches a fixed UTC offset like "+03:00" or "-05:30" — the form the
// profile editor stores (an offset dropdown rather than an IANA name).
var offsetZoneRe = regexp.MustCompile(`^([+-])(\d{2}):(\d{2})$`)

// parseOffsetZone parses a "±HH:MM" offset into a fixed-offset location, reporting
// ok=false when name is not a well-formed offset within ±14:00.
func parseOffsetZone(name string) (*time.Location, bool) {
	m := offsetZoneRe.FindStringSubmatch(name)
	if m == nil {
		return nil, false
	}
	h, _ := strconv.Atoi(m[2])
	min, _ := strconv.Atoi(m[3])
	if h > 14 || min > 59 || (h == 14 && min > 0) {
		return nil, false
	}
	secs := h*3600 + min*60
	if m[1] == "-" {
		secs = -secs
	}
	return time.FixedZone(name, secs), true
}

// ResolveZone resolves a stored timezone — a fixed "±HH:MM" offset or an IANA name —
// to a *time.Location, falling back to UTC when it is empty or unrecognised, so a
// bad profile value never breaks the turn-timeout sweeper or the robot's sleep.
func ResolveZone(name string) *time.Location {
	if name == "" {
		return time.UTC
	}
	if loc, ok := parseOffsetZone(name); ok {
		return loc
	}
	if loc, err := time.LoadLocation(name); err == nil {
		return loc
	}
	return time.UTC
}

// validZone reports whether name is an acceptable timezone for a profile update —
// either a "±HH:MM" offset or a loadable IANA location.
func validZone(name string) bool {
	if _, ok := parseOffsetZone(name); ok {
		return true
	}
	_, err := time.LoadLocation(name)
	return err == nil
}
