package recipe

import (
	"context"
	"errors"
	"fmt"

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

	"gorm.io/gorm"
)

// 定义领域特定的错误
var (
	ErrPigTypeNotFound = fmt.Errorf("猪类型不存在")
)

// PigTypeService 定义了猪类型领域的核心业务服务接口
type PigTypeService interface {
	CreatePigType(ctx context.Context, pigType *models.PigType) error
	GetPigTypeByID(ctx context.Context, id uint32) (*models.PigType, error)
	UpdatePigType(ctx context.Context, pigType *models.PigType) error
	DeletePigType(ctx context.Context, id uint32) error
	ListPigTypes(ctx context.Context, opts repository.PigTypeListOptions, page, pageSize int) ([]models.PigType, int64, error)
	UpdatePigTypeNutrientRequirements(ctx context.Context, pigTypeID uint32, requirements []models.PigNutrientRequirement) error
}

// pigTypeServiceImpl 是 PigTypeService 的实现
type pigTypeServiceImpl struct {
	ctx         context.Context
	uow         repository.UnitOfWork
	pigTypeRepo repository.PigTypeRepository
}

// NewPigTypeService 创建一个新的 PigTypeService 实例
func NewPigTypeService(ctx context.Context, uow repository.UnitOfWork, pigTypeRepo repository.PigTypeRepository) PigTypeService {
	return &pigTypeServiceImpl{
		ctx:         ctx,
		uow:         uow,
		pigTypeRepo: pigTypeRepo,
	}
}

// CreatePigType 实现了创建猪类型的核心业务逻辑
func (s *pigTypeServiceImpl) CreatePigType(ctx context.Context, pigType *models.PigType) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigType")
	if err := s.pigTypeRepo.CreatePigType(serviceCtx, pigType); err != nil {
		return fmt.Errorf("创建猪类型失败: %w", err)
	}
	return nil
}

// GetPigTypeByID 实现了获取单个猪类型的逻辑
func (s *pigTypeServiceImpl) GetPigTypeByID(ctx context.Context, id uint32) (*models.PigType, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigTypeByID")
	pigType, err := s.pigTypeRepo.GetPigTypeByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, ErrPigTypeNotFound
		}
		return nil, fmt.Errorf("获取猪类型失败: %w", err)
	}
	return pigType, nil
}

// UpdatePigType 实现了更新猪类型的核心业务逻辑
func (s *pigTypeServiceImpl) UpdatePigType(ctx context.Context, pigType *models.PigType) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigType")
	if err := s.pigTypeRepo.UpdatePigType(serviceCtx, pigType); err != nil {
		return fmt.Errorf("更新猪类型失败: %m", err)
	}
	return nil
}

// DeletePigType 实现了删除猪类型的核心业务逻辑
func (s *pigTypeServiceImpl) DeletePigType(ctx context.Context, id uint32) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigType")

	// 检查实体是否存在
	_, err := s.pigTypeRepo.GetPigTypeByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return ErrPigTypeNotFound
		}
		return fmt.Errorf("获取待删除的猪类型失败: %w", err)
	}

	if err := s.pigTypeRepo.DeletePigType(serviceCtx, id); err != nil {
		return fmt.Errorf("删除猪类型失败: %w", err)
	}
	return nil
}

// ListPigTypes 实现了列出猪类型的逻辑
func (s *pigTypeServiceImpl) ListPigTypes(ctx context.Context, opts repository.PigTypeListOptions, page, pageSize int) ([]models.PigType, int64, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTypes")
	pigTypes, total, err := s.pigTypeRepo.ListPigTypes(serviceCtx, opts, page, pageSize)
	if err != nil {
		return nil, 0, fmt.Errorf("获取猪类型列表失败: %w", err)
	}
	return pigTypes, total, nil
}

// UpdatePigTypeNutrientRequirements 实现了全量更新猪类型营养需求的核心业务逻辑
func (s *pigTypeServiceImpl) UpdatePigTypeNutrientRequirements(ctx context.Context, pigTypeID uint32, requirements []models.PigNutrientRequirement) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigTypeNutrientRequirements")

	// 1. 检查猪类型是否存在
	if _, err := s.pigTypeRepo.GetPigTypeByID(serviceCtx, pigTypeID); err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return ErrPigTypeNotFound
		}
		return fmt.Errorf("获取待更新营养需求的猪类型失败: %w", err)
	}

	// 2. 在事务中执行替换操作
	err := s.uow.ExecuteInTransaction(serviceCtx, func(tx *gorm.DB) error {
		// 2.1. 删除旧的关联记录
		if err := s.pigTypeRepo.DeletePigNutrientRequirementsByPigTypeIDTx(serviceCtx, tx, pigTypeID); err != nil {
			return err // 错误已在仓库层封装，直接返回
		}

		// 2.2. 创建新的关联记录
		if err := s.pigTypeRepo.CreateBatchPigNutrientRequirementsTx(serviceCtx, tx, requirements); err != nil {
			return err // 错误已在仓库层封装，直接返回
		}

		return nil
	})

	if err != nil {
		return fmt.Errorf("更新猪类型营养需求事务执行失败: %w", err)
	}

	// 3. 操作成功，直接返回 nil
	return nil
}
