package admin

import (
	"context"

	"git.dmitriygnatenko.ru/dima/go-common/db"
	"git.dmitriygnatenko.ru/dima/go-common/logger"
	"github.com/gofiber/fiber/v2"

	customErrors "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/helper/errors"
	"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/helper/request"
	"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/model"
	"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/service/handler"
	"git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/service/i18n"
)

type deleteArticlePage struct {
	tm                   TransactionManager
	articleRepository    ArticleRepository
	articleTagRepository ArticleTagRepository
	cacheService         CacheService
}

func NewDeleteArticlePageHandler(
	tm TransactionManager,
	articleRepository ArticleRepository,
	articleTagRepository ArticleTagRepository,
	cacheService CacheService,
) fiber.Handler {
	h := deleteArticlePage{
		tm:                   tm,
		articleRepository:    articleRepository,
		articleTagRepository: articleTagRepository,
		cacheService:         cacheService,
	}

	return h.handler()
}

func (h deleteArticlePage) handler() fiber.Handler {
	return func(fctx *fiber.Ctx) error {
		ctx := fctx.Context()
		lang := i18n.LanguageFromContext(fctx)
		articleID, err := request.ConvertToUint64(fctx, "id")
		if err != nil {
			logger.Error(ctx, customErrors.Wrap(err, "delete article page: can't get id from request").Error())
			return err
		}

		article, err := h.getArticle(ctx, articleID)
		if err != nil {
			return err // logging in the getArticle method
		}

		if fctx.Method() == fiber.MethodPost {
			err = h.tm.ReadCommitted(ctx, func(ctx context.Context) error {
				txErr := h.articleTagRepository.DeleteByArticleID(ctx, articleID)
				if txErr != nil {
					return customErrors.Wrap(txErr, "can't delete tags")
				}

				txErr = h.articleRepository.Delete(ctx, articleID)
				if txErr != nil {
					return customErrors.Wrap(txErr, "can't delete article")
				}

				return nil
			})

			if err != nil {
				logger.Error(ctx, customErrors.Wrap(err, "delete article page").Error())
				return err
			}

			articleLang := string(i18n.LanguageFromID(article.Language))
			h.cacheService.Delete(handler.ArticleCacheKey + article.URL + articleLang)
			h.cacheService.Delete(handler.RecentArticlesCacheKey + articleLang)
			h.cacheService.Delete(handler.UsedTagsCacheKey + articleLang)
			h.cacheService.Delete(handler.AllPreviewArticlesCacheKey + articleLang)

			return fctx.Redirect("/admin")
		}

		return fctx.Render("admin/article_delete", fiber.Map{
			"lang":    lang,
			"section": "article",
			"article": article.Title,
		}, "admin/_layout")
	}
}

func (h deleteArticlePage) getArticle(ctx context.Context, id uint64) (*model.Article, error) {
	article, err := h.articleRepository.GetByID(ctx, id)
	if err != nil {
		if db.IsNotFoundError(err) {
			return nil, fiber.ErrNotFound
		}

		logger.Error(ctx, customErrors.Wrap(err, "delete article page: can't get article").Error())
		return nil, err
	}

	return article, nil
}
