package models

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	orm "go-admin/common/global"
	"go-admin/logger"
	"math/rand"
	"time"
)

const (
	ErpMonthEndClosingUnAudit = 1 // 待审核
	ErpMonthEndClosingAudited = 2 // 已审核
)

// ErpMonthEndClosing 财务月结订单表
type ErpMonthEndClosing struct {
	Model

	SerialNumber     string     `json:"serial_number" gorm:"index"`          // 单据编号
	ClosingStartDate time.Time  `json:"closing_start_date" gorm:"type:date"` // 月结开始时间，精确到天
	ClosingEndDate   time.Time  `json:"closing_end_date" gorm:"type:date"`   // 月结结束时间，精确到天
	MakerId          uint32     `json:"maker_id" gorm:"index"`               // 制单人 ID
	MakerName        string     `json:"maker_name"`                          // 制单人名称
	MakerTime        *time.Time `json:"maker_time"`                          // 制单时间
	AuditorId        uint32     `json:"auditor_id" gorm:"index"`             // 审核人 ID
	AuditorName      string     `json:"auditor_name"`                        // 审核人姓名
	AuditTime        *time.Time `json:"audit_time"`                          // 审核时间
	State            uint32     `json:"state"`                               // 订单状态：1-待审核；2-已审核
}

// ErpMonthEndClosingListReq 月结列表-入参
type ErpMonthEndClosingListReq struct {
	SerialNumber     string `json:"serial_number"`      // 单据编号
	ClosingStartDate string `json:"closing_start_date"` // 月结开始时间
	ClosingEndDate   string `json:"closing_end_date"`   // 月结结束时间
	State            uint32 `json:"state"`              // 订单状态：1-待审核；2-已审核
	PageIndex        int    `json:"pageIndex"`          // 页码
	PageSize         int    `json:"pageSize"`           // 页面条数
}

type ErpMonthEndOrder struct {
	Model

	SerialNumber     string     `json:"serial_number"`      // 单据编号
	ClosingStartDate string     `json:"closing_start_date"` // 月结开始时间，精确到天
	ClosingEndDate   string     `json:"closing_end_date"`   // 月结结束时间，精确到天
	MakerId          uint32     `json:"maker_id"`           // 制单人 ID
	MakerName        string     `json:"maker_name"`         // 制单人名称
	MakerTime        *time.Time `json:"maker_time"`         // 制单时间
	AuditorId        uint32     `json:"auditor_id"`         // 审核人 ID
	AuditorName      string     `json:"auditor_name"`       // 审核人姓名
	AuditTime        *time.Time `json:"audit_time"`         // 审核时间
	State            uint32     `json:"state"`              // 订单状态：1-待审核；2-已审核
}

// ErpMonthEndClosingListResp 月结列表-出参
type ErpMonthEndClosingListResp struct {
	List      []ErpMonthEndOrder `json:"list"`
	Total     int                `json:"total"`     // 总条数
	PageIndex int                `json:"pageIndex"` // 页码
	PageSize  int                `json:"pageSize"`  // 每页展示条数
}

