package pig

import (
	"context"
	"errors"
	"time"

	"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
)

// --- 业务错误定义 ---

var (
	// ErrPigBatchNotFound 表示当尝试访问一个不存在的猪批次时发生的错误。
	ErrPigBatchNotFound = errors.New("指定的猪批次不存在")
	// ErrPigBatchActive 表示当尝试对一个活跃的猪批次执行不允许的操作（如删除）时发生的错误。
	ErrPigBatchActive = errors.New("活跃的猪批次不能被删除")
	// ErrPigBatchNotActive 表示当猪批次不处于活跃状态，但执行了需要其活跃的操作时发生的错误。
	ErrPigBatchNotActive = errors.New("猪批次不处于活跃状态，无法修改关联猪栏")
	// ErrPenOccupiedByOtherBatch 表示当尝试将一个已经被其他批次占用的猪栏分配给新批次时发生的错误。
	ErrPenOccupiedByOtherBatch = errors.New("猪栏已被其他批次使用")
	// ErrPenStatusInvalidForAllocation 表示猪栏的当前状态（例如，'维修中'）不允许被分配。
	ErrPenStatusInvalidForAllocation = errors.New("猪栏状态不允许分配")
	// ErrPenNotFound 表示猪栏不存在
	ErrPenNotFound = errors.New("指定的猪栏不存在")
	// ErrPenNotAssociatedWithBatch 表示猪栏未与该批次关联
	ErrPenNotAssociatedWithBatch = errors.New("猪栏未与该批次关联")
	// ErrPenNotEmpty 表示猪栏内仍有猪只，不允许执行当前操作。
	ErrPenNotEmpty = errors.New("猪栏内仍有猪只，无法执行此操作")
	// ErrInvalidOperation 非法操作
	ErrInvalidOperation = errors.New("非法操作")
)

// --- 领域服务接口 ---

