// Package postgres 提供基于 PostgreSQL 的数据访问层实现
// 包含所有模型的 Store 接口实现，使用 GORM 进行数据库操作
package postgres

import (
	"context"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"

	"github.com/break/junhong_cmp_fiber/internal/model"
)

// AccountRoleStore 账号-角色关联数据访问层
type AccountRoleStore struct {
	db          *gorm.DB
	redisClient *redis.Client
}

// NewAccountRoleStore 创建账号-角色关联 Store
func NewAccountRoleStore(db *gorm.DB, redisClient *redis.Client) *AccountRoleStore {
	return &AccountRoleStore{
		db:          db,
		redisClient: redisClient,
	}
}

// Create 创建账号-角色关联
func (s *AccountRoleStore) Create(ctx context.Context, ar *model.AccountRole) error {
	if err := s.db.WithContext(ctx).Create(ar).Error; err != nil {
		return err
	}
	s.clearUserPermissionCache(ctx, ar.AccountID)
	return nil
}

// BatchCreate 批量创建账号-角色关联
func (s *AccountRoleStore) BatchCreate(ctx context.Context, ars []*model.AccountRole) error {
	if err := s.db.WithContext(ctx).Create(&ars).Error; err != nil {
		return err
	}
	for _, ar := range ars {
		s.clearUserPermissionCache(ctx, ar.AccountID)
	}
	return nil
}

// Delete 软删除账号-角色关联
func (s *AccountRoleStore) Delete(ctx context.Context, accountID, roleID uint) error {
	if err := s.db.WithContext(ctx).
		Where("account_id = ? AND role_id = ?", accountID, roleID).
		Delete(&model.AccountRole{}).Error; err != nil {
		return err
	}
	s.clearUserPermissionCache(ctx, accountID)
	return nil
}

// DeleteByAccountID 删除账号的所有角色关联
func (s *AccountRoleStore) DeleteByAccountID(ctx context.Context, accountID uint) error {
	if err := s.db.WithContext(ctx).
		Where("account_id = ?", accountID).
		Delete(&model.AccountRole{}).Error; err != nil {
		return err
	}
	s.clearUserPermissionCache(ctx, accountID)
	return nil
}

func (s *AccountRoleStore) clearUserPermissionCache(ctx context.Context, userID uint) {
	if s.redisClient != nil {
		key := constants.RedisUserPermissionsKey(userID)
		s.redisClient.Del(ctx, key)
	}
}

// GetByAccountID 获取账号的所有角色关联
func (s *AccountRoleStore) GetByAccountID(ctx context.Context, accountID uint) ([]*model.AccountRole, error) {
	var ars []*model.AccountRole
	if err := s.db.WithContext(ctx).
		Where("account_id = ?", accountID).
		Find(&ars).Error; err != nil {
		return nil, err
	}
	return ars, nil
}

// GetRoleIDsByAccountID 获取账号的所有角色 ID
func (s *AccountRoleStore) GetRoleIDsByAccountID(ctx context.Context, accountID uint) ([]uint, error) {
	var roleIDs []uint
	if err := s.db.WithContext(ctx).
		Model(&model.AccountRole{}).
		Where("account_id = ?", accountID).
		Pluck("role_id", &roleIDs).Error; err != nil {
		return nil, err
	}
	return roleIDs, nil
}

// Exists 检查账号-角色关联是否存在
func (s *AccountRoleStore) Exists(ctx context.Context, accountID, roleID uint) (bool, error) {
	var count int64
	if err := s.db.WithContext(ctx).
		Model(&model.AccountRole{}).
		Where("account_id = ? AND role_id = ?", accountID, roleID).
		Count(&count).Error; err != nil {
		return false, err
	}
	return count > 0, nil
}

// CountByAccountID 统计账号的角色数量
func (s *AccountRoleStore) CountByAccountID(ctx context.Context, accountID uint) (int64, error) {
	var count int64
	if err := s.db.WithContext(ctx).
		Model(&model.AccountRole{}).
		Where("account_id = ?", accountID).
		Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}

// CountByRoleID 统计持有指定角色的账号数量
func (s *AccountRoleStore) CountByRoleID(ctx context.Context, roleID uint) (int64, error) {
	var count int64
	if err := s.db.WithContext(ctx).
		Model(&model.AccountRole{}).
		Where("role_id = ?", roleID).
		Count(&count).Error; err != nil {
		return 0, err
	}
	return count, nil
}
