package sql_test

import (
	"context"
	"testing"
	"tercul/internal/data/sql"
	"tercul/internal/domain"
	"tercul/internal/platform/config"
	"tercul/internal/testutil"

	"github.com/stretchr/testify/suite"
)

type LikeRepositoryTestSuite struct {
	testutil.IntegrationTestSuite
	LikeRepo domain.LikeRepository
	UserRepo domain.UserRepository
	WorkRepo domain.WorkRepository
}

func (s *LikeRepositoryTestSuite) SetupSuite() {
	s.IntegrationTestSuite.SetupSuite(testutil.DefaultTestConfig())
	cfg, err := config.LoadConfig()
	s.Require().NoError(err)
	s.LikeRepo = sql.NewLikeRepository(s.DB, cfg)
	s.UserRepo = sql.NewUserRepository(s.DB, cfg)
	s.WorkRepo = sql.NewWorkRepository(s.DB, cfg)
}

func (s *LikeRepositoryTestSuite) SetupTest() {
	s.IntegrationTestSuite.SetupTest()
	s.DB.Exec("DELETE FROM likes")
	s.DB.Exec("DELETE FROM works")
}

func TestLikeRepository(t *testing.T) {
	suite.Run(t, new(LikeRepositoryTestSuite))
}

func (s *LikeRepositoryTestSuite) createUser(username string) *domain.User {
	user := &domain.User{Username: username, Email: username + "@test.com"}
	err := s.UserRepo.Create(context.Background(), user)
	s.Require().NoError(err)
	return user
}

func (s *LikeRepositoryTestSuite) TestListByUserID() {
	s.Run("should return all likes for a given user", func() {
		// Arrange
		user1 := s.createUser("user1")
		user2 := s.createUser("user2")
		work := s.CreateTestWork(s.AdminCtx, "Test Work", "en", "Test content")

		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, WorkID: &work.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, WorkID: &work.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user2.ID, WorkID: &work.ID}))

		// Act
		likes, err := s.LikeRepo.ListByUserID(context.Background(), user1.ID)

		// Assert
		s.Require().NoError(err)
		s.Len(likes, 2)
	})
}

func (s *LikeRepositoryTestSuite) TestListByWorkID() {
	s.Run("should return all likes for a given work", func() {
		// Arrange
		user1 := s.createUser("user1")
		work1 := s.CreateTestWork(s.AdminCtx, "Test Work 1", "en", "Test content")
		work2 := s.CreateTestWork(s.AdminCtx, "Test Work 2", "en", "Test content")

		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, WorkID: &work1.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, WorkID: &work1.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, WorkID: &work2.ID}))

		// Act
		likes, err := s.LikeRepo.ListByWorkID(context.Background(), work1.ID)

		// Assert
		s.Require().NoError(err)
		s.Len(likes, 2)
	})
}

func (s *LikeRepositoryTestSuite) TestListByTranslationID() {
	s.Run("should return all likes for a given translation", func() {
		// Arrange
		user1 := s.createUser("user1")
		work := s.CreateTestWork(s.AdminCtx, "Test Work", "en", "Test content")
		translation1 := s.CreateTestTranslation(work.ID, "es", "Contenido de prueba")
		translation2 := s.CreateTestTranslation(work.ID, "fr", "Contenu de test")

		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, TranslationID: &translation1.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, TranslationID: &translation1.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, TranslationID: &translation2.ID}))

		// Act
		likes, err := s.LikeRepo.ListByTranslationID(context.Background(), translation1.ID)

		// Assert
		s.Require().NoError(err)
		s.Len(likes, 2)
	})
}

func (s *LikeRepositoryTestSuite) TestListByCommentID() {
	s.Run("should return all likes for a given comment", func() {
		// Arrange
		user1 := s.createUser("user1")
		work := s.CreateTestWork(s.AdminCtx, "Test Work", "en", "Test content")
		comment1 := &domain.Comment{UserID: user1.ID, WorkID: &work.ID, Text: "Comment 1"}
		comment2 := &domain.Comment{UserID: user1.ID, WorkID: &work.ID, Text: "Comment 2"}
		s.Require().NoError(s.DB.Create(comment1).Error)
		s.Require().NoError(s.DB.Create(comment2).Error)

		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, CommentID: &comment1.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, CommentID: &comment1.ID}))
		s.Require().NoError(s.LikeRepo.Create(context.Background(), &domain.Like{UserID: user1.ID, CommentID: &comment2.ID}))

		// Act
		likes, err := s.LikeRepo.ListByCommentID(context.Background(), comment1.ID)

		// Assert
		s.Require().NoError(err)
		s.Len(likes, 2)
	})
}