package service

import (
	"context"

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

// MonitorService 定义了监控相关的业务逻辑服务接口
type MonitorService interface {
	ListSensorData(ctx context.Context, req *dto.ListSensorDataRequest) (*dto.ListSensorDataResponse, error)
	ListDeviceCommandLogs(ctx context.Context, req *dto.ListDeviceCommandLogRequest) (*dto.ListDeviceCommandLogResponse, error)
	ListPlanExecutionLogs(ctx context.Context, req *dto.ListPlanExecutionLogRequest) (*dto.ListPlanExecutionLogResponse, error)
	ListTaskExecutionLogs(ctx context.Context, req *dto.ListTaskExecutionLogRequest) (*dto.ListTaskExecutionLogResponse, error)
	ListPendingCollections(ctx context.Context, req *dto.ListPendingCollectionRequest) (*dto.ListPendingCollectionResponse, error)
	ListUserActionLogs(ctx context.Context, req *dto.ListUserActionLogRequest) (*dto.ListUserActionLogResponse, error)
	ListMedicationLogs(ctx context.Context, req *dto.ListMedicationLogRequest) (*dto.ListMedicationLogResponse, error)
	ListPigBatchLogs(ctx context.Context, req *dto.ListPigBatchLogRequest) (*dto.ListPigBatchLogResponse, error)
	ListWeighingBatches(ctx context.Context, req *dto.ListWeighingBatchRequest) (*dto.ListWeighingBatchResponse, error)
	ListWeighingRecords(ctx context.Context, req *dto.ListWeighingRecordRequest) (*dto.ListWeighingRecordResponse, error)
	ListPigTransferLogs(ctx context.Context, req *dto.ListPigTransferLogRequest) (*dto.ListPigTransferLogResponse, error)
	ListPigSickLogs(ctx context.Context, req *dto.ListPigSickLogRequest) (*dto.ListPigSickLogResponse, error)
	ListPigPurchases(ctx context.Context, req *dto.ListPigPurchaseRequest) (*dto.ListPigPurchaseResponse, error)
	ListPigSales(ctx context.Context, req *dto.ListPigSaleRequest) (*dto.ListPigSaleResponse, error)
	ListNotifications(ctx context.Context, req *dto.ListNotificationRequest) (*dto.ListNotificationResponse, error)
}

// monitorService 是 MonitorService 接口的具体实现
type monitorService struct {
	ctx                   context.Context
	sensorDataRepo        repository.SensorDataRepository
	deviceCommandLogRepo  repository.DeviceCommandLogRepository
	executionLogRepo      repository.ExecutionLogRepository
	planRepository        repository.PlanRepository
	pendingCollectionRepo repository.PendingCollectionRepository
	userActionLogRepo     repository.UserActionLogRepository
	medicationRepo        repository.MedicationLogRepository
	pigBatchRepo          repository.PigBatchRepository
	pigBatchLogRepo       repository.PigBatchLogRepository
	pigTransferLogRepo    repository.PigTransferLogRepository
	pigSickLogRepo        repository.PigSickLogRepository
	pigTradeRepo          repository.PigTradeRepository
	notificationRepo      repository.NotificationRepository
}

// NewMonitorService 创建一个新的 MonitorService 实例
func NewMonitorService(
	ctx context.Context,
	sensorDataRepo repository.SensorDataRepository,
	deviceCommandLogRepo repository.DeviceCommandLogRepository,
	executionLogRepo repository.ExecutionLogRepository,
	planRepository repository.PlanRepository,
	pendingCollectionRepo repository.PendingCollectionRepository,
	userActionLogRepo repository.UserActionLogRepository,
	medicationRepo repository.MedicationLogRepository,
	pigBatchRepo repository.PigBatchRepository,
	pigBatchLogRepo repository.PigBatchLogRepository,
	pigTransferLogRepo repository.PigTransferLogRepository,
	pigSickLogRepo repository.PigSickLogRepository,
	pigTradeRepo repository.PigTradeRepository,
	notificationRepo repository.NotificationRepository,
) MonitorService {
	return &monitorService{
		ctx:                   ctx,
		sensorDataRepo:        sensorDataRepo,
		deviceCommandLogRepo:  deviceCommandLogRepo,
		executionLogRepo:      executionLogRepo,
		planRepository:        planRepository,
		pendingCollectionRepo: pendingCollectionRepo,
		userActionLogRepo:     userActionLogRepo,
		medicationRepo:        medicationRepo,
		pigBatchRepo:          pigBatchRepo,
		pigBatchLogRepo:       pigBatchLogRepo,
		pigTransferLogRepo:    pigTransferLogRepo,
		pigSickLogRepo:        pigSickLogRepo,
		pigTradeRepo:          pigTradeRepo,
		notificationRepo:      notificationRepo,
	}
}

// ListSensorData 负责处理查询传感器数据列表的业务逻辑
func (s *monitorService) ListSensorData(ctx context.Context, req *dto.ListSensorDataRequest) (*dto.ListSensorDataResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListSensorData")
	opts := repository.SensorDataListOptions{
		DeviceID:  req.DeviceID,
		OrderBy:   req.OrderBy,
		StartTime: req.StartTime,
		EndTime:   req.EndTime,
	}
	if req.SensorType != nil {
		sensorType := models.SensorType(*req.SensorType)
		opts.SensorType = &sensorType
	}

	data, total, err := s.sensorDataRepo.List(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListSensorDataResponse(data, total, req.Page, req.PageSize), nil
}

// ListDeviceCommandLogs 负责处理查询设备命令日志列表的业务逻辑
func (s *monitorService) ListDeviceCommandLogs(ctx context.Context, req *dto.ListDeviceCommandLogRequest) (*dto.ListDeviceCommandLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListDeviceCommandLogs")
	opts := repository.DeviceCommandLogListOptions{
		DeviceID:        req.DeviceID,
		ReceivedSuccess: req.ReceivedSuccess,
		OrderBy:         req.OrderBy,
		StartTime:       req.StartTime,
		EndTime:         req.EndTime,
	}

	data, total, err := s.deviceCommandLogRepo.List(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListDeviceCommandLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListPlanExecutionLogs 负责处理查询计划执行日志列表的业务逻辑
func (s *monitorService) ListPlanExecutionLogs(ctx context.Context, req *dto.ListPlanExecutionLogRequest) (*dto.ListPlanExecutionLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPlanExecutionLogs")
	opts := repository.PlanExecutionLogListOptions{
		PlanID:    req.PlanID,
		OrderBy:   req.OrderBy,
		StartTime: req.StartTime,
		EndTime:   req.EndTime,
	}
	if req.Status != nil {
		status := models.ExecutionStatus(*req.Status)
		opts.Status = &status
	}

	planLogs, total, err := s.executionLogRepo.ListPlanExecutionLogs(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	planIds := make([]uint32, 0, len(planLogs))
	for _, datum := range planLogs {
		has := false
		for _, id := range planIds {
			if id == datum.PlanID {
				has = true
				break
			}
		}
		if !has {
			planIds = append(planIds, datum.PlanID)
		}
	}
	plans, err := s.planRepository.GetPlansByIDs(serviceCtx, planIds)
	if err != nil {
		return nil, err
	}
	return dto.NewListPlanExecutionLogResponse(planLogs, plans, total, req.Page, req.PageSize), nil
}

// ListTaskExecutionLogs 负责处理查询任务执行日志列表的业务逻辑
func (s *monitorService) ListTaskExecutionLogs(ctx context.Context, req *dto.ListTaskExecutionLogRequest) (*dto.ListTaskExecutionLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListTaskExecutionLogs")
	opts := repository.TaskExecutionLogListOptions{
		PlanExecutionLogID: req.PlanExecutionLogID,
		TaskID:             req.TaskID,
		OrderBy:            req.OrderBy,
		StartTime:          req.StartTime,
		EndTime:            req.EndTime,
	}
	if req.Status != nil {
		status := models.ExecutionStatus(*req.Status)
		opts.Status = &status
	}

	data, total, err := s.executionLogRepo.ListTaskExecutionLogs(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListTaskExecutionLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListPendingCollections 负责处理查询待采集请求列表的业务逻辑
func (s *monitorService) ListPendingCollections(ctx context.Context, req *dto.ListPendingCollectionRequest) (*dto.ListPendingCollectionResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPendingCollections")
	opts := repository.PendingCollectionListOptions{
		DeviceID:  req.DeviceID,
		OrderBy:   req.OrderBy,
		StartTime: req.StartTime,
		EndTime:   req.EndTime,
	}
	if req.Status != nil {
		status := models.PendingCollectionStatus(*req.Status)
		opts.Status = &status
	}

	data, total, err := s.pendingCollectionRepo.List(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListPendingCollectionResponse(data, total, req.Page, req.PageSize), nil
}

// ListUserActionLogs 负责处理查询用户操作日志列表的业务逻辑
func (s *monitorService) ListUserActionLogs(ctx context.Context, req *dto.ListUserActionLogRequest) (*dto.ListUserActionLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListUserActionLogs")
	opts := repository.UserActionLogListOptions{
		UserID:     req.UserID,
		Username:   req.Username,
		ActionType: req.ActionType,
		OrderBy:    req.OrderBy,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
	}
	if req.Status != nil {
		status := models.AuditStatus(*req.Status)
		opts.Status = &status
	}

	data, total, err := s.userActionLogRepo.List(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListUserActionLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListMedicationLogs 负责处理查询用药记录列表的业务逻辑
func (s *monitorService) ListMedicationLogs(ctx context.Context, req *dto.ListMedicationLogRequest) (*dto.ListMedicationLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListMedicationLogs")
	opts := repository.MedicationLogListOptions{
		PigBatchID:   req.PigBatchID,
		MedicationID: req.MedicationID,
		OperatorID:   req.OperatorID,
		OrderBy:      req.OrderBy,
		StartTime:    req.StartTime,
		EndTime:      req.EndTime,
	}
	if req.Reason != nil {
		reason := models.MedicationReasonType(*req.Reason)
		opts.Reason = &reason
	}

	data, total, err := s.medicationRepo.ListMedicationLogs(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListMedicationLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListPigBatchLogs 负责处理查询猪批次日志列表的业务逻辑
func (s *monitorService) ListPigBatchLogs(ctx context.Context, req *dto.ListPigBatchLogRequest) (*dto.ListPigBatchLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigBatchLogs")
	opts := repository.PigBatchLogListOptions{
		PigBatchID: req.PigBatchID,
		OperatorID: req.OperatorID,
		OrderBy:    req.OrderBy,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
	}
	if req.ChangeType != nil {
		changeType := models.LogChangeType(*req.ChangeType)
		opts.ChangeType = &changeType
	}

	data, total, err := s.pigBatchLogRepo.List(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListPigBatchLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListWeighingBatches 负责处理查询批次称重记录列表的业务逻辑
func (s *monitorService) ListWeighingBatches(ctx context.Context, req *dto.ListWeighingBatchRequest) (*dto.ListWeighingBatchResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListWeighingBatches")
	opts := repository.WeighingBatchListOptions{
		PigBatchID: req.PigBatchID,
		OrderBy:    req.OrderBy,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
	}

	data, total, err := s.pigBatchRepo.ListWeighingBatches(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListWeighingBatchResponse(data, total, req.Page, req.PageSize), nil
}

// ListWeighingRecords 负责处理查询单次称重记录列表的业务逻辑
func (s *monitorService) ListWeighingRecords(ctx context.Context, req *dto.ListWeighingRecordRequest) (*dto.ListWeighingRecordResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListWeighingRecords")
	opts := repository.WeighingRecordListOptions{
		WeighingBatchID: req.WeighingBatchID,
		PenID:           req.PenID,
		OperatorID:      req.OperatorID,
		OrderBy:         req.OrderBy,
		StartTime:       req.StartTime,
		EndTime:         req.EndTime,
	}

	data, total, err := s.pigBatchRepo.ListWeighingRecords(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListWeighingRecordResponse(data, total, req.Page, req.PageSize), nil
}

// ListPigTransferLogs 负责处理查询猪只迁移日志列表的业务逻辑
func (s *monitorService) ListPigTransferLogs(ctx context.Context, req *dto.ListPigTransferLogRequest) (*dto.ListPigTransferLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigTransferLogs")
	opts := repository.PigTransferLogListOptions{
		PigBatchID:    req.PigBatchID,
		PenID:         req.PenID,
		OperatorID:    req.OperatorID,
		CorrelationID: req.CorrelationID,
		OrderBy:       req.OrderBy,
		StartTime:     req.StartTime,
		EndTime:       req.EndTime,
	}
	if req.TransferType != nil {
		transferType := models.PigTransferType(*req.TransferType)
		opts.TransferType = &transferType
	}

	data, total, err := s.pigTransferLogRepo.ListPigTransferLogs(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListPigTransferLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListPigSickLogs 负责处理查询病猪日志列表的业务逻辑
func (s *monitorService) ListPigSickLogs(ctx context.Context, req *dto.ListPigSickLogRequest) (*dto.ListPigSickLogResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigSickLogs")
	opts := repository.PigSickLogListOptions{
		PigBatchID: req.PigBatchID,
		PenID:      req.PenID,
		OperatorID: req.OperatorID,
		OrderBy:    req.OrderBy,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
	}
	if req.Reason != nil {
		reason := models.PigBatchSickPigReasonType(*req.Reason)
		opts.Reason = &reason
	}
	if req.TreatmentLocation != nil {
		treatmentLocation := models.PigBatchSickPigTreatmentLocation(*req.TreatmentLocation)
		opts.TreatmentLocation = &treatmentLocation
	}

	data, total, err := s.pigSickLogRepo.ListPigSickLogs(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListPigSickLogResponse(data, total, req.Page, req.PageSize), nil
}

// ListPigPurchases 负责处理查询猪只采购记录列表的业务逻辑
func (s *monitorService) ListPigPurchases(ctx context.Context, req *dto.ListPigPurchaseRequest) (*dto.ListPigPurchaseResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigPurchases")
	opts := repository.PigPurchaseListOptions{
		PigBatchID: req.PigBatchID,
		Supplier:   req.Supplier,
		OperatorID: req.OperatorID,
		OrderBy:    req.OrderBy,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
	}

	data, total, err := s.pigTradeRepo.ListPigPurchases(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListPigPurchaseResponse(data, total, req.Page, req.PageSize), nil
}

// ListPigSales 负责处理查询猪只销售记录列表的业务逻辑
func (s *monitorService) ListPigSales(ctx context.Context, req *dto.ListPigSaleRequest) (*dto.ListPigSaleResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListPigSales")
	opts := repository.PigSaleListOptions{
		PigBatchID: req.PigBatchID,
		Buyer:      req.Buyer,
		OperatorID: req.OperatorID,
		OrderBy:    req.OrderBy,
		StartTime:  req.StartTime,
		EndTime:    req.EndTime,
	}

	data, total, err := s.pigTradeRepo.ListPigSales(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListPigSaleResponse(data, total, req.Page, req.PageSize), nil
}

// ListNotifications 负责处理查询通知列表的业务逻辑
func (s *monitorService) ListNotifications(ctx context.Context, req *dto.ListNotificationRequest) (*dto.ListNotificationResponse, error) {
	serviceCtx := logs.AddFuncName(ctx, s.ctx, "ListNotifications")
	opts := repository.NotificationListOptions{
		UserID:       req.UserID,
		NotifierType: req.NotifierType,
		Level:        req.Level,
		StartTime:    req.StartTime,
		EndTime:      req.EndTime,
		OrderBy:      req.OrderBy,
		Status:       req.Status,
	}

	data, total, err := s.notificationRepo.List(serviceCtx, opts, req.Page, req.PageSize)
	if err != nil {
		return nil, err
	}

	return dto.NewListNotificationResponse(data, total, req.Page, req.PageSize), nil
}
