package services

import (
	"context"
	"git.sch9.ru/new_gate/ms-tester/internal/lib"
	"git.sch9.ru/new_gate/ms-tester/internal/models"
)

type ProblemStorage interface {
	CreateProblem(ctx context.Context, problem *models.Problem, testGroupData []models.TestGroupData) (int32, error)
	ReadProblemById(ctx context.Context, id int32) (*models.Problem, error)
	UpdateProblem(ctx context.Context, problem *models.Problem) error
	DeleteProblem(ctx context.Context, id int32) error
}

type PandocClient interface {
	ConvertLatexToHtml5(ctx context.Context, text string) (string, error)
}

type IPermissionService interface {
	Allowed(ctx context.Context, user *models.User, action string) bool
}

type ProblemService struct {
	problemStorage    ProblemStorage
	pandocClient      PandocClient
	permissionService IPermissionService
}

func NewProblemService(
	problemStorage ProblemStorage,
	pandocClient PandocClient,
    permissionService IPermissionService,
) *ProblemService {
	return &ProblemService{
		problemStorage:    problemStorage,
		pandocClient:      pandocClient,
        permissionService: permissionService,
	}
}

func extractUser(ctx context.Context) *models.User {
	return ctx.Value("user").(*models.User)
}

func (service *ProblemService) CanCreateProblem(ctx context.Context) error {
	if !service.permissionService.Allowed(ctx, extractUser(ctx), "create") {
		return lib.ServiceError(nil, lib.ErrNoPermission, "permission denied")
	}
	return nil
}

func (service *ProblemService) CanReadProblemById(ctx context.Context) error {
	if !service.permissionService.Allowed(ctx, extractUser(ctx), "read") {
		return lib.ServiceError(nil, lib.ErrNoPermission, "permission denied")
	}
	return nil
}

func (service *ProblemService) CanUpdateProblem(ctx context.Context) error {
	if !service.permissionService.Allowed(ctx, extractUser(ctx), "update") {
		return lib.ServiceError(nil, lib.ErrNoPermission, "permission denied")
	}
	return nil
}

func (service *ProblemService) CanDeleteProblem(ctx context.Context) error {
	if !service.permissionService.Allowed(ctx, extractUser(ctx), "delete") {
		return lib.ServiceError(nil, lib.ErrNoPermission, "permission denied")
	}
	return nil
}

func (service *ProblemService) CreateProblem(ctx context.Context, problem *models.Problem) (int32, error) {
	if err := service.CanCreateProblem(ctx); err != nil {
		return 0, err
	}
	_, err := service.pandocClient.ConvertLatexToHtml5(ctx, *problem.Description)
	if err != nil {
		return 0, err
	}
	return service.problemStorage.CreateProblem(ctx, problem, nil)
}

func (service *ProblemService) ReadProblemById(ctx context.Context, id int32) (*models.Problem, error) {
	if err := service.CanReadProblemById(ctx); err != nil {
		return nil, err
	}
	return service.problemStorage.ReadProblemById(ctx, id)
}

func (service *ProblemService) UpdateProblem(ctx context.Context, problem *models.Problem) error {
	if err := service.CanUpdateProblem(ctx); err != nil {
		return err
	}
	return service.problemStorage.UpdateProblem(ctx, problem)
}

func (service *ProblemService) DeleteProblem(ctx context.Context, id int32) error {
	if err := service.CanDeleteProblem(ctx); err != nil {
		return err
	}
	return service.problemStorage.DeleteProblem(ctx, id)
}