// PigBatchService 定义了猪批次管理的核心业务逻辑接口。
// 它抽象了所有与猪批次相关的操作，使得应用层可以依赖于此接口，而不是具体的实现。
type PigBatchService interface {
	// CreatePigBatch 创建猪批次，并记录初始日志。
	CreatePigBatch(ctx context.Context, operatorID uint32, batch *models.PigBatch) (*models.PigBatch, error)
	// GetPigBatch 获取单个猪批次。
	GetPigBatch(ctx context.Context, id uint32) (*models.PigBatch, error)
	// UpdatePigBatch 更新猪批次信息。
	UpdatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, error)
	// DeletePigBatch 删除猪批次，包含业务规则校验。
	DeletePigBatch(ctx context.Context, id uint32) error
	// ListPigBatches 批量查询猪批次。
	ListPigBatches(ctx context.Context, isActive *bool) ([]*models.PigBatch, error)
	// AssignEmptyPensToBatch 为猪群分配空栏
	AssignEmptyPensToBatch(ctx context.Context, batchID uint32, penIDs []uint32, operatorID uint32) error
	// MovePigsIntoPen 将猪只从“虚拟库存”移入指定猪栏
	MovePigsIntoPen(ctx context.Context, batchID uint32, toPenID uint32, quantity int, operatorID uint32, remarks string) error
	// ReclassifyPenToNewBatch 连猪带栏，整体划拨到另一个猪群
	ReclassifyPenToNewBatch(ctx context.Context, fromBatchID uint32, toBatchID uint32, penID uint32, operatorID uint32, remarks string) error
	// RemoveEmptyPenFromBatch 将一个猪栏移除出猪群，此方法需要在猪栏为空的情况下执行。
	RemoveEmptyPenFromBatch(ctx context.Context, batchID uint32, penID uint32) error

	// GetCurrentPigQuantity 获取指定猪批次的当前猪只数量。
	GetCurrentPigQuantity(ctx context.Context, batchID uint32) (int, error)
	// GetCurrentPigsInPen 获取指定猪栏的当前存栏量。
	GetCurrentPigsInPen(ctx context.Context, penID uint32) (int, error)
	// GetTotalPigsInPensForBatch 获取指定猪群下所有猪栏的当前总存栏数
	GetTotalPigsInPensForBatch(ctx context.Context, batchID uint32) (int, error)

	UpdatePigBatchQuantity(ctx context.Context, operatorID uint32, batchID uint32, changeType models.LogChangeType, changeAmount int, changeReason string, happenedAt time.Time) error

	// ---交易子服务---
	// SellPigs 处理卖猪的业务逻辑。
	SellPigs(ctx context.Context, batchID uint32, penID uint32, quantity int, unitPrice float32, tatalPrice float32, traderName string, tradeDate time.Time, remarks string, operatorID uint32) error
	// BuyPigs 处理买猪的业务逻辑。
	BuyPigs(ctx context.Context, batchID uint32, penID uint32, quantity int, unitPrice float32, tatalPrice float32, traderName string, tradeDate time.Time, remarks string, operatorID uint32) error

	// ---调栏子服务 ---
	TransferPigsAcrossBatches(ctx context.Context, sourceBatchID uint32, destBatchID uint32, fromPenID uint32, toPenID uint32, quantity uint32, operatorID uint32, remarks string) error
	TransferPigsWithinBatch(ctx context.Context, batchID uint32, fromPenID uint32, toPenID uint32, quantity uint32, operatorID uint32, remarks string) error

	// --- 病猪管理相关方法 ---
	// RecordSickPigs 记录新增病猪事件。
	RecordSickPigs(ctx context.Context, operatorID uint32, batchID uint32, penID uint32, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
	// RecordSickPigRecovery 记录病猪康复事件。
	RecordSickPigRecovery(ctx context.Context, operatorID uint32, batchID uint32, penID uint32, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
	// RecordSickPigDeath 记录病猪死亡事件。
	RecordSickPigDeath(ctx context.Context, operatorID uint32, batchID uint32, penID uint32, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error
	// RecordSickPigCull 记录病猪淘汰事件。
	RecordSickPigCull(ctx context.Context, operatorID uint32, batchID uint32, penID uint32, quantity int, treatmentLocation models.PigBatchSickPigTreatmentLocation, happenedAt time.Time, remarks string) error

	// --- 正常猪只管理相关方法 ---
	// RecordDeath 记录正常猪只死亡事件。
	RecordDeath(ctx context.Context, operatorID uint32, batchID uint32, penID uint32, quantity int, happenedAt time.Time, remarks string) error
	// RecordCull 记录正常猪只淘汰事件。
	RecordCull(ctx context.Context, operatorID uint32, batchID uint32, penID uint32, quantity int, happenedAt time.Time, remarks string) error
}

// pigBatchService 是 PigBatchService 接口的具体实现。
// 它作为猪群领域的主服务，封装了所有业务逻辑。
type pigBatchService struct {
	ctx             context.Context
	pigBatchRepo    repository.PigBatchRepository    // 猪批次仓库
	pigBatchLogRepo repository.PigBatchLogRepository // 猪批次日志仓库
	uow             repository.UnitOfWork            // 工作单元，用于管理事务
	transferSvc     PigPenTransferManager            // 调栏子服务
	tradeSvc        PigTradeManager                  // 交易子服务
	sickSvc         SickPigManager                   // 病猪子服务
}

// NewPigBatchService 是 pigBatchService 的构造函数。
// 它通过依赖注入的方式，创建并返回一个 PigBatchService 接口的实例。
func NewPigBatchService(
	ctx context.Context,
	pigBatchRepo repository.PigBatchRepository,
	pigBatchLogRepo repository.PigBatchLogRepository,
	uow repository.UnitOfWork,
	transferSvc PigPenTransferManager,
	tradeSvc PigTradeManager,
	sickSvc SickPigManager,
) PigBatchService {
	return &pigBatchService{
		ctx:             ctx,
		pigBatchRepo:    pigBatchRepo,
		pigBatchLogRepo: pigBatchLogRepo,
		uow:             uow,
		transferSvc:     transferSvc,
		tradeSvc:        tradeSvc,
		sickSvc:         sickSvc,
	}
}
