package graphql

// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.
// Code generated by github.com/99designs/gqlgen version v0.17.72

import (
	"context"
	"errors"
	"fmt"
	"strconv"
	"tercul/internal/adapters/graphql/model"
	"tercul/internal/app/auth"
	"tercul/internal/app/author"
	"tercul/internal/app/book"
	"tercul/internal/app/bookmark"
	"tercul/internal/app/collection"
	"tercul/internal/app/comment"
	"tercul/internal/app/contribution"
	"tercul/internal/app/like"
	"tercul/internal/app/translation"
	"tercul/internal/app/user"
	"tercul/internal/domain"
	platform_auth "tercul/internal/platform/auth"
	"tercul/internal/platform/log"
	"time"
)

// Register is the resolver for the register field.
func (r *mutationResolver) Register(ctx context.Context, input model.RegisterInput) (*model.AuthPayload, error) {
	// Convert GraphQL input to service input
	registerInput := auth.RegisterInput{
		Username:  input.Username,
		Email:     input.Email,
		Password:  input.Password,
		FirstName: input.FirstName,
		LastName:  input.LastName,
	}

	// Call auth service
	authResponse, err := r.App.Auth.Commands.Register(ctx, registerInput)
	if err != nil {
		return nil, err
	}

	// Convert service response to GraphQL response
	return &model.AuthPayload{
		Token: authResponse.Token,
		User: &model.User{
			ID:          fmt.Sprintf("%d", authResponse.User.ID),
			Username:    authResponse.User.Username,
			Email:       authResponse.User.Email,
			FirstName:   &authResponse.User.FirstName,
			LastName:    &authResponse.User.LastName,
			DisplayName: &authResponse.User.DisplayName,
			Role:        model.UserRole(authResponse.User.Role),
			Verified:    authResponse.User.Verified,
			Active:      authResponse.User.Active,
		},
	}, nil
}

// Login is the resolver for the login field.
func (r *mutationResolver) Login(ctx context.Context, input model.LoginInput) (*model.AuthPayload, error) {
	// Convert GraphQL input to service input
	loginInput := auth.LoginInput{
		Email:    input.Email,
		Password: input.Password,
	}

	// Call auth service
	authResponse, err := r.App.Auth.Commands.Login(ctx, loginInput)
	if err != nil {
		return nil, err
	}

	// Convert service response to GraphQL response
	return &model.AuthPayload{
		Token: authResponse.Token,
		User: &model.User{
			ID:          fmt.Sprintf("%d", authResponse.User.ID),
			Username:    authResponse.User.Username,
			Email:       authResponse.User.Email,
			FirstName:   &authResponse.User.FirstName,
			LastName:    &authResponse.User.LastName,
			DisplayName: &authResponse.User.DisplayName,
			Role:        model.UserRole(authResponse.User.Role),
			Verified:    authResponse.User.Verified,
			Active:      authResponse.User.Active,
		},
	}, nil
}

// CreateWork is the resolver for the createWork field.
func (r *mutationResolver) CreateWork(ctx context.Context, input model.WorkInput) (*model.Work, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}
	// Create domain model
	workModel := &domain.Work{
		Title:             input.Name,
		TranslatableModel: domain.TranslatableModel{Language: input.Language},
	}

	// Call work service
	createdWork, err := r.App.Work.Commands.CreateWork(ctx, workModel)
	if err != nil {
		return nil, err
	}

	if input.Content != nil && *input.Content != "" {
		translationInput := translation.CreateOrUpdateTranslationInput{
			Title:              input.Name,
			Content:            *input.Content,
			Language:           input.Language,
			TranslatableID:     createdWork.ID,
			TranslatableType:   "works",
			IsOriginalLanguage: true,
		}
		_, err := r.App.Translation.Commands.CreateOrUpdateTranslation(ctx, translationInput)
		if err != nil {
			return nil, fmt.Errorf("failed to create initial translation: %w", err)
		}
	}

	// Convert to GraphQL model
	return &model.Work{
		ID:       fmt.Sprintf("%d", createdWork.ID),
		Name:     createdWork.Title,
		Language: createdWork.Language,
		Content:  input.Content,
	}, nil
}

// UpdateWork is the resolver for the updateWork field.
func (r *mutationResolver) UpdateWork(ctx context.Context, id string, input model.WorkInput) (*model.Work, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}

	workID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid work ID", domain.ErrValidation)
	}

	// Create domain model
	workModel := &domain.Work{
		TranslatableModel: domain.TranslatableModel{
			BaseModel: domain.BaseModel{ID: uint(workID)},
			Language:  input.Language,
		},
		Title: input.Name,
	}

	// Call work service
	err = r.App.Work.Commands.UpdateWork(ctx, workModel)
	if err != nil {
		return nil, err
	}

	// Convert to GraphQL model
	return &model.Work{
		ID:       id,
		Name:     workModel.Title,
		Language: workModel.Language,
		Content:  input.Content,
	}, nil
}

