package service

import (
	"context"
	"errors"
	"fmt"

	"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
	"git.huangwc.com/pig/pig-farm-controller/internal/domain/recipe"
	"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"
)

// 定义猪类型服务特定的错误
var (
	ErrPigTypeNotFound = errors.New("猪类型不存在")
)

// PigTypeService 定义了猪类型相关的应用服务接口
type PigTypeService interface {
	CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error)
	UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error)
	DeletePigType(ctx context.Context, id uint32) error
	GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error)
	ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error)
	UpdatePigTypeNutrientRequirements(ctx context.Context, id uint32, req *dto.UpdatePigTypeNutrientRequirementsRequest) (*dto.PigTypeResponse, error)
}

// pigTypeServiceImpl 是 PigTypeService 接口的实现
type pigTypeServiceImpl struct {
	ctx       context.Context
	recipeSvc recipe.Service
}

// NewPigTypeService 创建一个新的 PigTypeService 实例
func NewPigTypeService(ctx context.Context, recipeSvc recipe.Service) PigTypeService {
	return &pigTypeServiceImpl{
		ctx:       ctx,
		recipeSvc: recipeSvc,
	}
}

// CreatePigType 创建猪类型
func (s *pigTypeServiceImpl) CreatePigType(ctx context.Context, req *dto.CreatePigTypeRequest) (*dto.PigTypeResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigType")

	pigType := &models.PigType{
		BreedID:         req.BreedID,
		AgeStageID:      req.AgeStageID,
		Description:     req.Description,
		DailyFeedIntake: req.DailyFeedIntake,
		DailyGainWeight: req.DailyGainWeight,
		MinDays:         req.MinDays,
		MaxDays:         req.MaxDays,
		MinWeight:       req.MinWeight,
		MaxWeight:       req.MaxWeight,
	}

	if err := s.recipeSvc.CreatePigType(serviceCtx, pigType); err != nil {
		if errors.Is(err, recipe.ErrPigBreedNotFound) {
			return nil, ErrPigBreedNotFound
		}
		if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
			return nil, ErrPigAgeStageNotFound
		}
		return nil, fmt.Errorf("创建猪类型失败: %w", err)
	}
	// 创建后需要重新获取，以包含关联数据
	createdPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, pigType.ID)
	if err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生，因为刚创建
			return nil, ErrPigTypeNotFound
		}
		return nil, fmt.Errorf("创建猪类型后获取详情失败: %w", err)
	}
	return dto.ConvertPigTypeToDTO(createdPigType), nil
}

// UpdatePigType 更新猪类型
func (s *pigTypeServiceImpl) UpdatePigType(ctx context.Context, id uint32, req *dto.UpdatePigTypeRequest) (*dto.PigTypeResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigType")

	pigType := &models.PigType{
		Model:           models.Model{ID: id},
		BreedID:         req.BreedID,
		AgeStageID:      req.AgeStageID,
		Description:     req.Description,
		DailyFeedIntake: req.DailyFeedIntake,
		DailyGainWeight: req.DailyGainWeight,
		MinDays:         req.MinDays,
		MaxDays:         req.MaxDays,
		MinWeight:       req.MinWeight,
		MaxWeight:       req.MaxWeight,
	}

	if err := s.recipeSvc.UpdatePigType(serviceCtx, pigType); err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) {
			return nil, ErrPigTypeNotFound
		}
		if errors.Is(err, recipe.ErrPigBreedNotFound) {
			return nil, ErrPigBreedNotFound
		}
		if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
			return nil, ErrPigAgeStageNotFound
		}
		return nil, fmt.Errorf("更新猪类型失败: %w", err)
	}
	// 更新后需要重新获取，以包含关联数据
	updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) { // 理论上不应该发生，因为刚更新成功
			return nil, ErrPigTypeNotFound
		}
		return nil, fmt.Errorf("更新猪类型后获取详情失败: %w", err)
	}
	return dto.ConvertPigTypeToDTO(updatedPigType), nil
}

// DeletePigType 删除猪类型
func (s *pigTypeServiceImpl) DeletePigType(ctx context.Context, id uint32) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigType")
	err := s.recipeSvc.DeletePigType(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) {
			return ErrPigTypeNotFound
		}
		return fmt.Errorf("删除猪类型失败: %w", err)
	}
	return nil
}

// GetPigType 获取单个猪类型
func (s *pigTypeServiceImpl) GetPigType(ctx context.Context, id uint32) (*dto.PigTypeResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigType")

	pigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) {
			return nil, ErrPigTypeNotFound
		}
		return nil, fmt.Errorf("获取猪类型失败: %w", err)
	}
	return dto.ConvertPigTypeToDTO(pigType), nil
}

// ListPigTypes 列出猪类型
func (s *pigTypeServiceImpl) ListPigTypes(ctx context.Context, req *dto.ListPigTypeRequest) (*dto.ListPigTypeResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTypes")

	opts := repository.PigTypeListOptions{
		BreedID:      req.BreedID,
		AgeStageID:   req.AgeStageID,
		BreedName:    req.BreedName,
		AgeStageName: req.AgeStageName,
		OrderBy:      req.OrderBy,
	}
	pigTypes, total, err := s.recipeSvc.ListPigTypes(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, fmt.Errorf("获取猪类型列表失败: %w", err)
	}

	return dto.ConvertPigTypeListToDTO(pigTypes, total, req.Page, req.PageSize), nil
}

// UpdatePigTypeNutrientRequirements 全量更新猪类型的营养需求
func (s *pigTypeServiceImpl) UpdatePigTypeNutrientRequirements(ctx context.Context, id uint32, req *dto.UpdatePigTypeNutrientRequirementsRequest) (*dto.PigTypeResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigTypeNutrientRequirements")

	// 1. 将 DTO 转换为领域模型
	requirements := make([]models.PigNutrientRequirement, len(req.NutrientRequirements))
	for i, item := range req.NutrientRequirements {
		requirements[i] = models.PigNutrientRequirement{
			PigTypeID:      id, // 设置所属的 PigTypeID
			NutrientID:     item.NutrientID,
			MinRequirement: item.MinRequirement,
			MaxRequirement: item.MaxRequirement,
		}
	}

	// 2. 调用领域服务执行更新命令
	err := s.recipeSvc.UpdatePigTypeNutrientRequirements(serviceCtx, id, requirements)
	if err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) {
			return nil, ErrPigTypeNotFound
		}
		// 此处可以根据领域层可能返回的其他特定错误进行转换
		return nil, fmt.Errorf("更新猪类型营养需求失败: %w", err)
	}

	// 3. 更新成功后，调用查询服务获取最新的猪类型信息
	updatedPigType, err := s.recipeSvc.GetPigTypeByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigTypeNotFound) {
			// 理论上不应该发生，因为刚更新成功
			return nil, ErrPigTypeNotFound
		}
		return nil, fmt.Errorf("更新后获取猪类型信息失败: %w", err)
	}

	// 4. 将领域模型转换为 DTO 并返回
	return dto.ConvertPigTypeToDTO(updatedPigType), nil
}
