package controller

import (
	"campaign-pool-be/app/module/ai_chat/request"
	"campaign-pool-be/app/module/ai_chat/service"
	"campaign-pool-be/utils/paginator"
	utilRes "campaign-pool-be/utils/response"
	utilVal "campaign-pool-be/utils/validator"
	"strconv"

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

type aiChatController struct {
	aiChatService service.AIChatService
	Log           zerolog.Logger
}

type AIChatController interface {
	// AI Chat Sessions
	GetUserSessions(c *fiber.Ctx) error
	GetSession(c *fiber.Ctx) error
	CreateSession(c *fiber.Ctx) error
	UpdateSession(c *fiber.Ctx) error
	DeleteSession(c *fiber.Ctx) error

	// AI Chat Messages
	GetSessionMessages(c *fiber.Ctx) error
	SendMessage(c *fiber.Ctx) error
	UpdateMessage(c *fiber.Ctx) error
	DeleteMessage(c *fiber.Ctx) error

	// AI Chat Logs
	GetUserLogs(c *fiber.Ctx) error
	GetLog(c *fiber.Ctx) error
}

func NewAIChatController(aiChatService service.AIChatService, log zerolog.Logger) AIChatController {
	return &aiChatController{
		aiChatService: aiChatService,
		Log:           log,
	}
}

// Get User Sessions
// @Summary      Get user AI chat sessions
// @Description  API for getting all AI chat sessions for authenticated user
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        req query request.AIChatSessionsQueryRequest 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       /ai-chat/sessions [get]
func (_i *aiChatController) GetUserSessions(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	reqContext := request.AIChatSessionsQueryRequestContext{
		IsActive: c.Query("isActive"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	sessionsData, paging, err := _i.aiChatService.GetUserSessions(authHeader, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat sessions successfully retrieved"},
		Data:     sessionsData,
		Meta:     paging,
	})
}

// Get Session
// @Summary      Get one AI chat session
// @Description  API for getting one AI chat session
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        id path int true "Session ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/sessions/{id} [get]
func (_i *aiChatController) GetSession(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	sessionData, err := _i.aiChatService.GetSession(authHeader, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat session successfully retrieved"},
		Data:     sessionData,
	})
}

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

	authHeader := c.Get("Authorization")

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

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

// Update Session
// @Summary      Update AI chat session
// @Description  API for update AI chat session
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        X-Csrf-Token header string false "Insert the X-Csrf-Token"
// @Param        id path int true "Session ID"
// @Param        payload body request.AIChatSessionsUpdateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/sessions/{id} [put]
func (_i *aiChatController) UpdateSession(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

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

	authHeader := c.Get("Authorization")

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

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat session successfully updated"},
	})
}

// Delete Session
// @Summary      Delete AI chat session
// @Description  API for delete AI chat session
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        id path int true "Session ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/sessions/{id} [delete]
func (_i *aiChatController) DeleteSession(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

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

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat session successfully deleted"},
	})
}

// Get Session Messages
// @Summary      Get AI chat session messages
// @Description  API for getting all messages in an AI chat session
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        id path int true "Session ID"
// @Param        req query request.AIChatMessagesQueryRequest 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       /ai-chat/sessions/{id}/messages [get]
func (_i *aiChatController) GetSessionMessages(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	reqContext := request.AIChatMessagesQueryRequestContext{}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	messagesData, paging, err := _i.aiChatService.GetSessionMessages(authHeader, uint(id), req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat messages successfully retrieved"},
		Data:     messagesData,
		Meta:     paging,
	})
}

// Send Message
// @Summary      Send message to AI chat session
// @Description  API for sending a message to an AI chat session
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        payload body request.AIChatMessagesCreateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/sessions/messages [post]
func (_i *aiChatController) SendMessage(c *fiber.Ctx) error {
	req := new(request.AIChatMessagesCreateRequest)
	if err := utilVal.ParseAndValidate(c, req); err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

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

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Message successfully sent"},
		Data:     dataResult,
	})
}

// Update Message
// @Summary      Update AI chat message
// @Description  API for update AI chat message
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        messageId path int true "Message ID"
// @Param        payload body request.AIChatMessagesUpdateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/sessions/messages/{messageId} [put]
func (_i *aiChatController) UpdateMessage(c *fiber.Ctx) error {
	messageId, err := strconv.ParseUint(c.Params("messageId"), 10, 0)
	if err != nil {
		return err
	}

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

	authHeader := c.Get("Authorization")

	err = _i.aiChatService.UpdateMessage(authHeader, uint(messageId), *req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat message successfully updated"},
	})
}

// Delete Message
// @Summary      Delete AI chat message
// @Description  API for delete AI chat message
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        X-Csrf-Token header string true "Insert the X-Csrf-Token"
// @Param        messageId path int true "Message ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/sessions/messages/{messageId} [delete]
func (_i *aiChatController) DeleteMessage(c *fiber.Ctx) error {
	messageId, err := strconv.ParseUint(c.Params("messageId"), 10, 0)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	err = _i.aiChatService.DeleteMessage(authHeader, uint(messageId))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat message successfully deleted"},
	})
}

// Get User Logs
// @Summary      Get user AI chat logs
// @Description  API for getting all AI chat logs for authenticated user
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        req query request.AIChatLogsQueryRequest 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       /ai-chat/logs [get]
func (_i *aiChatController) GetUserLogs(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	reqContext := request.AIChatLogsQueryRequestContext{
		LogType: c.Query("logType"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = paginate

	logsData, paging, err := _i.aiChatService.GetUserLogs(authHeader, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat logs successfully retrieved"},
		Data:     logsData,
		Meta:     paging,
	})
}

// Get Log
// @Summary      Get one AI chat log
// @Description  API for getting one AI chat log
// @Tags         AI Chat
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        id path int true "Log ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /ai-chat/logs/{id} [get]
func (_i *aiChatController) GetLog(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authHeader := c.Get("Authorization")

	logData, err := _i.aiChatService.GetLog(authHeader, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"AI chat log successfully retrieved"},
		Data:     logData,
	})
}