// DeleteWork is the resolver for the deleteWork field.
func (r *mutationResolver) DeleteWork(ctx context.Context, id string) (bool, error) {
	workID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("%w: invalid work ID", domain.ErrValidation)
	}

	err = r.App.Work.Commands.DeleteWork(ctx, uint(workID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateTranslation is the resolver for the createTranslation field.
func (r *mutationResolver) CreateTranslation(ctx context.Context, input model.TranslationInput) (*model.Translation, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}

	workID, err := strconv.ParseUint(input.WorkID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid work ID", domain.ErrValidation)
	}

	var content string
	if input.Content != nil {
		content = *input.Content
	}

	createInput := translation.CreateOrUpdateTranslationInput{
		Title:            input.Name,
		Content:          content,
		Language:         input.Language,
		TranslatableID:   uint(workID),
		TranslatableType: "works",
	}
	createdTranslation, err := r.App.Translation.Commands.CreateOrUpdateTranslation(ctx, createInput)
	if err != nil {
		return nil, err
	}

	go func() {
		if err := r.App.Analytics.IncrementWorkTranslationCount(context.Background(), uint(workID)); err != nil {
			log.Error(err, "failed to increment work translation count")
		}
	}()

	return &model.Translation{
		ID:       fmt.Sprintf("%d", createdTranslation.ID),
		Name:     createdTranslation.Title,
		Language: createdTranslation.Language,
		Content:  &createdTranslation.Content,
		WorkID:   input.WorkID,
	}, nil
}

// UpdateTranslation is the resolver for the updateTranslation field.
func (r *mutationResolver) UpdateTranslation(ctx context.Context, id string, input model.TranslationInput) (*model.Translation, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}

	workID, err := strconv.ParseUint(input.WorkID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid work ID", domain.ErrValidation)
	}

	var content string
	if input.Content != nil {
		content = *input.Content
	}

	updateInput := translation.CreateOrUpdateTranslationInput{
		Title:            input.Name,
		Content:          content,
		Language:         input.Language,
		TranslatableID:   uint(workID),
		TranslatableType: "works",
	}
	updatedTranslation, err := r.App.Translation.Commands.CreateOrUpdateTranslation(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.Translation{
		ID:       fmt.Sprintf("%d", updatedTranslation.ID),
		Name:     updatedTranslation.Title,
		Language: updatedTranslation.Language,
		Content:  &updatedTranslation.Content,
		WorkID:   input.WorkID,
	}, nil
}

// DeleteTranslation is the resolver for the deleteTranslation field.
func (r *mutationResolver) DeleteTranslation(ctx context.Context, id string) (bool, error) {
	translationID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("invalid translation ID: %v", err)
	}

	err = r.App.Translation.Commands.DeleteTranslation(ctx, uint(translationID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateBook is the resolver for the createBook field.
func (r *mutationResolver) CreateBook(ctx context.Context, input model.BookInput) (*model.Book, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}

	createInput := book.CreateBookInput{
		Title:       input.Name,
		Description: *input.Description,
		Language:    input.Language,
		ISBN:        input.Isbn,
	}

	createdBook, err := r.App.Book.Commands.CreateBook(ctx, createInput)
	if err != nil {
		return nil, err
	}

	return &model.Book{
		ID:          fmt.Sprintf("%d", createdBook.ID),
		Name:        createdBook.Title,
		Language:    createdBook.Language,
		Description: &createdBook.Description,
		Isbn:        &createdBook.ISBN,
	}, nil
}

// UpdateBook is the resolver for the updateBook field.
func (r *mutationResolver) UpdateBook(ctx context.Context, id string, input model.BookInput) (*model.Book, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}

	bookID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid book ID", domain.ErrValidation)
	}

	updateInput := book.UpdateBookInput{
		ID:          uint(bookID),
		Title:       &input.Name,
		Description: input.Description,
		Language:    &input.Language,
		ISBN:        input.Isbn,
	}

	updatedBook, err := r.App.Book.Commands.UpdateBook(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.Book{
		ID:          id,
		Name:        updatedBook.Title,
		Language:    updatedBook.Language,
		Description: &updatedBook.Description,
		Isbn:        &updatedBook.ISBN,
	}, nil
}

// DeleteBook is the resolver for the deleteBook field.
func (r *mutationResolver) DeleteBook(ctx context.Context, id string) (bool, error) {
	bookID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("%w: invalid book ID", domain.ErrValidation)
	}

	err = r.App.Book.Commands.DeleteBook(ctx, uint(bookID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateAuthor is the resolver for the createAuthor field.
func (r *mutationResolver) CreateAuthor(ctx context.Context, input model.AuthorInput) (*model.Author, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}
	createInput := author.CreateAuthorInput{
		Name: input.Name,
	}
	createdAuthor, err := r.App.Author.Commands.CreateAuthor(ctx, createInput)
	if err != nil {
		return nil, err
	}

	return &model.Author{
		ID:       fmt.Sprintf("%d", createdAuthor.ID),
		Name:     createdAuthor.Name,
		Language: createdAuthor.Language,
	}, nil
}

// UpdateAuthor is the resolver for the updateAuthor field.
func (r *mutationResolver) UpdateAuthor(ctx context.Context, id string, input model.AuthorInput) (*model.Author, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}
	authorID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid author ID: %v", err)
	}

	updateInput := author.UpdateAuthorInput{
		ID:   uint(authorID),
		Name: input.Name,
	}
	updatedAuthor, err := r.App.Author.Commands.UpdateAuthor(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.Author{
		ID:       id,
		Name:     updatedAuthor.Name,
		Language: updatedAuthor.Language,
	}, nil
}

// DeleteAuthor is the resolver for the deleteAuthor field.
func (r *mutationResolver) DeleteAuthor(ctx context.Context, id string) (bool, error) {
	authorID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("invalid author ID: %v", err)
	}

	err = r.App.Author.Commands.DeleteAuthor(ctx, uint(authorID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// UpdateUser is the resolver for the updateUser field.
func (r *mutationResolver) UpdateUser(ctx context.Context, id string, input model.UserInput) (*model.User, error) {
	if err := Validate(input); err != nil {
		return nil, err
	}

	userID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid user ID: %v", err)
	}

	updateInput := user.UpdateUserInput{
		ID:          uint(userID),
		Username:    input.Username,
		Email:       input.Email,
		Password:    input.Password,
		FirstName:   input.FirstName,
		LastName:    input.LastName,
		DisplayName: input.DisplayName,
		Bio:         input.Bio,
		AvatarURL:   input.AvatarURL,
		Verified:    input.Verified,
		Active:      input.Active,
	}

	if input.Role != nil {
		role := domain.UserRole(input.Role.String())
		updateInput.Role = &role
	}

	if input.CountryID != nil {
		countryID, err := strconv.ParseUint(*input.CountryID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid country ID: %v", err)
		}
		uid := uint(countryID)
		updateInput.CountryID = &uid
	}
	if input.CityID != nil {
		cityID, err := strconv.ParseUint(*input.CityID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid city ID: %v", err)
		}
		uid := uint(cityID)
		updateInput.CityID = &uid
	}
	if input.AddressID != nil {
		addressID, err := strconv.ParseUint(*input.AddressID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid address ID: %v", err)
		}
		uid := uint(addressID)
		updateInput.AddressID = &uid
	}

	updatedUser, err := r.App.User.Commands.UpdateUser(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.User{
		ID:          fmt.Sprintf("%d", updatedUser.ID),
		Username:    updatedUser.Username,
		Email:       updatedUser.Email,
		FirstName:   &updatedUser.FirstName,
		LastName:    &updatedUser.LastName,
		DisplayName: &updatedUser.DisplayName,
		Bio:         &updatedUser.Bio,
		AvatarURL:   &updatedUser.AvatarURL,
		Role:        model.UserRole(updatedUser.Role),
		Verified:    updatedUser.Verified,
		Active:      updatedUser.Active,
	}, nil
}

// DeleteUser is the resolver for the deleteUser field.
func (r *mutationResolver) DeleteUser(ctx context.Context, id string) (bool, error) {
	userID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("%w: invalid user ID", domain.ErrValidation)
	}

	err = r.App.User.Commands.DeleteUser(ctx, uint(userID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateCollection is the resolver for the createCollection field.
func (r *mutationResolver) CreateCollection(ctx context.Context, input model.CollectionInput) (*model.Collection, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	createInput := collection.CreateCollectionInput{
		Name:   input.Name,
		UserID: userID,
	}
	if input.Description != nil {
		createInput.Description = *input.Description
	}
	createdCollection, err := r.App.Collection.Commands.CreateCollection(ctx, createInput)
	if err != nil {
		return nil, err
	}

	return &model.Collection{
		ID:          fmt.Sprintf("%d", createdCollection.ID),
		Name:        createdCollection.Name,
		Description: &createdCollection.Description,
		User: &model.User{
			ID: fmt.Sprintf("%d", userID),
		},
	}, nil
}

// UpdateCollection is the resolver for the updateCollection field.
func (r *mutationResolver) UpdateCollection(ctx context.Context, id string, input model.CollectionInput) (*model.Collection, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	collectionID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid collection ID: %v", err)
	}

	updateInput := collection.UpdateCollectionInput{
		ID:     uint(collectionID),
		Name:   input.Name,
		UserID: userID,
	}
	if input.Description != nil {
		updateInput.Description = *input.Description
	}
	updatedCollection, err := r.App.Collection.Commands.UpdateCollection(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.Collection{
		ID:          id,
		Name:        updatedCollection.Name,
		Description: &updatedCollection.Description,
		User: &model.User{
			ID: fmt.Sprintf("%d", userID),
		},
	}, nil
}

// DeleteCollection is the resolver for the deleteCollection field.
func (r *mutationResolver) DeleteCollection(ctx context.Context, id string) (bool, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return false, fmt.Errorf("unauthorized")
	}

	collectionID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("invalid collection ID: %v", err)
	}

	err = r.App.Collection.Commands.DeleteCollection(ctx, uint(collectionID), userID)
	if err != nil {
		return false, err
	}

	return true, nil
}

// AddWorkToCollection is the resolver for the addWorkToCollection field.
func (r *mutationResolver) AddWorkToCollection(ctx context.Context, collectionID string, workID string) (*model.Collection, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	collID, err := strconv.ParseUint(collectionID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid collection ID: %v", err)
	}
	wID, err := strconv.ParseUint(workID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid work ID: %v", err)
	}

	addInput := collection.AddWorkToCollectionInput{
		CollectionID: uint(collID),
		WorkID:       uint(wID),
		UserID:       userID,
	}
	err = r.App.Collection.Commands.AddWorkToCollection(ctx, addInput)
	if err != nil {
		return nil, err
	}

	updatedCollection, err := r.App.Collection.Queries.Collection(ctx, uint(collID))
	if err != nil {
		return nil, err
	}

	return &model.Collection{
		ID:          collectionID,
		Name:        updatedCollection.Name,
		Description: &updatedCollection.Description,
	}, nil
}

// RemoveWorkFromCollection is the resolver for the removeWorkFromCollection field.
func (r *mutationResolver) RemoveWorkFromCollection(ctx context.Context, collectionID string, workID string) (*model.Collection, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	collID, err := strconv.ParseUint(collectionID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid collection ID: %v", err)
	}
	wID, err := strconv.ParseUint(workID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid work ID: %v", err)
	}

	removeInput := collection.RemoveWorkFromCollectionInput{
		CollectionID: uint(collID),
		WorkID:       uint(wID),
		UserID:       userID,
	}
	err = r.App.Collection.Commands.RemoveWorkFromCollection(ctx, removeInput)
	if err != nil {
		return nil, err
	}

	updatedCollection, err := r.App.Collection.Queries.Collection(ctx, uint(collID))
	if err != nil {
		return nil, err
	}

	return &model.Collection{
		ID:          collectionID,
		Name:        updatedCollection.Name,
		Description: &updatedCollection.Description,
	}, nil
}

// CreateComment is the resolver for the createComment field.
func (r *mutationResolver) CreateComment(ctx context.Context, input model.CommentInput) (*model.Comment, error) {
	if (input.WorkID == nil && input.TranslationID == nil) || (input.WorkID != nil && input.TranslationID != nil) {
		return nil, fmt.Errorf("must provide either workId or translationId, but not both")
	}

	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	createInput := comment.CreateCommentInput{
		Text:   input.Text,
		UserID: userID,
	}
	if input.WorkID != nil {
		workID, err := strconv.ParseUint(*input.WorkID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid work ID: %v", err)
		}
		wID := uint(workID)
		createInput.WorkID = &wID
	}
	if input.TranslationID != nil {
		translationID, err := strconv.ParseUint(*input.TranslationID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid translation ID: %v", err)
		}
		tID := uint(translationID)
		createInput.TranslationID = &tID
	}
	if input.ParentCommentID != nil {
		parentCommentID, err := strconv.ParseUint(*input.ParentCommentID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid parent comment ID: %v", err)
		}
		pID := uint(parentCommentID)
		createInput.ParentID = &pID
	}

	createdComment, err := r.App.Comment.Commands.CreateComment(ctx, createInput)
	if err != nil {
		return nil, err
	}

	if createdComment.WorkID != nil {
		if err := r.App.Analytics.IncrementWorkComments(ctx, *createdComment.WorkID); err != nil {
			log.FromContext(ctx).Error(err, "failed to increment work comments")
		}
	}
	if createdComment.TranslationID != nil {
		if err := r.App.Analytics.IncrementTranslationComments(ctx, *createdComment.TranslationID); err != nil {
			log.FromContext(ctx).Error(err, "failed to increment translation comments")
		}
	}

	return &model.Comment{
		ID:   fmt.Sprintf("%d", createdComment.ID),
		Text: createdComment.Text,
		User: &model.User{
			ID: fmt.Sprintf("%d", userID),
		},
	}, nil
}

// UpdateComment is the resolver for the updateComment field.
func (r *mutationResolver) UpdateComment(ctx context.Context, id string, input model.CommentInput) (*model.Comment, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	commentID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid comment ID: %v", err)
	}

	commentModel, err := r.App.Comment.Queries.Comment(ctx, uint(commentID))
	if err != nil {
		return nil, err
	}
	if commentModel == nil {
		return nil, fmt.Errorf("comment not found")
	}

	if commentModel.UserID != userID {
		return nil, fmt.Errorf("unauthorized")
	}

	updateInput := comment.UpdateCommentInput{
		ID:   uint(commentID),
		Text: input.Text,
	}
	updatedComment, err := r.App.Comment.Commands.UpdateComment(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.Comment{
		ID:   id,
		Text: updatedComment.Text,
		User: &model.User{
			ID: fmt.Sprintf("%d", userID),
		},
	}, nil
}

// DeleteComment is the resolver for the deleteComment field.
func (r *mutationResolver) DeleteComment(ctx context.Context, id string) (bool, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return false, fmt.Errorf("unauthorized")
	}

	commentID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("invalid comment ID: %v", err)
	}

	comment, err := r.App.Comment.Queries.Comment(ctx, uint(commentID))
	if err != nil {
		return false, err
	}
	if comment == nil {
		return false, fmt.Errorf("comment not found")
	}

	if comment.UserID != userID {
		return false, fmt.Errorf("unauthorized")
	}

	err = r.App.Comment.Commands.DeleteComment(ctx, uint(commentID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateLike is the resolver for the createLike field.
func (r *mutationResolver) CreateLike(ctx context.Context, input model.LikeInput) (*model.Like, error) {
	if (input.WorkID == nil && input.TranslationID == nil && input.CommentID == nil) ||
		(input.WorkID != nil && input.TranslationID != nil) ||
		(input.WorkID != nil && input.CommentID != nil) ||
		(input.TranslationID != nil && input.CommentID != nil) {
		return nil, fmt.Errorf("must provide exactly one of workId, translationId, or commentId")
	}

	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	createInput := like.CreateLikeInput{
		UserID: userID,
	}
	if input.WorkID != nil {
		workID, err := strconv.ParseUint(*input.WorkID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid work ID: %v", err)
		}
		wID := uint(workID)
		createInput.WorkID = &wID
	}
	if input.TranslationID != nil {
		translationID, err := strconv.ParseUint(*input.TranslationID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid translation ID: %v", err)
		}
		tID := uint(translationID)
		createInput.TranslationID = &tID
	}
	if input.CommentID != nil {
		commentID, err := strconv.ParseUint(*input.CommentID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid comment ID: %v", err)
		}
		cID := uint(commentID)
		createInput.CommentID = &cID
	}

	createdLike, err := r.App.Like.Commands.CreateLike(ctx, createInput)
	if err != nil {
		return nil, err
	}

	if createdLike.WorkID != nil {
		if err := r.App.Analytics.IncrementWorkLikes(ctx, *createdLike.WorkID); err != nil {
			log.FromContext(ctx).Error(err, "failed to increment work likes")
		}
	}
	if createdLike.TranslationID != nil {
		if err := r.App.Analytics.IncrementTranslationLikes(ctx, *createdLike.TranslationID); err != nil {
			log.FromContext(ctx).Error(err, "failed to increment translation likes")
		}
	}

	return &model.Like{
		ID:   fmt.Sprintf("%d", createdLike.ID),
		User: &model.User{ID: fmt.Sprintf("%d", userID)},
	}, nil
}

// DeleteLike is the resolver for the deleteLike field.
func (r *mutationResolver) DeleteLike(ctx context.Context, id string) (bool, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return false, fmt.Errorf("unauthorized")
	}

	likeID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("invalid like ID: %v", err)
	}

	like, err := r.App.Like.Queries.Like(ctx, uint(likeID))
	if err != nil {
		return false, err
	}
	if like == nil {
		return false, fmt.Errorf("like not found")
	}

	if like.UserID != userID {
		return false, fmt.Errorf("unauthorized")
	}

	err = r.App.Like.Commands.DeleteLike(ctx, uint(likeID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateBookmark is the resolver for the createBookmark field.
func (r *mutationResolver) CreateBookmark(ctx context.Context, input model.BookmarkInput) (*model.Bookmark, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	workID, err := strconv.ParseUint(input.WorkID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid work ID: %v", err)
	}

	createInput := bookmark.CreateBookmarkInput{
		UserID: userID,
		WorkID: uint(workID),
	}
	if input.Name != nil {
		createInput.Name = *input.Name
	}

	createdBookmark, err := r.App.Bookmark.Commands.CreateBookmark(ctx, createInput)
	if err != nil {
		return nil, err
	}

	if err := r.App.Analytics.IncrementWorkBookmarks(ctx, uint(workID)); err != nil {
		log.FromContext(ctx).Error(err, "failed to increment work bookmarks")
	}

	return &model.Bookmark{
		ID:   fmt.Sprintf("%d", createdBookmark.ID),
		Name: &createdBookmark.Name,
		User: &model.User{ID: fmt.Sprintf("%d", userID)},
		Work: &model.Work{ID: fmt.Sprintf("%d", workID)},
	}, nil
}

// DeleteBookmark is the resolver for the deleteBookmark field.
func (r *mutationResolver) DeleteBookmark(ctx context.Context, id string) (bool, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return false, fmt.Errorf("unauthorized")
	}

	bookmarkID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("invalid bookmark ID: %v", err)
	}

	bookmark, err := r.App.Bookmark.Queries.Bookmark(ctx, uint(bookmarkID))
	if err != nil {
		return false, err
	}
	if bookmark == nil {
		return false, fmt.Errorf("bookmark not found")
	}

	if bookmark.UserID != userID {
		return false, fmt.Errorf("unauthorized")
	}

	err = r.App.Bookmark.Commands.DeleteBookmark(ctx, uint(bookmarkID))
	if err != nil {
		return false, err
	}

	return true, nil
}

// CreateContribution is the resolver for the createContribution field.
func (r *mutationResolver) CreateContribution(ctx context.Context, input model.ContributionInput) (*model.Contribution, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, fmt.Errorf("unauthorized")
	}

	createInput := contribution.CreateContributionInput{
		Name: input.Name,
	}

	if input.WorkID != nil {
		workID, err := strconv.ParseUint(*input.WorkID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid work ID: %v", err)
		}
		wID := uint(workID)
		createInput.WorkID = &wID
	}

	if input.TranslationID != nil {
		translationID, err := strconv.ParseUint(*input.TranslationID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid translation ID: %v", err)
		}
		tID := uint(translationID)
		createInput.TranslationID = &tID
	}

	if input.Status != nil {
		createInput.Status = input.Status.String()
	} else {
		createInput.Status = "DRAFT" // Default status
	}

	createdContribution, err := r.App.Contribution.Commands.CreateContribution(ctx, createInput)
	if err != nil {
		return nil, err
	}

	return &model.Contribution{
		ID:     fmt.Sprintf("%d", createdContribution.ID),
		Name:   createdContribution.Name,
		Status: model.ContributionStatus(createdContribution.Status),
		User: &model.User{
			ID: fmt.Sprintf("%d", userID),
		},
	}, nil
}

// UpdateContribution is the resolver for the updateContribution field.
func (r *mutationResolver) UpdateContribution(ctx context.Context, id string, input model.ContributionInput) (*model.Contribution, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, domain.ErrUnauthorized
	}

	contributionID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid contribution ID", domain.ErrValidation)
	}

	updateInput := contribution.UpdateContributionInput{
		ID:     uint(contributionID),
		UserID: userID,
		Name:   &input.Name,
	}

	if input.Status != nil {
		status := input.Status.String()
		updateInput.Status = &status
	}

	updatedContribution, err := r.App.Contribution.Commands.UpdateContribution(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.Contribution{
		ID:     fmt.Sprintf("%d", updatedContribution.ID),
		Name:   updatedContribution.Name,
		Status: model.ContributionStatus(updatedContribution.Status),
		User: &model.User{
			ID: fmt.Sprintf("%d", updatedContribution.UserID),
		},
	}, nil
}

// DeleteContribution is the resolver for the deleteContribution field.
func (r *mutationResolver) DeleteContribution(ctx context.Context, id string) (bool, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return false, domain.ErrUnauthorized
	}

	contributionID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return false, fmt.Errorf("%w: invalid contribution ID", domain.ErrValidation)
	}

	err = r.App.Contribution.Commands.DeleteContribution(ctx, uint(contributionID), userID)
	if err != nil {
		return false, err
	}

	return true, nil
}

