package types

import (
	"database/sql/driver"
	"fmt"
	"time"
)

// 默认时间格式
const dateFormat = "2006-01-02 15:04:05.000"

// DateTime 自定义时间类型
type DateTime time.Time

// Scan implements the Scanner interface.
func (dt *DateTime) Scan(value any) error {
	// mysql 内部日期的格式可能是 2006-01-02 15:04:05 +0800 CST 格式，所以检出的时候还需要进行一次格式化
	tTime, _ := time.ParseInLocation("2006-01-02 15:04:05 +0800 CST", value.(time.Time).String(), time.Local)
	*dt = DateTime(tTime)
	return nil
}

// Value implements the driver Valuer interface.
func (dt DateTime) Value() (driver.Value, error) {
	// 0001-01-01 00:00:00 属于空值，遇到空值解析成 null 即可
	if dt.String() == "0001-01-01 00:00:00.000" {
		return nil, nil
	}
	return []byte(dt.Format(dateFormat)), nil
}

// 用于 fmt.Println 和后续验证场景
func (dt DateTime) String() string {
	return dt.Format(dateFormat)
}

// Format 格式化
func (dt DateTime) Format(fm string) string {
	return time.Time(dt).Format(fm)
}

// After 时间比较
func (dt *DateTime) After(now time.Time) bool {
	return time.Time(*dt).After(now)
}

// Before 时间比较
func (dt *DateTime) Before(now time.Time) bool {
	return time.Time(*dt).Before(now)
}

// IBefore 时间比较
func (dt *DateTime) IBefore(now DateTime) bool {
	return dt.Before(time.Time(now))
}

// SubTime 对比
func (dt DateTime) SubTime(t time.Time) time.Duration {
	return dt.ToTime().Sub(t)
}

// Sub 对比
func (dt DateTime) Sub(t DateTime) time.Duration {
	return dt.ToTime().Sub(t.ToTime())
}

// ToTime 转换为golang的时间类型
func (dt DateTime) ToTime() time.Time {
	return time.Time(dt).Local()
}

// IsNil 是否为空值
func (dt DateTime) IsNil() bool {
	return dt.Format(dateFormat) == "0001-01-01 00:00:00.000"
}

// Unix 实现Unix函数
func (dt DateTime) Unix() int64 {
	return dt.ToTime().Unix()
}

// EndOfCentury 获取本世纪最后时间
func (dt DateTime) EndOfCentury() DateTime {
	yearEnd := time.Now().Local().Year()/100*100 + 99
	return DateTime(time.Date(yearEnd, 12, 31, 23, 59, 59, 999999999, time.Local))
}

// ========  序列化 ========

// MarshalJSON 时间到字符串
func (dt DateTime) MarshalJSON() ([]byte, error) {
	// 过滤掉空数据
	if dt.IsNil() {
		return []byte("\"\""), nil
	}
	output := fmt.Sprintf(`"%s"`, dt.Format("2006-01-02 15:04:05"))
	return []byte(output), nil
}

// UnmarshalJSON 字符串到时间
func (dt *DateTime) UnmarshalJSON(b []byte) error {
	if len(b) == 2 {
		*dt = DateTime{}
		return nil
	}
	// 解析指定的格式
	//now, err := time.ParseInLocation(`"`+dateFormat+`"`, string(b), time.Local)
	now, err := time.ParseInLocation(dateFormat, string(b), time.Local)
	*dt = DateTime(now)
	return err
}
