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 (
	ErrPigBreedInUse    = errors.New("猪品种正在被猪类型使用，无法删除")
	ErrPigBreedNotFound = errors.New("猪品种不存在")
)

// PigBreedService 定义了猪品种相关的应用服务接口
type PigBreedService interface {
	CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error)
	UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error)
	DeletePigBreed(ctx context.Context, id uint32) error
	GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error)
	ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error)
}

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

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

// CreatePigBreed 创建猪品种
func (s *pigBreedServiceImpl) CreatePigBreed(ctx context.Context, req *dto.CreatePigBreedRequest) (*dto.PigBreedResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigBreed")

	breed := &models.PigBreed{
		Name:               req.Name,
		Description:        req.Description,
		ParentInfo:         req.ParentInfo,
		AppearanceFeatures: req.AppearanceFeatures,
		BreedAdvantages:    req.BreedAdvantages,
		BreedDisadvantages: req.BreedDisadvantages,
	}

	if err := s.recipeSvc.CreatePigBreed(serviceCtx, breed); err != nil {
		return nil, fmt.Errorf("创建猪品种失败: %w", err)
	}
	return dto.ConvertPigBreedToDTO(breed), nil
}

// UpdatePigBreed 更新猪品种
func (s *pigBreedServiceImpl) UpdatePigBreed(ctx context.Context, id uint32, req *dto.UpdatePigBreedRequest) (*dto.PigBreedResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigBreed")

	breed := &models.PigBreed{
		Model:              models.Model{ID: id},
		Name:               req.Name,
		Description:        req.Description,
		ParentInfo:         req.ParentInfo,
		AppearanceFeatures: req.AppearanceFeatures,
		BreedAdvantages:    req.BreedAdvantages,
		BreedDisadvantages: req.BreedDisadvantages,
	}

	if err := s.recipeSvc.UpdatePigBreed(serviceCtx, breed); err != nil {
		if errors.Is(err, recipe.ErrPigBreedNotFound) {
			return nil, ErrPigBreedNotFound
		}
		return nil, fmt.Errorf("更新猪品种失败: %w", err)
	}
	return dto.ConvertPigBreedToDTO(breed), nil
}

// DeletePigBreed 删除猪品种
func (s *pigBreedServiceImpl) DeletePigBreed(ctx context.Context, id uint32) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigBreed")
	err := s.recipeSvc.DeletePigBreed(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigBreedNotFound) {
			return ErrPigBreedNotFound
		}
		if errors.Is(err, recipe.ErrPigBreedInUse) {
			return ErrPigBreedInUse
		}
		return fmt.Errorf("删除猪品种失败: %w", err)
	}
	return nil
}

// GetPigBreed 获取单个猪品种
func (s *pigBreedServiceImpl) GetPigBreed(ctx context.Context, id uint32) (*dto.PigBreedResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigBreed")

	breed, err := s.recipeSvc.GetPigBreedByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigBreedNotFound) {
			return nil, ErrPigBreedNotFound
		}
		return nil, fmt.Errorf("获取猪品种失败: %w", err)
	}
	return dto.ConvertPigBreedToDTO(breed), nil
}

// ListPigBreeds 列出猪品种
func (s *pigBreedServiceImpl) ListPigBreeds(ctx context.Context, req *dto.ListPigBreedRequest) (*dto.ListPigBreedResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigBreeds")

	opts := repository.PigBreedListOptions{
		Name:    req.Name,
		OrderBy: req.OrderBy,
	}
	breeds, total, err := s.recipeSvc.ListPigBreeds(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, fmt.Errorf("获取猪品种列表失败: %w", err)
	}

	return dto.ConvertPigBreedListToDTO(breeds, total, req.Page, req.PageSize), nil
}