// ReviewContribution is the resolver for the reviewContribution field.
func (r *mutationResolver) ReviewContribution(ctx context.Context, id string, status model.ContributionStatus, feedback *string) (*model.Contribution, error) {
	contributionID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid contribution ID", domain.ErrValidation)
	}

	reviewInput := contribution.ReviewContributionInput{
		ID:       uint(contributionID),
		Status:   status.String(),
		Feedback: feedback,
	}

	reviewedContribution, err := r.App.Contribution.Commands.ReviewContribution(ctx, reviewInput)
	if err != nil {
		return nil, err
	}

	return &model.Contribution{
		ID:     fmt.Sprintf("%d", reviewedContribution.ID),
		Name:   reviewedContribution.Name,
		Status: model.ContributionStatus(reviewedContribution.Status),
		User: &model.User{
			ID: fmt.Sprintf("%d", reviewedContribution.UserID),
		},
	}, nil
}

// Logout is the resolver for the logout field.
func (r *mutationResolver) Logout(ctx context.Context) (bool, error) {
	err := r.App.Auth.Commands.Logout(ctx)
	if err != nil {
		return false, err
	}
	return true, nil
}

// RefreshToken is the resolver for the refreshToken field.
func (r *mutationResolver) RefreshToken(ctx context.Context) (*model.AuthPayload, error) {
	authResponse, err := r.App.Auth.Commands.RefreshToken(ctx)
	if err != nil {
		return nil, err
	}

	return &model.AuthPayload{
		Token: authResponse.Token,
		User: &model.User{
			ID:          fmt.Sprintf("%d", authResponse.User.ID),
			Username:    authResponse.User.Username,
			Email:       authResponse.User.Email,
			FirstName:   &authResponse.User.FirstName,
			LastName:    &authResponse.User.LastName,
			DisplayName: &authResponse.User.DisplayName,
			Role:        model.UserRole(authResponse.User.Role),
			Verified:    authResponse.User.Verified,
			Active:      authResponse.User.Active,
		},
	}, nil
}

