package models

import (
	"time"
)

// StockLogSourceType 定义了库存日志来源的类型
type StockLogSourceType string

const (
	StockLogSourcePurchase      StockLogSourceType = "采购入库"
	StockLogSourceFeeding       StockLogSourceType = "饲喂出库"
	StockLogSourceDeteriorate   StockLogSourceType = "变质出库"
	StockLogSourceSale          StockLogSourceType = "售卖出库"
	StockLogSourceMiscellaneous StockLogSourceType = "杂用领取"
	StockLogSourceManual        StockLogSourceType = "手动盘点"
	StockLogSourceFermentStart  StockLogSourceType = "发酵出库" // 原料投入发酵，从库存中扣除
	StockLogSourceFermentEnd    StockLogSourceType = "发酵入库" // 发酵料产出，作为新原料计入库存
)

// RawMaterial 代表一种原料的静态定义，是系统中的原料字典。
type RawMaterial struct {
	Model
	Name             string  `gorm:"size:100;not null;comment:原料名称"`
	Description      string  `gorm:"size:255;comment:描述"`
	ReferencePrice   float32 `gorm:"comment:参考价格(kg/元)"`
	MaxAdditionRatio float32 `gorm:"comment:该物质最大添加比例"`
	// RawMaterialNutrients 关联此原料的所有营养素含量信息
	RawMaterialNutrients []RawMaterialNutrient `gorm:"foreignKey:RawMaterialID"`
}

func (RawMaterial) TableName() string {
	return "raw_materials"
}

// Nutrient 代表一种营养素的静态定义，是系统中的营养素字典。
// 注意：本系统强制统一营养单位，不再单独设置Unit字段。
// 约定：宏量营养素(粗蛋白等)单位为百分比(%)，微量元素(氨基酸等)单位为毫克/千克(mg/kg)。
type Nutrient struct {
	Model
	Name        string `gorm:"size:100;not null;comment:营养素名称"`
	Description string `gorm:"size:255;comment:描述"`
	// RawMaterialNutrients 记录营养在哪些原料中存在且比例是多少
	RawMaterialNutrients []RawMaterialNutrient `gorm:"foreignKey:NutrientID"`
}

func (Nutrient) TableName() string {
	return "nutrients"
}

// RawMaterialNutrient 存储了特定原料的特定营养素的含量值。
// 这是连接原料和营养素的“营养价值表”。
// 注意：其唯一性由 postgres.go 中的部分唯一索引保证，以兼容软删除。
type RawMaterialNutrient struct {
	Model
	RawMaterialID uint32      `gorm:"not null;comment:关联的原料ID"`
	RawMaterial   RawMaterial `gorm:"foreignKey:RawMaterialID"`
	NutrientID    uint32      `gorm:"not null;comment:关联的营养素ID"`
	Nutrient      Nutrient    `gorm:"foreignKey:NutrientID"`
	// Value 存储营养价值含量。单位遵循 Nutrient 表中定义的系统级约定。
	Value float32 `gorm:"not null;comment:营养价值含量"`
}

func (RawMaterialNutrient) TableName() string {
	return "raw_material_nutrients"
}

// RawMaterialStockLog 记录了原料库存的所有变动，提供了完整的追溯链。
// 它是保证数据一致性和可审计性的核心。
type RawMaterialStockLog struct {
	Model
	RawMaterialID  uint32      `gorm:"not null;index;comment:关联的原料ID"`
	RawMaterial    RawMaterial `gorm:"foreignKey:RawMaterialID"`
	ChangeAmount   float32     `gorm:"not null;comment:变动数量, 正数为入库, 负数为出库, 单位: g"`
	BeforeQuantity float32     `gorm:"not null;comment:变动前库存数量, 单位: g"`
	AfterQuantity  float32     `gorm:"not null;comment:变动后库存数量, 单位: g"`
	// SourceType 告知 SourceID 关联的是哪种类型的业务单据。
	SourceType StockLogSourceType `gorm:"size:50;not null;index;comment:库存变动来源类型"`
	// SourceID 是一个多态外键，关联到触发此次变动的业务单据ID (如采购单ID)。
	// 对于无单据的业务(如手动盘点)，此字段可为NULL。
	SourceID   *uint32   `gorm:"index;comment:来源业务单据的ID"`
	HappenedAt time.Time `gorm:"primaryKey;comment:业务发生时间"`
	Remarks    string    `gorm:"comment:备注"`
}

func (RawMaterialStockLog) TableName() string {
	return "raw_material_stock_logs"
}
