package repository

import (
	"context"
	"time"

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

	"gorm.io/gorm"
)

// PigBatchRepository 定义了与猪批次相关的数据库操作接口
type PigBatchRepository interface {
	CreatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, error)
	CreatePigBatchTx(ctx context.Context, tx *gorm.DB, batch *models.PigBatch) (*models.PigBatch, error)
	GetPigBatchByID(ctx context.Context, id uint32) (*models.PigBatch, error)
	GetPigBatchByIDTx(ctx context.Context, tx *gorm.DB, id uint32) (*models.PigBatch, error)
	// UpdatePigBatch 更新一个猪批次，返回更新后的批次、受影响的行数和错误
	UpdatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, int64, error)
	// DeletePigBatch 根据ID删除一个猪批次，返回受影响的行数和错误
	DeletePigBatch(ctx context.Context, id uint32) (int64, error)
	DeletePigBatchTx(ctx context.Context, tx *gorm.DB, id uint32) (int64, error)
	ListPigBatches(ctx context.Context, isActive *bool) ([]*models.PigBatch, error)

	// ListWeighingBatches 支持分页和过滤的批次称重列表查询
	ListWeighingBatches(ctx context.Context, opts WeighingBatchListOptions, page, pageSize int) ([]models.WeighingBatch, int64, error)

	// ListWeighingRecords 支持分页和过滤的单次称重记录列表查询
	ListWeighingRecords(ctx context.Context, opts WeighingRecordListOptions, page, pageSize int) ([]models.WeighingRecord, int64, error)
}

// WeighingBatchListOptions 定义了查询批次称重记录时的可选参数
type WeighingBatchListOptions struct {
	PigBatchID *uint32
	StartTime  *time.Time // 基于 weighing_time 字段
	EndTime    *time.Time // 基于 weighing_time 字段
	OrderBy    string     // 例如 "weighing_time asc"
}

// WeighingRecordListOptions 定义了查询单次称重记录时的可选参数
type WeighingRecordListOptions struct {
	WeighingBatchID *uint32
	PenID           *uint32
	OperatorID      *uint32
	StartTime       *time.Time // 基于 weighing_time 字段
	EndTime         *time.Time // 基于 weighing_time 字段
	OrderBy         string     // 例如 "weighing_time asc"
}

// gormPigBatchRepository 是 PigBatchRepository 的 GORM 实现
type gormPigBatchRepository struct {
	ctx context.Context
	db  *gorm.DB
}

// NewGormPigBatchRepository 创建一个新的 PigBatchRepository GORM 实现实例
func NewGormPigBatchRepository(ctx context.Context, db *gorm.DB) PigBatchRepository {
	return &gormPigBatchRepository{ctx: ctx, db: db}
}

// CreatePigBatch 创建一个新的猪批次
func (r *gormPigBatchRepository) CreatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "CreatePigBatch")
	return r.CreatePigBatchTx(repoCtx, r.db, batch)
}

// CreatePigBatchTx 在指定的事务中，创建一个新的猪批次
func (r *gormPigBatchRepository) CreatePigBatchTx(ctx context.Context, tx *gorm.DB, batch *models.PigBatch) (*models.PigBatch, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "CreatePigBatchTx")
	if err := tx.WithContext(repoCtx).Create(batch).Error; err != nil {
		return nil, err
	}
	return batch, nil
}

// GetPigBatchByID 根据ID获取单个猪批次
func (r *gormPigBatchRepository) GetPigBatchByID(ctx context.Context, id uint32) (*models.PigBatch, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "GetPigBatchByID")
	return r.GetPigBatchByIDTx(repoCtx, r.db, id)
}

// UpdatePigBatch 更新一个猪批次
func (r *gormPigBatchRepository) UpdatePigBatch(ctx context.Context, batch *models.PigBatch) (*models.PigBatch, int64, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "UpdatePigBatch")
	result := r.db.WithContext(repoCtx).Model(&models.PigBatch{}).Where("id = ?", batch.ID).Updates(batch)
	if result.Error != nil {
		return nil, 0, result.Error
	}
	// 返回更新后的批次、受影响的行数和错误
	return batch, result.RowsAffected, nil
}

// DeletePigBatch 根据ID删除一个猪批次 (GORM 会执行软删除)
func (r *gormPigBatchRepository) DeletePigBatch(ctx context.Context, id uint32) (int64, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "DeletePigBatch")
	return r.DeletePigBatchTx(repoCtx, r.db, id)
}