// ForgotPassword is the resolver for the forgotPassword field.
func (r *mutationResolver) ForgotPassword(ctx context.Context, email string) (bool, error) {
	err := r.App.Auth.Commands.ForgotPassword(ctx, email)
	if err != nil {
		return true, nil
	}
	return true, nil
}

// ResetPassword is the resolver for the resetPassword field.
func (r *mutationResolver) ResetPassword(ctx context.Context, token string, newPassword string) (bool, error) {
	resetInput := auth.ResetPasswordInput{
		Token:       token,
		NewPassword: newPassword,
	}
	err := r.App.Auth.Commands.ResetPassword(ctx, resetInput)
	if err != nil {
		return false, err
	}
	return true, nil
}

// VerifyEmail is the resolver for the verifyEmail field.
func (r *mutationResolver) VerifyEmail(ctx context.Context, token string) (bool, error) {
	err := r.App.Auth.Commands.VerifyEmail(ctx, token)
	if err != nil {
		return false, err
	}
	return true, nil
}

// ResendVerificationEmail is the resolver for the resendVerificationEmail field.
func (r *mutationResolver) ResendVerificationEmail(ctx context.Context, email string) (bool, error) {
	err := r.App.Auth.Commands.ResendVerificationEmail(ctx, email)
	if err != nil {
		return true, nil
	}
	return true, nil
}

