package backend

import (
	"context"
	"fmt"
	"kpt-pasture/model"
	"kpt-pasture/util"
	"strconv"
	"strings"

	"gitee.com/xuyiping_admin/pkg/xerr"

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

func (s *StoreEntry) SubmitEventLog(ctx context.Context, pastureId int64, cow *model.Cow, eventType pasturePb.EventType_Kind, req interface{}) *model.EventCowLog {
	var (
		desc, remarks    = "", ""
		eventTypeName    = s.EventTypeMap()[eventType]
		eventAt          = int64(0)
		eventCategoryMap = s.eventCategoryMap()
		penMap           = s.PenMap(ctx, pastureId)
		cowTypeMap       = s.CowTypeMap()
		operationUser    = &model.SystemUser{}
	)

	switch eventType {
	case pasturePb.EventType_Enter:
		data := req.(*pasturePb.EventEnterRequest)
		eventAt = int64(data.EnterAt)
		remarks = data.Remarks
		sourceMap := s.CowSourceMap()
		sex := "公"
		if data.Sex == pasturePb.Genders_Female {
			sex = "母"
		}
		desc = fmt.Sprintf("性别: %s; 栏舍: %s; 体重: %s kg; 价格: %s; 来源: %s;", sex, penMap[cow.PenId].Name,
			strconv.FormatFloat(float64(data.Weight), 'f', 2, 64),
			strconv.FormatFloat(float64(data.Price), 'f', 2, 64), sourceMap[cow.SourceKind])
	case pasturePb.EventType_Transfer_Ben:
		data := req.(*model.EventTransferGroup)
		transferAt, _ := util.TimeParseLocal(model.LayoutTime, data.TransferDate)
		eventAt = transferAt.Unix()
		remarks = data.Remarks
		operationUser.Id = data.OperationId
		operationUser.Name = data.OperationName
		desc = fmt.Sprintf("转出栏舍: %s; 转入栏舍: %s", penMap[data.PenOutId].Name, penMap[data.PenInId].Name)
	case pasturePb.EventType_Body_Score:
	case pasturePb.EventType_Disease:
		data := req.(*model.EventCowDisease)
		eventAt = data.DiseaseAt
		remarks = data.Remarks
		operationUser.Id = int64(data.OperationId)
		operationUser.Name = data.OperationName
		desc = fmt.Sprintf("疾病名称: %s; 状态: 治疗中;", data.DiseaseName)
	case pasturePb.EventType_Pregnancy_Check:
		data := req.(*PregnantCheckBatchModel)
		eventAt = int64(data.PregnantCheckAt)
		if data.PregnantCheckResult == pasturePb.PregnantCheckResult_Pregnant {
			desc += fmt.Sprintf("孕检方式: %s; 孕检结果: %s", s.PregnantCheckMethodMap()[data.PregnantCheckMethod], s.MatingResultMap()[pasturePb.MatingResult_Pregnant])
		}
		if data.PregnantCheckResult == pasturePb.PregnantCheckResult_UnPregnant {
			desc += fmt.Sprintf("孕检方式: %s", s.PregnantCheckMethodMap()[data.PregnantCheckMethod])
			if cow.BreedStatus == pasturePb.BreedStatus_Abort {
				desc += fmt.Sprintf("; 复检结果: %s", s.MatingResultMap()[pasturePb.MatingResult_Abort])
			}
			if cow.BreedStatus == pasturePb.BreedStatus_Empty {
				desc += fmt.Sprintf("; 孕检结果: %s", s.MatingResultMap()[pasturePb.MatingResult_Empty])
			}
		}
		operationUser.Id = data.OperationUser.Id
		operationUser.Name = data.OperationUser.Name
		remarks = data.Remarks
	case pasturePb.EventType_Estrus:
		data := req.(*model.EventEstrus)
		eventAt = data.PlanDay
		isMating := "否"
		if data.IsMating == pasturePb.IsShow_Ok {
			isMating = "是"
		}
		desc = fmt.Sprintf("发情揭发方式:%s;是否配种:%s;", s.ExposeEstrusTypeMap()[data.ExposeEstrusType], isMating)
		operationUser.Id = data.OperationId
		operationUser.Name = data.OperationName
		remarks = data.Remarks
	case pasturePb.EventType_Calving:
		data := req.(*pasturePb.EventCalving)
		eventAt = int64(data.CalvingAt)
		desc = fmt.Sprintf("怀孕天数:%d;难产等级: %s;产子数量: %d;", cow.PregnancyAge, s.CalvingLevelMap()[data.CalvingLevel], data.ChildNumber)
		if data.CalvingLevel > pasturePb.CalvingLevel_Natural_Childbirth {
			desc += fmt.Sprintf("难产原因: %s", s.DystociaReasonMap()[data.DystociaReason])
		}
		ly, qy, die := 0, 0, 0
		earNumber := ""
		if len(data.CalfItemList) > 0 {
			for _, v := range data.CalfItemList {
				if v.IsLive == pasturePb.IsShow_Ok && v.IsAdoption == pasturePb.IsShow_No {
					qy++
				}
				if v.IsLive == pasturePb.IsShow_No {
					die++
				}
				if v.IsAdoption == pasturePb.IsShow_Ok {
					ly++
					earNumber += fmt.Sprintf("犊牛耳号: %s,出生体重: %s KG;", v.EarNumber, strconv.FormatFloat(float64(v.Weight), 'f', 2, 64))
				}
			}
		}
		desc += fmt.Sprintf("留养: %d个 %s;弃养: %d; 死亡: %d个", ly, earNumber, qy, die)
		operationUser.Id = int64(data.OperationId)
		operationUser.Name = data.OperationName
		remarks = data.Remarks
	case pasturePb.EventType_Seme_Time:
		data := req.(*pasturePb.EventSameTime)
		eventAt = int64(data.SameTimeAt)
		desc = fmt.Sprintf("同期名称: %s;激素名称: %s;剂量:%f;操作人: %s", data.SameTimeTypeName, data.DrugsName, data.Usage, data.OperationName)
		operationUser.Id = int64(data.OperationId)
		operationUser.Name = data.OperationName
		remarks = data.Remarks
	case pasturePb.EventType_Mating:
		data := req.(*model.EventMatingCheckBatchModel)
		eventAt = data.MatingAt
		desc = fmt.Sprintf("配种公牛: %s;配种结果:未知", data.FrozenSemen.BullId)
		operationUser.Id = data.OperationUser.Id
		operationUser.Name = data.OperationUser.Name
		remarks = data.Remarks
	case pasturePb.EventType_Birth:
		eventAt = cow.BirthAt
		desc = fmt.Sprintf("出生体重: %s KG;母号:%s;父号: %s", strconv.FormatFloat(float64(cow.BirthWeight)/1000, 'f', 2, 64), cow.MotherNumber, cow.FatherNumber)
	case pasturePb.EventType_Death:
		data := req.(*model.EventDeparture)
		eventAt = data.DepartureAt
		desc = fmt.Sprintf("死亡原因: %s", data.ReasonName)
		operationUser.Id = data.OperationId
		operationUser.Name = data.OperationName
	case pasturePb.EventType_Transfer_Out:
	case pasturePb.EventType_Transfer_In:
	case pasturePb.EventType_Out:
		data := req.(*model.EventDeparture)
		eventAt = data.DepartureAt
		desc = fmt.Sprintf("淘汰原因: %s", data.ReasonName)
		operationUser.Id = data.OperationId
		operationUser.Name = data.OperationName
	case pasturePb.EventType_Immunication:
		data := req.(*model.EventImmunizationPlan)
		eventAt = data.RealityDay
		desc = fmt.Sprintf("免疫名称: %s;药物名称: %s;剂量: %d %s", data.PlanName, data.DrugsName, data.Usage, data.UnitName)
		operationUser.Id = data.OperationId
		operationUser.Name = data.OperationName
	case pasturePb.EventType_Weaning:
		data := req.(*pasturePb.EventWeaningBatch)
		eventAt = int64(data.WeaningAt)
		operationUser.Id = int64(data.OperationId)
		operationUser.Name = data.OperationName
		remarks = data.Remarks
		for _, v := range data.Items {
			if int64(v.CowId) == cow.Id {
				desc = fmt.Sprintf("具体体重: %s", strconv.FormatFloat(float64(v.Weight), 'f', 2, 64))
				break
			}
		}
	case pasturePb.EventType_Sale:
		data := req.(*pasturePb.EventCowSale)
		eventAt = int64(data.SaleAt)
		for _, v := range data.CowIds {
			if int64(v) == cow.Id {
				desc = fmt.Sprintf("经销商: %s,单价: %s", data.DealerName, strconv.FormatFloat(float64(data.SalePrice), 'f', 2, 64))
				break
			}
		}
	case pasturePb.EventType_Abort:
		data := req.(*AbortionCheckBatchModel)
		eventAt = data.EventAbortion.AbortionAt
		operationUser.Id = data.OperationUser.Id
		operationUser.Name = data.OperationUser.Name
		remarks = data.EventAbortion.Remarks
		desc = fmt.Sprintf("流产原因: %s", data.EventAbortion.AbortionReasonsName)
	case pasturePb.EventType_Weight:
		data := req.(*pasturePb.EventWeight)
		eventAt = int64(data.WeightAt)
		operationUser.Id = int64(data.OperationId)
		operationUser.Name = data.OperationName
		remarks = data.Remarks
		desc = fmt.Sprintf("日龄: %d;体重: %s kg", cow.DayAge, strconv.FormatFloat(float64(data.Weight), 'f', 2, 64))
	case pasturePb.EventType_Castrated:
	case pasturePb.EventType_Insect_Repellent:
	}
	newEventCowLogModel := &model.EventCowLogModel{
		Cow:               cow,
		CowTypeName:       cowTypeMap[cow.CowType],
		OperationUser:     operationUser,
		EventCategoryKind: eventCategoryMap[eventType],
		EventAt:           eventAt,
		EventType:         eventType,
		EventTypeName:     eventTypeName,
		Description:       desc,
		Remarks:           remarks,
		PenName:           penMap[cow.PenId].Name,
	}
	return model.NewEventCowLog(newEventCowLogModel)
}

func (s *StoreEntry) UpdateMatingResultEventCowLogByCowId(ctx context.Context, cowId int64, newResult string) error {
	newEventCowLog := &model.EventCowLog{CowId: cowId}
	if err := s.DB.Table(newEventCowLog.TableName()).
		Where("cow_id = ?", cowId).
		Where("event_category_kind = ?", pasturePb.EventCategory_Breed).
		Where("event_type = ?", pasturePb.EventType_Mating).
		Order("id desc").
		First(newEventCowLog).Error; err != nil {
		return xerr.WithStack(err)
	} else {
		desc := strings.ReplaceAll(newEventCowLog.EventDescription, "未知", newResult)
		if err = s.DB.Table(newEventCowLog.TableName()).
			Where("id = ?", newEventCowLog.Id).
			Update("event_description", desc).Error; err != nil {
			return xerr.WithStack(err)
		}
	}
	return nil
}