func (r *gormPigBatchRepository) DeletePigBatchTx(ctx context.Context, tx *gorm.DB, id uint32) (int64, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "DeletePigBatchTx")
	result := tx.WithContext(repoCtx).Delete(&models.PigBatch{}, id)
	if result.Error != nil {
		return 0, result.Error
	}
	// 返回受影响的行数和错误
	return result.RowsAffected, nil
}

// ListPigBatches 批量查询猪批次，支持根据 IsActive 筛选
func (r *gormPigBatchRepository) ListPigBatches(ctx context.Context, isActive *bool) ([]*models.PigBatch, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "ListPigBatches")
	var batches []*models.PigBatch
	query := r.db.WithContext(repoCtx).Model(&models.PigBatch{})

	if isActive != nil {
		if *isActive {
			// 查询活跃的批次：状态不是已出售或已归档
			query = query.Where("status NOT IN (?) ", []models.PigBatchStatus{models.BatchStatusSold, models.BatchStatusArchived})
		} else {
			// 查询非活跃的批次：状态是已出售或已归档
			query = query.Where("status IN (?) ", []models.PigBatchStatus{models.BatchStatusSold, models.BatchStatusArchived})
		}
	}

	if err := query.Find(&batches).Error; err != nil {
		return nil, err
	}
	return batches, nil
}

// GetPigBatchByIDTx 在指定的事务中，通过ID获取单个猪批次
func (r *gormPigBatchRepository) GetPigBatchByIDTx(ctx context.Context, tx *gorm.DB, id uint32) (*models.PigBatch, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "GetPigBatchByIDTx")
	var batch models.PigBatch
	if err := tx.WithContext(repoCtx).First(&batch, id).Error; err != nil {
		return nil, err
	}
	return &batch, nil
}

// ListWeighingBatches 实现了分页和过滤查询批次称重记录的功能
func (r *gormPigBatchRepository) ListWeighingBatches(ctx context.Context, opts WeighingBatchListOptions, page, pageSize int) ([]models.WeighingBatch, int64, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "ListWeighingBatches")
	if page <= 0 || pageSize <= 0 {
		return nil, 0, ErrInvalidPagination
	}

	var results []models.WeighingBatch
	var total int64

	query := r.db.WithContext(repoCtx).Model(&models.WeighingBatch{})

	if opts.PigBatchID != nil {
		query = query.Where("pig_batch_id = ?", *opts.PigBatchID)
	}
	if opts.StartTime != nil {
		query = query.Where("weighing_time >= ?", *opts.StartTime)
	}
	if opts.EndTime != nil {
		query = query.Where("weighing_time <= ?", *opts.EndTime)
	}

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	orderBy := "weighing_time DESC"
	if opts.OrderBy != "" {
		orderBy = opts.OrderBy
	}
	query = query.Order(orderBy)

	offset := (page - 1) * pageSize
	err := query.Limit(pageSize).Offset(offset).Find(&results).Error

	return results, total, err
}

// ListWeighingRecords 实现了分页和过滤查询单次称重记录的功能
func (r *gormPigBatchRepository) ListWeighingRecords(ctx context.Context, opts WeighingRecordListOptions, page, pageSize int) ([]models.WeighingRecord, int64, error) {
	repoCtx := logs.AddFuncName(ctx, r.ctx, "ListWeighingRecords")
	if page <= 0 || pageSize <= 0 {
		return nil, 0, ErrInvalidPagination
	}

	var results []models.WeighingRecord
	var total int64

	query := r.db.WithContext(repoCtx).Model(&models.WeighingRecord{})

	if opts.WeighingBatchID != nil {
		query = query.Where("weighing_batch_id = ?", *opts.WeighingBatchID)
	}
	if opts.PenID != nil {
		query = query.Where("pen_id = ?", *opts.PenID)
	}
	if opts.OperatorID != nil {
		query = query.Where("operator_id = ?", *opts.OperatorID)
	}
	if opts.StartTime != nil {
		query = query.Where("weighing_time >= ?", *opts.StartTime)
	}
	if opts.EndTime != nil {
		query = query.Where("weighing_time <= ?", *opts.EndTime)
	}

	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	orderBy := "weighing_time DESC"
	if opts.OrderBy != "" {
		orderBy = opts.OrderBy
	}
	query = query.Order(orderBy)

	offset := (page - 1) * pageSize
	err := query.Limit(pageSize).Offset(offset).Find(&results).Error

	return results, total, err
}