// UpdateProfile is the resolver for the updateProfile field.
func (r *mutationResolver) UpdateProfile(ctx context.Context, input model.UserInput) (*model.User, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, domain.ErrUnauthorized
	}

	updateInput := user.UpdateUserInput{
		ID:          userID,
		FirstName:   input.FirstName,
		LastName:    input.LastName,
		DisplayName: input.DisplayName,
		Bio:         input.Bio,
		AvatarURL:   input.AvatarURL,
	}

	if input.CountryID != nil {
		countryID, err := strconv.ParseUint(*input.CountryID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid country ID: %v", err)
		}
		uid := uint(countryID)
		updateInput.CountryID = &uid
	}
	if input.CityID != nil {
		cityID, err := strconv.ParseUint(*input.CityID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid city ID: %v", err)
		}
		uid := uint(cityID)
		updateInput.CityID = &uid
	}
	if input.AddressID != nil {
		addressID, err := strconv.ParseUint(*input.AddressID, 10, 32)
		if err != nil {
			return nil, fmt.Errorf("invalid address ID: %v", err)
		}
		uid := uint(addressID)
		updateInput.AddressID = &uid
	}

	updatedUser, err := r.App.User.Commands.UpdateUser(ctx, updateInput)
	if err != nil {
		return nil, err
	}

	return &model.User{
		ID:          fmt.Sprintf("%d", updatedUser.ID),
		Username:    updatedUser.Username,
		Email:       updatedUser.Email,
		FirstName:   &updatedUser.FirstName,
		LastName:    &updatedUser.LastName,
		DisplayName: &updatedUser.DisplayName,
		Bio:         &updatedUser.Bio,
		AvatarURL:   &updatedUser.AvatarURL,
		Role:        model.UserRole(updatedUser.Role),
		Verified:    updatedUser.Verified,
		Active:      updatedUser.Active,
	}, nil
}

// ChangePassword is the resolver for the changePassword field.
func (r *mutationResolver) ChangePassword(ctx context.Context, currentPassword string, newPassword string) (bool, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return false, domain.ErrUnauthorized
	}

	changeInput := auth.ChangePasswordInput{
		UserID:          userID,
		CurrentPassword: currentPassword,
		NewPassword:     newPassword,
	}

	err := r.App.Auth.Commands.ChangePassword(ctx, changeInput)
	if err != nil {
		return false, err
	}

	return true, nil
}

// Work is the resolver for the work field.
func (r *queryResolver) Work(ctx context.Context, id string) (*model.Work, error) {
	workID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid work ID: %v", err)
	}

	workDTO, err := r.App.Work.Queries.GetWorkByID(ctx, uint(workID))
	if err != nil {
		if errors.Is(err, domain.ErrEntityNotFound) {
			return nil, nil
		}
		return nil, err
	}

	go func() {
		if err := r.App.Analytics.IncrementWorkViews(context.Background(), uint(workID)); err != nil {
			log.Error(err, "failed to increment work views")
		}
	}()

	content := r.resolveWorkContent(ctx, workDTO.ID, workDTO.Language)

	return &model.Work{
		ID:       id,
		Name:     workDTO.Title,
		Language: workDTO.Language,
		Content:  content,
	}, nil
}

// Works is the resolver for the works field.
func (r *queryResolver) Works(ctx context.Context, limit *int32, offset *int32, language *string, authorID *string, categoryID *string, tagID *string, search *string) ([]*model.Work, error) {
	page := 1
	pageSize := 20
	if limit != nil {
		pageSize = int(*limit)
	}
	if offset != nil {
		page = int(*offset)/pageSize + 1
	}

	paginatedResult, err := r.App.Work.Queries.ListWorks(ctx, page, pageSize)
	if err != nil {
		return nil, err
	}

	var result []*model.Work
	for _, w := range paginatedResult.Items {
		content := r.resolveWorkContent(ctx, w.ID, w.Language)
		result = append(result, &model.Work{
			ID:       fmt.Sprintf("%d", w.ID),
			Name:     w.Title,
			Language: w.Language,
			Content:  content,
		})
	}
	return result, nil
}

// Translation is the resolver for the translation field.
func (r *queryResolver) Translation(ctx context.Context, id string) (*model.Translation, error) {
	translationID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid translation ID: %v", err)
	}

	translationDTO, err := r.App.Translation.Queries.Translation(ctx, uint(translationID))
	if err != nil {
		return nil, err
	}
	if translationDTO == nil {
		return nil, nil
	}

	go func() {
		if err := r.App.Analytics.IncrementTranslationViews(context.Background(), uint(translationID)); err != nil {
			log.Error(err, "failed to increment translation views")
		}
	}()

	return &model.Translation{
		ID:       id,
		Name:     translationDTO.Title,
		Language: translationDTO.Language,
		Content:  &translationDTO.Content,
		WorkID:   fmt.Sprintf("%d", translationDTO.TranslatableID),
	}, nil
}

