package helper

import (
	"time"

	"github.com/pkg/errors"

	"google.golang.org/protobuf/types/known/timestamppb"
)

const (
	DefaultParseFormatLayout = "2006-1-02 15:04:05"         // 默认解析时间格式
	DefaultFormatLayout      = "2006-01-02 15:04:05"        // 默认时间格式
	MicroFormatLayout        = "2006-01-02 15:04:05.000000" // 微秒时间格式
	FormatLayout             = "20060102150405"             // 导出时间格式
)

func AfterMinutesUnix(minutes int64) int64 {
	// 获取当前时间
	currentTime := time.Now()
	// 将当前时间增加5分钟
	currentTime = currentTime.Add(time.Duration(minutes) * time.Minute)
	// 转换为Unix时间戳(秒)
	return currentTime.Unix()
}

func DateStringToTime(localTimeStr string) (time.Time, error) {
	defer func() {
		if err := recover(); err != nil {
			LogErr(errors.New("时间转换错误:" + localTimeStr))
		}
	}()
	if localTimeStr == "" {
		return time.Time{}, nil
	}

	layouts := []string{
		DefaultParseFormatLayout,
		DefaultFormatLayout,
		"2006-01-02 15:04",
		"2006-1-02 15:04",
		"2006-01-02",
		"2006-1-02",
		time.RFC3339Nano,
	}

	var (
		localTime time.Time
		err       error
	)

	loc, _ := time.LoadLocation(GetTimeZone())
	for _, layout := range layouts {
		localTime, err = time.ParseInLocation(layout, localTimeStr, loc)
		if err == nil {
			break
		}
	}

	if err != nil {
		return time.Time{}, errors.Errorf("解析时间错误: %s", err.Error())
	}

	return localTime, nil
}

// TimeFormat 时间戳转时间格式
func TimeFormat(inTime *time.Time, layout ...string) string {
	if inTime == nil {
		return ""
	}
	if len(layout) == 0 {
		layout = []string{DefaultFormatLayout}
	}
	return inTime.Format(layout[0])
}

// TimeStampFormat 时间戳转时间格式
func TimeStampFormat(timestamp int64, layout ...string) string {
	if timestamp == 0 {
		return ""
	}
	if len(layout) == 0 {
		layout = []string{DefaultFormatLayout}
	}
	return time.Unix(timestamp, 0).Format(layout[0])
}

// Int32TimeStampFormat int32类型时间戳转时间格式
func Int32TimeStampFormat(timestamp int32, layout ...string) string {
	return TimeStampFormat(int64(timestamp), layout...)
}

// IsoDateStringToTimeStamp iso格式字符串转时间戳
func IsoDateStringToTimeStamp(isoTimeStr string) (int64, error) {
	isoTime, err := time.ParseInLocation(time.RFC3339Nano, isoTimeStr, time.Local)
	if err != nil {
		return 0, err
	}
	return isoTime.Unix(), nil
}

// LayOutDateStringToTimeStamp layout格式字符串转时间戳
func LayOutDateStringToTimeStamp(localTimeStr string) (int64, error) {
	localTime, err := time.ParseInLocation(DefaultFormatLayout, localTimeStr, time.Local)
	if err != nil {
		return 0, err
	}
	return localTime.Unix(), nil
}

// DateStringToTimeStamp 字符串转时间戳(兼容格式)
func DateStringToTimeStamp(date string) (int64, error) {
	u, err := IsoDateStringToTimeStamp(date)
	if err != nil {
		u, err = LayOutDateStringToTimeStamp(date)
	}
	return u, err
}

// DateStringToTimeStampInt32 字符串转时间戳(兼容格式)
func DateStringToTimeStampInt32(date string) (int32, error) {
	u, err := DateStringToTimeStamp(date)
	return int32(u), err
}

// BatchDateStringToTimeStampInt32 批量字符串转时间戳
func BatchDateStringToTimeStampInt32(dates []string) ([]int32, error) {
	res := make([]int32, 0, len(dates))
	for _, date := range dates {
		u, err := DateStringToTimeStampInt32(date)
		if err != nil {
			return nil, err
		}
		res = append(res, u)
	}
	return res, nil
}

// GoogleTimeToString google proto时间转字符串
func GoogleTimeToString(date *timestamppb.Timestamp) string {
	loc, _ := time.LoadLocation(GetTimeZone())
	return date.AsTime().In(loc).Format(DefaultFormatLayout)
}

// GoogleTimeToMicroString google proto时间转字符串
func GoogleTimeToMicroString(date *timestamppb.Timestamp) string {
	loc, _ := time.LoadLocation(GetTimeZone())
	return date.AsTime().In(loc).Format(MicroFormatLayout)
}

func DateStringToTimeStampV2(localTimeStr string) (int64, error) {
	if localTimeStr == "" {
		return 0, nil
	}

	layouts := []string{
		DefaultParseFormatLayout,
		DefaultFormatLayout,
		"2006-01-02 15:04",
		"2006-1-02 15:04",
		"2006-01-02",
		"2006-1-02",
		time.RFC3339Nano,
	}

	var (
		localTime time.Time
		err       error
	)

	loc, _ := time.LoadLocation(GetTimeZone())
	for _, layout := range layouts {
		localTime, err = time.ParseInLocation(layout, localTimeStr, loc)
		if err == nil {
			break
		}
	}

	if err != nil {
		return 0, errors.Errorf("解析时间错误: %s", err.Error())
	}

	return localTime.Unix(), nil
}

// IsTimeStrBefore 时间比较 格式:2006-01-02 15:04:05
func IsTimeStrBefore(beforeTime, afterTime string) bool {
	time1, _ := time.Parse(DefaultFormatLayout, beforeTime)
	time2, _ := time.Parse(DefaultFormatLayout, afterTime)
	if time1.Before(time2) {
		return true
	}
	return false
}

// IsTimeBefore 时间比较 格式:2006-01-02 15:04:05
func IsTimeBefore(beforeTime, afterTime time.Time) bool {
	if beforeTime.Before(afterTime) {
		return true
	}
	return false
}