package controller

import (
	"narasi-ahli-be/app/module/research_journals/request"
	"narasi-ahli-be/app/module/research_journals/service"
	"narasi-ahli-be/utils/paginator"
	utilRes "narasi-ahli-be/utils/response"
	utilVal "narasi-ahli-be/utils/validator"
	"strconv"

	"github.com/gofiber/fiber/v2"
)

type researchJournalsController struct {
	researchJournalsService service.ResearchJournalsService
}

type ResearchJournalsController interface {
	All(c *fiber.Ctx) error
	Show(c *fiber.Ctx) error
	Save(c *fiber.Ctx) error
	Update(c *fiber.Ctx) error
	Delete(c *fiber.Ctx) error
}

func NewResearchJournalsController(researchJournalsService service.ResearchJournalsService) ResearchJournalsController {
	return &researchJournalsController{
		researchJournalsService: researchJournalsService,
	}
}

// All Research Journals
// @Summary      Get all Research Journals
// @Description  API for getting all Research Journals for authenticated user
// @Tags         Research Journals
// @Security     Bearer
// @Param        req query request.ResearchJournalsQueryRequest false "query parameters"
// @Param        req query paginator.Pagination false "pagination parameters"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /research-journals [get]
func (_i *researchJournalsController) All(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	reqContext := request.ResearchJournalsQueryRequestContext{
		UserID:         c.Query("userId"),

		JournalTitle:  c.Query("journalTitle"),
		Publisher:     c.Query("publisher"),
		PublishedYear: c.Query("publishedYear"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	// Handle publishedYear filter
	if publishedYearStr := c.Query("publishedYear"); publishedYearStr != "" {
		if publishedYear, err := strconv.Atoi(publishedYearStr); err == nil {
			req.PublishedYear = &publishedYear
		}
	}

	journalsData, paging, err := _i.researchJournalsService.All(req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Research journals list successfully retrieved"},
		Data:     journalsData,
		Meta:     paging,
	})
}

// Show Research Journal
// @Summary      Get one Research Journal
// @Description  API for getting one Research Journal
// @Tags         Research Journals
// @Security     Bearer
// @Param        id path int true "Research Journal ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /research-journals/{id} [get]
func (_i *researchJournalsController) Show(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	journalData, err := _i.researchJournalsService.Show(authHeader, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Research journal successfully retrieved"},
		Data:     journalData,
	})
}

// Save Research Journal
// @Summary      Create Research Journal
// @Description  API for create Research Journal
// @Tags         Research Journals
// @Security     Bearer
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        payload body request.ResearchJournalsCreateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /research-journals [post]
func (_i *researchJournalsController) Save(c *fiber.Ctx) error {
	req := new(request.ResearchJournalsCreateRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	dataResult, err := _i.researchJournalsService.Save(authHeader, *req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Research journal successfully created"},
		Data:     dataResult,
	})
}

// Update Research Journal
// @Summary      Update Research Journal
// @Description  API for update Research Journal
// @Tags         Research Journals
// @Security     Bearer
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        id path int true "Research Journal ID"
// @Param        payload body request.ResearchJournalsUpdateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /research-journals/{id} [put]
func (_i *researchJournalsController) Update(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	req := new(request.ResearchJournalsUpdateRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	err = _i.researchJournalsService.Update(authHeader, uint(id), *req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Research journal successfully updated"},
	})
}

// Delete Research Journal
// @Summary      Delete Research Journal
// @Description  API for delete Research Journal
// @Tags         Research Journals
// @Security     Bearer
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        id path int true "Research Journal ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /research-journals/{id} [delete]
func (_i *researchJournalsController) Delete(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	err = _i.researchJournalsService.Delete(authHeader, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Research journal successfully deleted"},
	})
}