// Translations is the resolver for the translations field.
func (r *queryResolver) Translations(ctx context.Context, workID string, language *string, limit *int32, offset *int32) ([]*model.Translation, error) {
	wID, err := strconv.ParseUint(workID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid work ID", domain.ErrValidation)
	}

	page := 1
	pageSize := 20
	if limit != nil {
		pageSize = int(*limit)
	}
	if offset != nil {
		page = int(*offset)/pageSize + 1
	}

	paginatedResult, err := r.App.Translation.Queries.ListTranslations(ctx, uint(wID), language, page, pageSize)
	if err != nil {
		return nil, err
	}

	var result []*model.Translation
	for _, t := range paginatedResult.Items {
		result = append(result, &model.Translation{
			ID:       fmt.Sprintf("%d", t.ID),
			Name:     t.Title,
			Language: t.Language,
			Content:  &t.Content,
			WorkID:   workID,
		})
	}
	return result, nil
}

// Book is the resolver for the book field.
func (r *queryResolver) Book(ctx context.Context, id string) (*model.Book, error) {
	bookID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid book ID", domain.ErrValidation)
	}

	bookRecord, err := r.App.Book.Queries.Book(ctx, uint(bookID))
	if err != nil {
		return nil, err
	}
	if bookRecord == nil {
		return nil, nil
	}

	return &model.Book{
		ID:          fmt.Sprintf("%d", bookRecord.ID),
		Name:        bookRecord.Title,
		Language:    bookRecord.Language,
		Description: &bookRecord.Description,
		Isbn:        &bookRecord.ISBN,
	}, nil
}

// Books is the resolver for the books field.
func (r *queryResolver) Books(ctx context.Context, limit *int32, offset *int32) ([]*model.Book, error) {
	books, err := r.App.Book.Queries.Books(ctx)
	if err != nil {
		return nil, err
	}

	var result []*model.Book
	for _, b := range books {
		result = append(result, &model.Book{
			ID:          fmt.Sprintf("%d", b.ID),
			Name:        b.Title,
			Language:    b.Language,
			Description: &b.Description,
			Isbn:        &b.ISBN,
		})
	}

	return result, nil
}

// Author is the resolver for the author field.
func (r *queryResolver) Author(ctx context.Context, id string) (*model.Author, error) {
	authorID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid author ID", domain.ErrValidation)
	}

	authorRecord, err := r.App.Author.Queries.Author(ctx, uint(authorID))
	if err != nil {
		return nil, err
	}
	if authorRecord == nil {
		return nil, nil
	}

	var bio *string
	authorWithTranslations, err := r.App.Author.Queries.AuthorWithTranslations(ctx, authorRecord.ID)
	if err == nil && authorWithTranslations != nil {
		biography, err := r.App.Localization.Queries.GetAuthorBiography(ctx, authorRecord.ID, authorRecord.Language)
		if err == nil && biography != "" {
			bio = &biography
		}
	}

	return &model.Author{
		ID:        fmt.Sprintf("%d", authorRecord.ID),
		Name:      authorRecord.Name,
		Language:  authorRecord.Language,
		Biography: bio,
	}, nil
}

// Authors is the resolver for the authors field.
func (r *queryResolver) Authors(ctx context.Context, limit *int32, offset *int32, search *string, countryID *string) ([]*model.Author, error) {
	var authors []*domain.Author
	var err error
	var countryIDUint *uint

	if countryID != nil {
		parsedID, err := strconv.ParseUint(*countryID, 10, 32)
		if err != nil {
			return nil, err
		}
		uid := uint(parsedID)
		countryIDUint = &uid
	}

	authors, err = r.App.Author.Queries.Authors(ctx, countryIDUint)
	if err != nil {
		return nil, err
	}

	var result []*model.Author
	for _, a := range authors {
		var bio *string
		authorWithTranslations, err := r.App.Author.Queries.AuthorWithTranslations(ctx, a.ID)
		if err == nil && authorWithTranslations != nil {
			biography, err := r.App.Localization.Queries.GetAuthorBiography(ctx, a.ID, a.Language)
			if err == nil && biography != "" {
				bio = &biography
			}
		}

		result = append(result, &model.Author{
			ID:        fmt.Sprintf("%d", a.ID),
			Name:      a.Name,
			Language:  a.Language,
			Biography: bio,
		})
	}

	return result, nil
}

// User is the resolver for the user field.
func (r *queryResolver) User(ctx context.Context, id string) (*model.User, error) {
	userID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid user ID", domain.ErrValidation)
	}

	userRecord, err := r.App.User.Queries.User(ctx, uint(userID))
	if err != nil {
		return nil, err
	}
	if userRecord == nil {
		return nil, nil
	}

	return &model.User{
		ID:          fmt.Sprintf("%d", userRecord.ID),
		Username:    userRecord.Username,
		Email:       userRecord.Email,
		FirstName:   &userRecord.FirstName,
		LastName:    &userRecord.LastName,
		DisplayName: &userRecord.DisplayName,
		Bio:         &userRecord.Bio,
		AvatarURL:   &userRecord.AvatarURL,
		Role:        model.UserRole(userRecord.Role),
		Verified:    userRecord.Verified,
		Active:      userRecord.Active,
	}, nil
}

// UserByEmail is the resolver for the userByEmail field.
func (r *queryResolver) UserByEmail(ctx context.Context, email string) (*model.User, error) {
	userRecord, err := r.App.User.Queries.UserByEmail(ctx, email)
	if err != nil {
		return nil, err
	}
	if userRecord == nil {
		return nil, nil
	}

	return &model.User{
		ID:          fmt.Sprintf("%d", userRecord.ID),
		Username:    userRecord.Username,
		Email:       userRecord.Email,
		FirstName:   &userRecord.FirstName,
		LastName:    &userRecord.LastName,
		DisplayName: &userRecord.DisplayName,
		Bio:         &userRecord.Bio,
		AvatarURL:   &userRecord.AvatarURL,
		Role:        model.UserRole(userRecord.Role),
		Verified:    userRecord.Verified,
		Active:      userRecord.Active,
	}, nil
}

// UserByUsername is the resolver for the userByUsername field.
func (r *queryResolver) UserByUsername(ctx context.Context, username string) (*model.User, error) {
	userRecord, err := r.App.User.Queries.UserByUsername(ctx, username)
	if err != nil {
		return nil, err
	}
	if userRecord == nil {
		return nil, nil
	}

	return &model.User{
		ID:          fmt.Sprintf("%d", userRecord.ID),
		Username:    userRecord.Username,
		Email:       userRecord.Email,
		FirstName:   &userRecord.FirstName,
		LastName:    &userRecord.LastName,
		DisplayName: &userRecord.DisplayName,
		Bio:         &userRecord.Bio,
		AvatarURL:   &userRecord.AvatarURL,
		Role:        model.UserRole(userRecord.Role),
		Verified:    userRecord.Verified,
		Active:      userRecord.Active,
	}, nil
}

