package model

import (
	"fmt"
	"kpt-pasture/util"
	"strings"
	"time"

	"gitee.com/xuyiping_admin/pkg/logger/zaplog"
	"go.uber.org/zap"

	pasturePb "gitee.com/xuyiping_admin/go_proto/proto/go/backend/cow"
)

// 执行时间超过当前创单时间5秒的工单,不生效
const (
	expireTimeSec = 5
	secondsInDay  = 86400
)

type WorkOrderSub struct {
	Id                 int64                          `json:"id"`
	WorkOrderSubNumber string                         `json:"workOrderSubNumber"`
	WorkOrderMasterId  int64                          `json:"workOrderMasterId"`
	ExecTime           int64                          `json:"execTime"`
	Status             pasturePb.WorkOrderStatus_Kind `json:"status"`
	ExecUserId         int64                          `json:"execUserId"`
	SetUserIds         string                         `json:"setUserIds"`
	IsShow             pasturePb.IsShow_Kind          `json:"isShow"`
	FinishTime         int64                          `json:"finishTime"`
	Remarks            string                         `json:"remarks"`
	CreatedAt          int64                          `json:"createdAt"`
	UpdatedAt          int64                          `json:"updatedAt"`
}

func (w *WorkOrderSub) TableName() string {
	return "work_order_sub"
}

func NewWorkOrderSub(req *WorkOrderMaster) []*WorkOrderSub {
	workOrderSubList := make([]*WorkOrderSub, 0)
	if req.IsShow == pasturePb.IsShow_No {
		return workOrderSubList
	}

	nowTime := time.Now()
	execTime, err := util.ConvertParseLocalUnix(req.ExecTime)
	if err != nil {
		zaplog.Error("NewWorkOrderSub", zap.Any("ConvertParseLocalUnix", err))
		return workOrderSubList
	}

	isToday := execTime <= nowTime.Unix()+expireTimeSec
	// 一次性工单就生成当天的工单记录
	if req.Frequency == pasturePb.WorkOrderFrequency_None && isToday {
		return workOrderSubList
	}

	switch req.Frequency {
	case pasturePb.WorkOrderFrequency_None:
		currentExecTime := execTime
		workOrderSubList = append(workOrderSubList, &WorkOrderSub{
			WorkOrderMasterId:  req.Id,
			ExecTime:           currentExecTime,
			ExecUserId:         0,
			SetUserIds:         req.ExecPersons,
			WorkOrderSubNumber: fmt.Sprintf("s%s%d", LayoutDate, time.Now().Unix()),
			Status:             pasturePb.WorkOrderStatus_Created,
			IsShow:             pasturePb.IsShow_Ok,
			Remarks:            "",
		})

	case pasturePb.WorkOrderFrequency_Daily, pasturePb.WorkOrderFrequency_Weekly, pasturePb.WorkOrderFrequency_Monthly:
		// 本月剩余天数
		remainingDays := util.GetMonthRemainDay()
		for i := 0; i < remainingDays; i++ {
			if isToday && i == 0 {
				continue
			}
			currentExecTime := execTime + int64(i)*secondsInDay
			t := time.Unix(currentExecTime, 0)
			if shouldGenerateSubOrder(req.Frequency, t, req.WeekMonthValue) {
				sub := &WorkOrderSub{
					WorkOrderMasterId:  req.Id,
					ExecTime:           currentExecTime,
					ExecUserId:         0,
					WorkOrderSubNumber: fmt.Sprintf("s%s%d", LayoutDate, execTime),
					Status:             pasturePb.WorkOrderStatus_Created,
					IsShow:             pasturePb.IsShow_Ok,
					SetUserIds:         req.ExecPersons,
					Remarks:            "",
				}
				workOrderSubList = append(workOrderSubList, sub)
			}
		}
	}
	return workOrderSubList
}

func shouldGenerateSubOrder(frequency pasturePb.WorkOrderFrequency_Kind, t time.Time, weekMonth string) bool {
	switch frequency {
	case pasturePb.WorkOrderFrequency_Daily:
		return true
	case pasturePb.WorkOrderFrequency_Weekly, pasturePb.WorkOrderFrequency_Monthly:
		weekMonthDays := strings.Split(weekMonth, ",")
		dayOfWeekOrMonth := int64(t.Weekday())
		if frequency == pasturePb.WorkOrderFrequency_Monthly {
			dayOfWeekOrMonth = int64(t.Day())
		}
		for _, day := range weekMonthDays {
			if day == fmt.Sprintf("%d", dayOfWeekOrMonth) {
				return true
			}
		}
	}
	return false
}

type WorkOrderSubSlice []*WorkOrderSub

func (w WorkOrderSubSlice) ToPB(mMap map[int64]*WorkOrderMaster, priorityMap map[pasturePb.Priority_Kind]string) []*pasturePb.UserWorkOrderList {
	res := make([]*pasturePb.UserWorkOrderList, len(w))
	for i, v := range w {
		res[i] = &pasturePb.UserWorkOrderList{
			WorkOrderNumber:       v.WorkOrderSubNumber,
			WorkOrderName:         mMap[v.WorkOrderMasterId].Name,
			WorkOrderId:           int32(v.WorkOrderMasterId),
			WorkOrderCategoryName: mMap[v.WorkOrderMasterId].CategoryName,
			WorkOrderPriorityName: priorityMap[mMap[v.WorkOrderMasterId].Priority],
			Photos:                strings.Split(mMap[v.WorkOrderMasterId].Photos, ","),
			Remarks:               mMap[v.WorkOrderMasterId].Remarks,
			Status:                v.Status,
		}
	}
	return res
}