// List 查询采购订单列表
func (m *ErpMonthEndClosingListReq) List() (*ErpMonthEndClosingListResp, error) {
	resp := &ErpMonthEndClosingListResp{
		PageIndex: m.PageIndex,
		PageSize:  m.PageSize,
	}
	page := m.PageIndex - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}
	qs := orm.Eloquent.Table("erp_month_end_closing")

	if m.SerialNumber != "" {
		qs = qs.Where("serial_number=?", m.SerialNumber)
	}
	if m.State != 0 {
		qs = qs.Where("state=?", m.State)
	}

	if m.ClosingStartDate != "" {
		parse, err := time.Parse(QueryTimeFormat, m.ClosingStartDate)
		if err != nil {
			logger.Errorf("ErpMonthEndClosingList err:", err)
			return nil, err
		}
		qs = qs.Where("closing_end_date > ?", parse)
	}
	if m.ClosingEndDate != "" {
		parse, err := time.Parse(QueryTimeFormat, m.ClosingEndDate)
		if err != nil {
			logger.Errorf("ErpMonthEndClosingList err:", err)
			return nil, err
		}
		qs = qs.Where("closing_start_date < ?", parse)
	}

	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Error("count err:", logger.Field("err", err))
		return resp, err
	}
	resp.Total = int(count)
	var orders []ErpMonthEndClosing
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
	if err != nil && err != RecordNotFound {
		logger.Error("erp commodity list err:", logger.Field("err", err))
		return resp, err
	}

	var orderList []ErpMonthEndOrder
	// 校验时间
	for i, v := range orders {
		if v.MakerTime != nil && v.MakerTime.IsZero() {
			orders[i].MakerTime = nil
		}

		if v.AuditTime != nil && v.AuditTime.IsZero() {
			orders[i].AuditTime = nil
		}

		var orderInfo ErpMonthEndOrder
		orderInfo.Model = v.Model
		orderInfo.SerialNumber = v.SerialNumber
		orderInfo.ClosingStartDate = v.ClosingStartDate.Format(DateTimeFormat)
		orderInfo.ClosingEndDate = v.ClosingEndDate.Format(DateTimeFormat)
		orderInfo.MakerId = v.MakerId
		orderInfo.MakerName = v.MakerName
		orderInfo.MakerTime = orders[i].MakerTime
		orderInfo.AuditorId = v.AuditorId
		orderInfo.AuditorName = v.AuditorName
		orderInfo.AuditTime = orders[i].AuditTime
		orderInfo.State = v.State

		orderList = append(orderList, orderInfo)
	}

	resp.List = orderList
	return resp, nil
}

// ErpMonthEndClosingCreateReq 新增月结订单-入参
type ErpMonthEndClosingCreateReq struct {
	ClosingStartDate string `json:"closing_start_date" validate:"required"` // 月结开始时间，精确到天
	ClosingEndDate   string `json:"closing_end_date" validate:"required"`   // 月结结束时间，精确到天
}

// CreateErpMonthEndClosing 新增月结
func CreateErpMonthEndClosing(req *ErpMonthEndClosingCreateReq, c *gin.Context) error {
	sysUser, err := GetSysUserByCtx(c)
	if err != nil {
		return errors.New("操作失败:" + err.Error())
	}

	startDate, err := time.Parse(DateTimeFormat, req.ClosingStartDate)
	if err != nil {
		return err
	}

	endDate, err := time.Parse(DateTimeFormat, req.ClosingEndDate)
	if err != nil {
		return err
	}

	nowTime := time.Now()
	erpMonthEndClosing := &ErpMonthEndClosing{
		SerialNumber:     NewErpMonthEndClosingSerialNumber(),
		ClosingStartDate: startDate,
		ClosingEndDate:   endDate,
		MakerId:          uint32(sysUser.UserId),
		MakerName:        sysUser.NickName,
		MakerTime:        &nowTime,
		State:            ErpMonthEndClosingUnAudit,
	}

	err = orm.Eloquent.Create(erpMonthEndClosing).Error
	if err != nil {
		logger.Error("create  purchase order err:", logger.Field("err", err))
		return err
	}

	return nil
}

// NewErpMonthEndClosingSerialNumber 生成月结订单号
func NewErpMonthEndClosingSerialNumber() string {
	prefix := "YJ"

	nowTime := time.Now()
	rand.Seed(nowTime.UnixNano())
	max := 1
	for {
		if max > 5 {
			logger.Error("create sn err")
			return ""
		}
		random := rand.Intn(9000) + 1000
		sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
		exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_month_end_closing WHERE "+
			"serial_number='%s'", prefix+sn))
		if err != nil {
			logger.Error("exist sn err")
		}
		if !exist {
			return prefix + sn
		}

		max++
	}
}

// ErpMonthEndClosingDeleteReq 删除月结订单-入参
type ErpMonthEndClosingDeleteReq struct {
	SerialNumber string `json:"serial_number" validate:"required"` // 单据编号
}