// Users is the resolver for the users field.
func (r *queryResolver) Users(ctx context.Context, limit *int32, offset *int32, role *model.UserRole) ([]*model.User, error) {
	var users []domain.User
	var err error

	if role != nil {
		var modelRole domain.UserRole
		switch *role {
		case model.UserRoleReader:
			modelRole = domain.UserRoleReader
		case model.UserRoleContributor:
			modelRole = domain.UserRoleContributor
		case model.UserRoleReviewer:
			modelRole = domain.UserRoleReviewer
		case model.UserRoleEditor:
			modelRole = domain.UserRoleEditor
		case model.UserRoleAdmin:
			modelRole = domain.UserRoleAdmin
		default:
			return nil, fmt.Errorf("invalid user role: %s", *role)
		}
		users, err = r.App.User.Queries.UsersByRole(ctx, modelRole)
	} else {
		users, err = r.App.User.Queries.Users(ctx)
	}

	if err != nil {
		return nil, err
	}

	var result []*model.User
	for _, u := range users {
		var graphqlRole model.UserRole
		switch u.Role {
		case domain.UserRoleReader:
			graphqlRole = model.UserRoleReader
		case domain.UserRoleContributor:
			graphqlRole = model.UserRoleContributor
		case domain.UserRoleReviewer:
			graphqlRole = model.UserRoleReviewer
		case domain.UserRoleEditor:
			graphqlRole = model.UserRoleEditor
		case domain.UserRoleAdmin:
			graphqlRole = model.UserRoleAdmin
		default:
			graphqlRole = model.UserRoleReader
		}

		result = append(result, &model.User{
			ID:       fmt.Sprintf("%d", u.ID),
			Username: u.Username,
			Email:    u.Email,
			Role:     graphqlRole,
		})
	}

	return result, nil
}

// Me is the resolver for the me field.
func (r *queryResolver) Me(ctx context.Context) (*model.User, error) {
	userID, ok := platform_auth.GetUserIDFromContext(ctx)
	if !ok {
		return nil, domain.ErrUnauthorized
	}

	userRecord, err := r.App.User.Queries.User(ctx, userID)
	if err != nil {
		return nil, err
	}
	if userRecord == nil {
		return nil, domain.ErrUserNotFound
	}

	return &model.User{
		ID:          fmt.Sprintf("%d", userRecord.ID),
		Username:    userRecord.Username,
		Email:       userRecord.Email,
		FirstName:   &userRecord.FirstName,
		LastName:    &userRecord.LastName,
		DisplayName: &userRecord.DisplayName,
		Bio:         &userRecord.Bio,
		AvatarURL:   &userRecord.AvatarURL,
		Role:        model.UserRole(userRecord.Role),
		Verified:    userRecord.Verified,
		Active:      userRecord.Active,
	}, nil
}

// UserProfile is the resolver for the userProfile field.
func (r *queryResolver) UserProfile(ctx context.Context, userID string) (*model.UserProfile, error) {
	uID, err := strconv.ParseUint(userID, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid user ID", domain.ErrValidation)
	}

	profile, err := r.App.User.Queries.UserProfile(ctx, uint(uID))
	if err != nil {
		return nil, err
	}
	if profile == nil {
		return nil, nil
	}

	user, err := r.App.User.Queries.User(ctx, uint(uID))
	if err != nil {
		return nil, err
	}
	if user == nil {
		return nil, fmt.Errorf("user not found for profile %d", profile.ID)
	}

	return &model.UserProfile{
		ID:     fmt.Sprintf("%d", profile.ID),
		UserID: userID,
		User: &model.User{
			ID:          fmt.Sprintf("%d", user.ID),
			Username:    user.Username,
			Email:       user.Email,
			FirstName:   &user.FirstName,
			LastName:    &user.LastName,
			DisplayName: &user.DisplayName,
			Bio:         &user.Bio,
			AvatarURL:   &user.AvatarURL,
			Role:        model.UserRole(user.Role),
			Verified:    user.Verified,
			Active:      user.Active,
		},
		PhoneNumber: &profile.PhoneNumber,
		Website:     &profile.Website,
		Twitter:     &profile.Twitter,
		Facebook:    &profile.Facebook,
		LinkedIn:    &profile.LinkedIn,
		Github:      &profile.Github,
	}, nil
}

// Collection is the resolver for the collection field.
func (r *queryResolver) Collection(ctx context.Context, id string) (*model.Collection, error) {
	collID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid collection ID", domain.ErrValidation)
	}

	collectionRecord, err := r.App.Collection.Queries.Collection(ctx, uint(collID))
	if err != nil {
		return nil, err
	}
	if collectionRecord == nil {
		return nil, nil
	}

	workRecords, err := r.App.Work.Queries.ListByCollectionID(ctx, uint(collID))
	if err != nil {
		return nil, err
	}

	var works []*model.Work
	for _, w := range workRecords {
		content := r.resolveWorkContent(ctx, w.ID, w.Language)
		works = append(works, &model.Work{
			ID:       fmt.Sprintf("%d", w.ID),
			Name:     w.Title,
			Language: w.Language,
			Content:  content,
		})
	}

	return &model.Collection{
		ID:          fmt.Sprintf("%d", collectionRecord.ID),
		Name:        collectionRecord.Name,
		Description: &collectionRecord.Description,
		Works:       works,
		User: &model.User{
			ID: fmt.Sprintf("%d", collectionRecord.UserID),
		},
	}, nil
}

// Collections is the resolver for the collections field.
func (r *queryResolver) Collections(ctx context.Context, userID *string, limit *int32, offset *int32) ([]*model.Collection, error) {
	var collectionRecords []domain.Collection
	var err error

	if userID != nil {
		uID, idErr := strconv.ParseUint(*userID, 10, 32)
		if idErr != nil {
			return nil, fmt.Errorf("%w: invalid user ID", domain.ErrValidation)
		}
		collectionRecords, err = r.App.Collection.Queries.CollectionsByUserID(ctx, uint(uID))
	} else {
		collectionRecords, err = r.App.Collection.Queries.PublicCollections(ctx)
	}

	if err != nil {
		return nil, err
	}

	start := 0
	if offset != nil {
		start = int(*offset)
	}
	end := len(collectionRecords)
	if limit != nil {
		end = start + int(*limit)
		if end > len(collectionRecords) {
			end = len(collectionRecords)
		}
	}
	if start > len(collectionRecords) {
		start = len(collectionRecords)
	}
	paginatedRecords := collectionRecords[start:end]

	var result []*model.Collection
	for _, c := range paginatedRecords {
		result = append(result, &model.Collection{
			ID:          fmt.Sprintf("%d", c.ID),
			Name:        c.Name,
			Description: &c.Description,
			User: &model.User{
				ID: fmt.Sprintf("%d", c.UserID),
			},
		})
	}
	return result, nil
}

// Tag is the resolver for the tag field.
func (r *queryResolver) Tag(ctx context.Context, id string) (*model.Tag, error) {
	tagID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, err
	}

	tag, err := r.App.Tag.Queries.Tag(ctx, uint(tagID))
	if err != nil {
		return nil, err
	}

	return &model.Tag{
		ID:   fmt.Sprintf("%d", tag.ID),
		Name: tag.Name,
	}, nil
}

// Tags is the resolver for the tags field.
func (r *queryResolver) Tags(ctx context.Context, limit *int32, offset *int32) ([]*model.Tag, error) {
	tags, err := r.App.Tag.Queries.Tags(ctx)
	if err != nil {
		return nil, err
	}

	var result []*model.Tag
	for _, t := range tags {
		result = append(result, &model.Tag{
			ID:   fmt.Sprintf("%d", t.ID),
			Name: t.Name,
		})
	}

	return result, nil
}

