package usecase

import (
	"context"
	"errors"
	"time"

	"lune/talentscale/infra/cache"
	"lune/talentscale/internal/domain"

	"github.com/google/uuid"
)

type roleUsecase struct {
	repo domain.RoleRepository
}

func NewRoleUsecase(repo domain.RoleRepository) domain.RoleUsecase {
	return &roleUsecase{repo: repo}
}

func (u *roleUsecase) CreateRole(ctx context.Context, role *domain.Role) error {
	role.ID = uuid.New()
	role.CreatedAt = time.Now()
	role.UpdatedAt = time.Now()
	return u.repo.Create(ctx, role)
}

func (u *roleUsecase) GetRoleByID(ctx context.Context, id uuid.UUID, companyID *uuid.UUID) (*domain.Role, error) {
	return u.repo.GetByID(ctx, id, companyID)
}

func (u *roleUsecase) ListRoles(ctx context.Context, companyID *uuid.UUID, limit, offset int) ([]domain.Role, error) {
	if limit <= 0 { limit = 10 }
	return u.repo.List(ctx, companyID, limit, offset)
}

func (u *roleUsecase) UpdateRole(ctx context.Context, id uuid.UUID, companyID *uuid.UUID, role *domain.Role) error {
	existing, err := u.repo.GetByID(ctx, id, companyID)
	if err != nil {
		return errors.New("role not found or access denied")
	}
	existing.Name = role.Name
	existing.Description = role.Description
	return u.repo.Update(ctx, existing)
}

func (u *roleUsecase) DeleteRole(ctx context.Context, id uuid.UUID, companyID *uuid.UUID) error {
	_, err := u.repo.GetByID(ctx, id, companyID)
	if err != nil {
		return errors.New("role not found or access denied")
	}
	return u.repo.Delete(ctx, id, companyID)
}

func (u *roleUsecase) AssignPermission(ctx context.Context, roleID, permissionID uuid.UUID, companyID *uuid.UUID) error {
	_, err := u.repo.GetByID(ctx, roleID, companyID)
	if err != nil {
		return errors.New("role not found or access denied")
	}
	err = u.repo.AssignPermission(ctx, roleID, permissionID)
	if err == nil {
		_ = cache.DeletePattern("user:permissions:*")
	}
	return err
}

func (u *roleUsecase) RemovePermission(ctx context.Context, roleID, permissionID uuid.UUID, companyID *uuid.UUID) error {
	_, err := u.repo.GetByID(ctx, roleID, companyID)
	if err != nil {
		return errors.New("role not found or access denied")
	}
	err = u.repo.RemovePermission(ctx, roleID, permissionID)
	if err == nil {
		_ = cache.DeletePattern("user:permissions:*")
	}
	return err
}

func (u *roleUsecase) UpdateRolePermissions(ctx context.Context, roleID uuid.UUID, permissionIDs []uuid.UUID, companyID *uuid.UUID) error {
	_, err := u.repo.GetByID(ctx, roleID, companyID)
	if err != nil {
		return errors.New("role not found or access denied")
	}
	err = u.repo.SyncPermissions(ctx, roleID, permissionIDs)
	if err == nil {
		_ = cache.DeletePattern("user:permissions:*")
	}
	return err
}

func (u *roleUsecase) GetRolePermissions(ctx context.Context, roleID uuid.UUID, companyID *uuid.UUID) ([]domain.Permission, error) {
	_, err := u.repo.GetByID(ctx, roleID, companyID)
	if err != nil {
		return nil, errors.New("role not found or access denied")
	}
	return u.repo.GetPermissionsByRoleID(ctx, roleID)
}