// DeleteErpMonthEndClosing 删除月结订单
func DeleteErpMonthEndClosing(req *ErpMonthEndClosingDeleteReq) error {
	var orderInfo ErpMonthEndClosing
	err := orm.Eloquent.Table("erp_month_end_closing").Where("serial_number = ?", req.SerialNumber).Find(&orderInfo).Error
	if err != nil {
		logger.Error("erp_month_end_closing delete err:", logger.Field("err", err))
		return errors.New("未查询到订单")
	}

	if orderInfo.State == ErpMonthEndClosingAudited {
		logger.Errorf("erp_month_end_closing delete err, state is:", orderInfo.State)
		return errors.New("已审核订单不能删除")
	}

	err = orm.Eloquent.Delete(orderInfo).Error
	if err != nil {
		logger.Error("erp_month_end_closing delete2 err:", logger.Field("err", err))
		return err
	}

	return nil
}

// ErpMonthEndClosingEditReq 编辑月结订单-入参
type ErpMonthEndClosingEditReq struct {
	SerialNumber     string `json:"serial_number" validate:"required"`      // 单据编号
	ClosingStartDate string `json:"closing_start_date" validate:"required"` // 月结开始时间，精确到天
	ClosingEndDate   string `json:"closing_end_date" validate:"required"`   // 月结结束时间，精确到天
}

// EditErpMonthEndClosing 编辑月结订单
func EditErpMonthEndClosing(req *ErpMonthEndClosingEditReq, sysUser *SysUser) (*ErpMonthEndClosing, error) {
	// 查询订单信息
	var endOrder ErpMonthEndClosing
	err := orm.Eloquent.Table("erp_month_end_closing").Where("serial_number=?", req.SerialNumber).
		Find(&endOrder).Error
	if err != nil {
		logger.Error("erp_month_end_closing order err:", logger.Field("err", err))
		return nil, err
	}

	if endOrder.State != ErpMonthEndClosingUnAudit { // 只有待审核的订单才能编辑
		return nil, errors.New("订单不是待审核状态")
	}

	startDate, err := time.Parse(DateTimeFormat, req.ClosingStartDate)
	if err != nil {
		return nil, err
	}

	endDate, err := time.Parse(DateTimeFormat, req.ClosingEndDate)
	if err != nil {
		return nil, err
	}

	// 1-更新采购订单信息
	endOrder.ClosingStartDate = startDate
	endOrder.ClosingEndDate = endDate
	endOrder.MakerId = uint32(sysUser.UserId)
	endOrder.MakerName = sysUser.NickName

	err = orm.Eloquent.Model(&ErpMonthEndClosing{}).Where("serial_number = ?", req.SerialNumber).
		Omit("created_at").Save(endOrder).Error
	if err != nil {
		logger.Error("update erp_month_end_closing err:", logger.Field("err", err))
		return nil, err
	}

	return &endOrder, nil
}

// ErpMonthEndClosingAuditReq 审核月结订单-入参
type ErpMonthEndClosingAuditReq struct {
	SerialNumber string `json:"serial_number" validate:"required"` // 单据编号
	State        int    `json:"state"  validate:"required"`        // 审核操作: 1-审核 2-取消审核
}

// ErpMonthEndClosingDateResp 获取月结日期-出参
type ErpMonthEndClosingDateResp struct {
	StartDate string `json:"start_date"` // 月结开始时间
}

// IsMonthEndClosed 判断当前日期是否已月结
func IsMonthEndClosed(date time.Time) bool {
	// 获取当前月份的第一天
	firstDayOfMonth := time.Date(date.Year(), date.Month(), 1, 0, 0, 0, 0, date.Location())

	// 查询已月结的记录，找到最新的月结记录
	var erpMonthEndOrder ErpMonthEndClosing
	err := orm.Eloquent.Table("erp_month_end_closing").
		Where("closing_end_date >= ? AND state = ?", firstDayOfMonth, ErpMonthEndClosingAudited).
		Order("closing_end_date desc").
		First(&erpMonthEndOrder).Error
	if err != nil {
		// 如果没有找到已月结记录，直接返回 false
		if err == RecordNotFound {
			return false
		}
		logger.Error("Query month end closing record error:", logger.Field("err", err))
		return false
	}

	// 判断传入的时间是否早于已月结记录的截止日期
	return date.Before(erpMonthEndOrder.ClosingEndDate)
}
