package postgres

import (
	"context"
	"time"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
)

type EnterpriseDeviceAuthorizationStore struct {
	db    *gorm.DB
	redis *redis.Client
}

func NewEnterpriseDeviceAuthorizationStore(db *gorm.DB, redis *redis.Client) *EnterpriseDeviceAuthorizationStore {
	return &EnterpriseDeviceAuthorizationStore{
		db:    db,
		redis: redis,
	}
}

func (s *EnterpriseDeviceAuthorizationStore) Create(ctx context.Context, auth *model.EnterpriseDeviceAuthorization) error {
	return s.db.WithContext(ctx).Create(auth).Error
}

func (s *EnterpriseDeviceAuthorizationStore) BatchCreate(ctx context.Context, auths []*model.EnterpriseDeviceAuthorization) error {
	if len(auths) == 0 {
		return nil
	}
	batchSize := 100
	for i := 0; i < len(auths); i += batchSize {
		end := i + batchSize
		if end > len(auths) {
			end = len(auths)
		}
		batch := auths[i:end]
		if err := s.db.WithContext(ctx).Create(batch).Error; err != nil {
			return err
		}
	}
	return nil
}

func (s *EnterpriseDeviceAuthorizationStore) GetByID(ctx context.Context, id uint) (*model.EnterpriseDeviceAuthorization, error) {
	var auth model.EnterpriseDeviceAuthorization
	query := s.db.WithContext(ctx).Where("id = ?", id)
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)
	err := query.First(&auth).Error
	if err != nil {
		return nil, err
	}
	return &auth, nil
}

func (s *EnterpriseDeviceAuthorizationStore) GetByDeviceID(ctx context.Context, deviceID uint) (*model.EnterpriseDeviceAuthorization, error) {
	var auth model.EnterpriseDeviceAuthorization
	query := s.db.WithContext(ctx).
		Where("device_id = ? AND revoked_at IS NULL", deviceID)
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)
	err := query.First(&auth).Error
	if err != nil {
		return nil, err
	}
	return &auth, nil
}

func (s *EnterpriseDeviceAuthorizationStore) GetByEnterpriseID(ctx context.Context, enterpriseID uint, includeRevoked bool) ([]*model.EnterpriseDeviceAuthorization, error) {
	var auths []*model.EnterpriseDeviceAuthorization
	query := s.db.WithContext(ctx).Where("enterprise_id = ?", enterpriseID)
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)
	if !includeRevoked {
		query = query.Where("revoked_at IS NULL")
	}
	err := query.Find(&auths).Error
	return auths, err
}

type DeviceAuthListOptions struct {
	EnterpriseID   *uint
	DeviceIDs      []uint
	AuthorizerID   *uint
	IncludeRevoked bool
	Page           int
	PageSize       int
}

func (s *EnterpriseDeviceAuthorizationStore) ListByEnterprise(ctx context.Context, opts DeviceAuthListOptions) ([]*model.EnterpriseDeviceAuthorization, int64, error) {
	var auths []*model.EnterpriseDeviceAuthorization
	var total int64

	query := s.db.WithContext(ctx).Model(&model.EnterpriseDeviceAuthorization{})
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)

	if opts.EnterpriseID != nil {
		query = query.Where("enterprise_id = ?", *opts.EnterpriseID)
	}

	if len(opts.DeviceIDs) > 0 {
		query = query.Where("device_id IN ?", opts.DeviceIDs)
	}

	if opts.AuthorizerID != nil {
		query = query.Where("authorized_by = ?", *opts.AuthorizerID)
	}

	if !opts.IncludeRevoked {
		query = query.Where("revoked_at IS NULL")
	}

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

	if opts.Page > 0 && opts.PageSize > 0 {
		offset := (opts.Page - 1) * opts.PageSize
		query = query.Offset(offset).Limit(opts.PageSize)
	}

	err := query.Order("authorized_at DESC").Find(&auths).Error
	return auths, total, err
}

func (s *EnterpriseDeviceAuthorizationStore) RevokeByIDs(ctx context.Context, ids []uint, revokedBy uint) error {
	now := time.Now()
	return s.db.WithContext(ctx).
		Model(&model.EnterpriseDeviceAuthorization{}).
		Where("id IN ? AND revoked_at IS NULL", ids).
		Updates(map[string]interface{}{
			"revoked_by": revokedBy,
			"revoked_at": now,
		}).Error
}

func (s *EnterpriseDeviceAuthorizationStore) GetActiveAuthsByDeviceIDs(ctx context.Context, enterpriseID uint, deviceIDs []uint) (map[uint]bool, error) {
	if len(deviceIDs) == 0 {
		return make(map[uint]bool), nil
	}

	var auths []model.EnterpriseDeviceAuthorization
	query := s.db.WithContext(ctx).
		Select("device_id").
		Where("enterprise_id = ? AND device_id IN ? AND revoked_at IS NULL", enterpriseID, deviceIDs)
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)
	err := query.Find(&auths).Error

	if err != nil {
		return nil, err
	}

	result := make(map[uint]bool, len(auths))
	for _, auth := range auths {
		result[auth.DeviceID] = true
	}
	return result, nil
}

// GetActiveAuthEnterpriseByDeviceIDs 获取设备ID列表的有效授权企业映射（deviceID -> enterpriseID）
func (s *EnterpriseDeviceAuthorizationStore) GetActiveAuthEnterpriseByDeviceIDs(ctx context.Context, deviceIDs []uint) (map[uint]uint, error) {
	if len(deviceIDs) == 0 {
		return make(map[uint]uint), nil
	}

	var auths []model.EnterpriseDeviceAuthorization
	query := s.db.WithContext(ctx).
		Select("device_id, enterprise_id").
		Where("device_id IN ? AND revoked_at IS NULL", deviceIDs)
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)
	if err := query.Find(&auths).Error; err != nil {
		return nil, err
	}

	result := make(map[uint]uint, len(auths))
	for _, auth := range auths {
		result[auth.DeviceID] = auth.EnterpriseID
	}
	return result, nil
}

func (s *EnterpriseDeviceAuthorizationStore) ListDeviceIDsByEnterprise(ctx context.Context, enterpriseID uint) ([]uint, error) {
	var deviceIDs []uint
	query := s.db.WithContext(ctx).
		Model(&model.EnterpriseDeviceAuthorization{}).
		Where("enterprise_id = ? AND revoked_at IS NULL", enterpriseID)
	// 应用企业数据权限过滤
	query = middleware.ApplyEnterpriseFilter(ctx, query)
	err := query.Pluck("device_id", &deviceIDs).Error
	return deviceIDs, err
}
