package cmd

import (
	"os"
	"path/filepath"
	"strings"
	"time"
)

const (
	diagnoseQueryWindowLocalLayout = "2006-01-02 15:04:05 -07"
	diagnoseQueryWindowUTCLayout   = "2006-01-02 15:04:05Z"
)

func annotateDiagnoseQueryScope(scope QueryScope, location *time.Location) QueryScope {
	if location == nil {
		location = time.Local
	}

	scope.ProfileTimezone = diagnoseProfileTimezoneName(location)
	scope.QueryWindowLocal = formatDiagnoseQueryWindowLocal(scope.StartTime, scope.EndTime, location)
	scope.QueryWindowUTC = formatDiagnoseQueryWindowUTC(scope.StartTime, scope.EndTime)
	return scope
}

func diagnoseQueryScopeForOutput(scope QueryScope) QueryScope {
	if strings.TrimSpace(scope.ProfileTimezone) != "" &&
		strings.TrimSpace(scope.QueryWindowLocal) != "" &&
		strings.TrimSpace(scope.QueryWindowUTC) != "" {
		return scope
	}
	return annotateDiagnoseQueryScope(scope, time.Local)
}

func formatDiagnoseQueryWindowLocal(start, end time.Time, location *time.Location) string {
	if location == nil {
		location = time.Local
	}
	return start.In(location).Format(diagnoseQueryWindowLocalLayout) +
		" -> " +
		end.In(location).Format(diagnoseQueryWindowLocalLayout)
}

func formatDiagnoseQueryWindowUTC(start, end time.Time) string {
	return start.UTC().Format(diagnoseQueryWindowUTCLayout) +
		" -> " +
		end.UTC().Format(diagnoseQueryWindowUTCLayout)
}

func diagnoseProfileTimezoneName(location *time.Location) string {
	if location == nil {
		location = time.Local
	}

	name := strings.TrimSpace(location.String())
	if name != "" && name != "Local" {
		return name
	}

	if tz := strings.TrimSpace(os.Getenv("TZ")); tz != "" {
		return tz
	}
	if zoneName := diagnoseLocaltimeZoneName(); zoneName != "" {
		return zoneName
	}
	if name != "" {
		return name
	}
	return "Local"
}

func diagnoseLocaltimeZoneName() string {
	target, err := os.Readlink("/etc/localtime")
	if err != nil {
		return ""
	}

	target = filepath.ToSlash(target)
	const marker = "/zoneinfo/"
	index := strings.LastIndex(target, marker)
	if index < 0 {
		return ""
	}

	name := strings.Trim(target[index+len(marker):], "/")
	if name == "" || strings.Contains(name, "..") {
		return ""
	}
	return name
}