// Category is the resolver for the category field.
func (r *queryResolver) Category(ctx context.Context, id string) (*model.Category, error) {
	categoryID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("invalid category ID: %v", err)
	}

	category, err := r.App.Category.Queries.Category(ctx, uint(categoryID))
	if err != nil {
		return nil, err
	}
	if category == nil {
		return nil, nil
	}

	return &model.Category{
		ID:   fmt.Sprintf("%d", category.ID),
		Name: category.Name,
	}, nil
}

// Categories is the resolver for the categories field.
func (r *queryResolver) Categories(ctx context.Context, limit *int32, offset *int32) ([]*model.Category, error) {
	categories, err := r.App.Category.Queries.Categories(ctx)
	if err != nil {
		return nil, err
	}

	var result []*model.Category
	for _, c := range categories {
		result = append(result, &model.Category{
			ID:   fmt.Sprintf("%d", c.ID),
			Name: c.Name,
		})
	}

	return result, nil
}

// Comment is the resolver for the comment field.
func (r *queryResolver) Comment(ctx context.Context, id string) (*model.Comment, error) {
	cID, err := strconv.ParseUint(id, 10, 32)
	if err != nil {
		return nil, fmt.Errorf("%w: invalid comment ID", domain.ErrValidation)
	}

	commentRecord, err := r.App.Comment.Queries.Comment(ctx, uint(cID))
	if err != nil {
		return nil, err
	}
	if commentRecord == nil {
		return nil, nil
	}

	return &model.Comment{
		ID:   fmt.Sprintf("%d", commentRecord.ID),
		Text: commentRecord.Text,
		User: &model.User{
			ID: fmt.Sprintf("%d", commentRecord.UserID),
		},
	}, nil
}

// Comments is the resolver for the comments field.
func (r *queryResolver) Comments(ctx context.Context, workID *string, translationID *string, userID *string, limit *int32, offset *int32) ([]*model.Comment, error) {
	var commentRecords []domain.Comment
	var err error

	if workID != nil {
		wID, idErr := strconv.ParseUint(*workID, 10, 32)
		if idErr != nil {
			return nil, fmt.Errorf("%w: invalid work ID", domain.ErrValidation)
		}
		commentRecords, err = r.App.Comment.Queries.CommentsByWorkID(ctx, uint(wID))
	} else if translationID != nil {
		tID, idErr := strconv.ParseUint(*translationID, 10, 32)
		if idErr != nil {
			return nil, fmt.Errorf("%w: invalid translation ID", domain.ErrValidation)
		}
		commentRecords, err = r.App.Comment.Queries.CommentsByTranslationID(ctx, uint(tID))
	} else if userID != nil {
		uID, idErr := strconv.ParseUint(*userID, 10, 32)
		if idErr != nil {
			return nil, fmt.Errorf("%w: invalid user ID", domain.ErrValidation)
		}
		commentRecords, err = r.App.Comment.Queries.CommentsByUserID(ctx, uint(uID))
	} else {
		commentRecords, err = r.App.Comment.Queries.Comments(ctx)
	}

	if err != nil {
		return nil, err
	}

	start := 0
	if offset != nil {
		start = int(*offset)
	}
	end := len(commentRecords)
	if limit != nil {
		end = start + int(*limit)
		if end > len(commentRecords) {
			end = len(commentRecords)
		}
	}
	if start > len(commentRecords) {
		start = len(commentRecords)
	}
	paginatedRecords := commentRecords[start:end]

	var result []*model.Comment
	for _, c := range paginatedRecords {
		result = append(result, &model.Comment{
			ID:   fmt.Sprintf("%d", c.ID),
			Text: c.Text,
			User: &model.User{
				ID: fmt.Sprintf("%d", c.UserID),
			},
		})
	}
	return result, nil
}

// Search is the resolver for the search field.
func (r *queryResolver) Search(ctx context.Context, query string, limit *int32, offset *int32, filters *model.SearchFilters) (*model.SearchResults, error) {
	page := 1
	pageSize := 20
	if limit != nil {
		pageSize = int(*limit)
	}
	if offset != nil {
		page = int(*offset)/pageSize + 1
	}

	var searchFilters domain.SearchFilters
	if filters != nil {
		searchFilters.Languages = filters.Languages
		searchFilters.Categories = filters.Categories
		searchFilters.Tags = filters.Tags
		searchFilters.Authors = filters.Authors

		if filters.DateFrom != nil {
			t, err := time.Parse(time.RFC3339, *filters.DateFrom)
			if err != nil {
				return nil, fmt.Errorf("invalid DateFrom format: %w", err)
			}
			searchFilters.DateFrom = &t
		}
		if filters.DateTo != nil {
			t, err := time.Parse(time.RFC3339, *filters.DateTo)
			if err != nil {
				return nil, fmt.Errorf("invalid DateTo format: %w", err)
			}
			searchFilters.DateTo = &t
		}
	}

	results, err := r.App.Search.Search(ctx, query, page, pageSize, searchFilters)
	if err != nil {
		return nil, err
	}

	var works []*model.Work
	for _, w := range results.Works {
		works = append(works, &model.Work{
			ID:       fmt.Sprintf("%d", w.ID),
			Name:     w.Title,
			Language: w.Language,
		})
	}

	var translations []*model.Translation
	for _, t := range results.Translations {
		translations = append(translations, &model.Translation{
			ID:       fmt.Sprintf("%d", t.ID),
			Name:     t.Title,
			Language: t.Language,
			Content:  &t.Content,
			WorkID:   fmt.Sprintf("%d", t.TranslatableID),
		})
	}

	var authors []*model.Author
	for _, a := range results.Authors {
		authors = append(authors, &model.Author{
			ID:       fmt.Sprintf("%d", a.ID),
			Name:     a.Name,
			Language: a.Language,
		})
	}

	return &model.SearchResults{
		Works:        works,
		Translations: translations,
		Authors:      authors,
		Total:        int32(results.Total),
	}, nil
}

// TrendingWorks is the resolver for the trendingWorks field.
func (r *queryResolver) TrendingWorks(ctx context.Context, timePeriod *string, limit *int32) ([]*model.Work, error) {
	tp := "daily"
	if timePeriod != nil {
		tp = *timePeriod
	}

	l := 10
	if limit != nil {
		l = int(*limit)
	}

	workRecords, err := r.App.Analytics.GetTrendingWorks(ctx, tp, l)
	if err != nil {
		return nil, err
	}

	var result []*model.Work
	for _, w := range workRecords {
		result = append(result, &model.Work{
			ID:       fmt.Sprintf("%d", w.ID),
			Name:     w.Title,
			Language: w.Language,
		})
	}

	return result, nil
}

// Mutation returns MutationResolver implementation.
func (r *Resolver) Mutation() MutationResolver { return &mutationResolver{r} }

// Query returns QueryResolver implementation.
func (r *Resolver) Query() QueryResolver { return &queryResolver{r} }

type mutationResolver struct{ *Resolver }
type queryResolver struct{ *Resolver }
