package taskboard

import (
	"crypto/rand"
	"fmt"
)

const taskIDAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789"

func newTaskID() (string, error) {
	return newTaskScopedID("tsk")
}

func newTaskBoardID() (string, error) {
	return newTaskScopedID("tbd")
}

func newTaskChecklistItemID() (string, error) {
	return newTaskScopedID("tci")
}

func newTaskDiscussionEntryID() (string, error) {
	return newTaskScopedID("tds")
}

func newTaskDiscussionMentionID() (string, error) {
	return newTaskScopedID("tdm")
}

func newTaskReviewRequestID() (string, error) {
	return newTaskScopedID("trv")
}

func newTaskEventID() (string, error) {
	return newTaskScopedID("tev")
}

func newTaskCollaboratorID() (string, error) {
	return newTaskScopedID("tcl")
}

func newTaskScopeExecutionID() (string, error) {
	return newTaskScopedID("tse")
}

func newTaskFieldOptionID() (string, error) {
	return newTaskScopedID("tfo")
}

func newTaskFieldOptionAliasID() (string, error) {
	return newTaskScopedID("tfa")
}

func newTaskBoardSavedViewID() (string, error) {
	return newTaskScopedID("tbv")
}

func newTaskScopedID(prefix string) (string, error) {
	suffix, err := randomString(20, taskIDAlphabet)
	if err != nil {
		return "", err
	}
	return prefix + "_" + suffix, nil
}

func randomString(length int, alphabet string) (string, error) {
	if length <= 0 {
		return "", fmt.Errorf("length must be positive")
	}
	if len(alphabet) == 0 {
		return "", fmt.Errorf("alphabet is required")
	}

	bytes := make([]byte, length)
	raw := make([]byte, length)
	if _, err := rand.Read(raw); err != nil {
		return "", fmt.Errorf("read random bytes: %w", err)
	}
	for index := range bytes {
		bytes[index] = alphabet[int(raw[index])%len(alphabet)]
	}
	return string(bytes), nil
}
