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 (
	ErrPigAgeStageInUse    = errors.New("猪年龄阶段正在被猪类型使用，无法删除")
	ErrPigAgeStageNotFound = errors.New("猪年龄阶段不存在")
)

// PigAgeStageService 定义了猪年龄阶段相关的应用服务接口
type PigAgeStageService interface {
	CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error)
	UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error)
	DeletePigAgeStage(ctx context.Context, id uint32) error
	GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error)
	ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error)
}

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

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

// CreatePigAgeStage 创建猪年龄阶段
func (s *pigAgeStageServiceImpl) CreatePigAgeStage(ctx context.Context, req *dto.CreatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "CreatePigAgeStage")

	ageStage := &models.PigAgeStage{
		Name:        req.Name,
		Description: req.Description,
	}

	if err := s.recipeSvc.CreatePigAgeStage(serviceCtx, ageStage); err != nil {
		return nil, fmt.Errorf("创建猪年龄阶段失败: %w", err)
	}
	return dto.ConvertPigAgeStageToDTO(ageStage), nil
}

// UpdatePigAgeStage 更新猪年龄阶段
func (s *pigAgeStageServiceImpl) UpdatePigAgeStage(ctx context.Context, id uint32, req *dto.UpdatePigAgeStageRequest) (*dto.PigAgeStageResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "UpdatePigAgeStage")

	ageStage := &models.PigAgeStage{
		Model:       models.Model{ID: id},
		Name:        req.Name,
		Description: req.Description,
	}

	if err := s.recipeSvc.UpdatePigAgeStage(serviceCtx, ageStage); err != nil {
		if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
			return nil, ErrPigAgeStageNotFound
		}
		return nil, fmt.Errorf("更新猪年龄阶段失败: %w", err)
	}
	return dto.ConvertPigAgeStageToDTO(ageStage), nil
}

// DeletePigAgeStage 删除猪年龄阶段
func (s *pigAgeStageServiceImpl) DeletePigAgeStage(ctx context.Context, id uint32) error {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "DeletePigAgeStage")
	err := s.recipeSvc.DeletePigAgeStage(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
			return ErrPigAgeStageNotFound
		}
		if errors.Is(err, recipe.ErrPigAgeStageInUse) {
			return ErrPigAgeStageInUse
		}
		return fmt.Errorf("删除猪年龄阶段失败: %w", err)
	}
	return nil
}

// GetPigAgeStage 获取单个猪年龄阶段
func (s *pigAgeStageServiceImpl) GetPigAgeStage(ctx context.Context, id uint32) (*dto.PigAgeStageResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "GetPigAgeStage")

	ageStage, err := s.recipeSvc.GetPigAgeStageByID(serviceCtx, id)
	if err != nil {
		if errors.Is(err, recipe.ErrPigAgeStageNotFound) {
			return nil, ErrPigAgeStageNotFound
		}
		return nil, fmt.Errorf("获取猪年龄阶段失败: %w", err)
	}
	return dto.ConvertPigAgeStageToDTO(ageStage), nil
}

// ListPigAgeStages 列出猪年龄阶段
func (s *pigAgeStageServiceImpl) ListPigAgeStages(ctx context.Context, req *dto.ListPigAgeStageRequest) (*dto.ListPigAgeStageResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigAgeStages")

	opts := repository.PigAgeStageListOptions{
		Name:    req.Name,
		OrderBy: req.OrderBy,
	}
	ageStages, total, err := s.recipeSvc.ListPigAgeStages(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, fmt.Errorf("获取猪年龄阶段列表失败: %w", err)
	}

	return dto.ConvertPigAgeStageListToDTO(ageStages, total, req.Page, req.PageSize), nil
}
