package controller

import (
	"campaign-pool-be/app/module/chat/request"
	"campaign-pool-be/app/module/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"
)

type chatScheduleController struct {
	chatScheduleService service.ChatScheduleService
}

type ChatScheduleController interface {
	// Chat Schedule endpoints
	GetAllChatSchedules(c *fiber.Ctx) error
	GetChatScheduleByID(c *fiber.Ctx) error
	CreateChatSchedule(c *fiber.Ctx) error
	UpdateChatSchedule(c *fiber.Ctx) error
	DeleteChatSchedule(c *fiber.Ctx) error

	// Additional schedule endpoints
	GetUpcomingSchedules(c *fiber.Ctx) error
	GetSchedulesByStatus(c *fiber.Ctx) error
	SendScheduleReminder(c *fiber.Ctx) error
}

func NewChatScheduleController(chatScheduleService service.ChatScheduleService) ChatScheduleController {
	return &chatScheduleController{
		chatScheduleService: chatScheduleService,
	}
}

// GetAllChatSchedules - Get all chat schedules for a user
// @Summary      Get all chat schedules
// @Description  API for getting all chat schedules for authenticated user
// @Tags         Chat Schedule
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        chatSessionId query string false "Chat Session ID"
// @Param        status query string false "Schedule status (scheduled, ongoing, completed, cancelled)"
// @Param        createdBy query string false "Created by user ID"
// @Param        dateFrom query string false "Date from (YYYY-MM-DD)"
// @Param        dateTo query string false "Date to (YYYY-MM-DD)"
// @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       /chat/schedules [get]
func (_i *chatScheduleController) GetAllChatSchedules(c *fiber.Ctx) error {
	paginate, err := paginator.Paginate(c)
	if err != nil {
		return err
	}

	authToken := c.Get("Authorization")

	reqContext := request.ChatScheduleQueryRequestContext{
		ChatSessionID: c.Query("chatSessionId"),
		Status:        c.Query("status"),
		CreatedBy:     c.Query("createdBy"),
		DateFrom:      c.Query("dateFrom"),
		DateTo:        c.Query("dateTo"),
	}
	req := reqContext.ToParamRequest()
	req.Pagination = *paginate

	chatSchedules, paging, err := _i.chatScheduleService.GetAllChatSchedules(authToken, req)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Chat schedules successfully retrieved"},
		Data:     chatSchedules,
		Meta:     paging,
	})
}

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

	authToken := c.Get("Authorization")

	chatSchedule, err := _i.chatScheduleService.GetChatScheduleByID(authToken, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Chat schedule successfully retrieved"},
		Data:     chatSchedule,
	})
}

// CreateChatSchedule - Create chat schedule
// @Summary      Create chat schedule
// @Description  API for creating a new chat schedule
// @Tags         Chat Schedule
// @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.ChatScheduleCreateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /chat/schedules [post]
func (_i *chatScheduleController) CreateChatSchedule(c *fiber.Ctx) error {
	authToken := c.Get("Authorization")

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

	dataResult, err := _i.chatScheduleService.CreateChatSchedule(authToken, *req)
	if err != nil {
		return err
	}

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

// UpdateChatSchedule - Update chat schedule
// @Summary      Update chat schedule
// @Description  API for updating chat schedule (only creator can update)
// @Tags         Chat Schedule
// @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        id path int true "Chat Schedule ID"
// @Param        payload body request.ChatScheduleUpdateRequest true "Required payload"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /chat/schedules/{id} [put]
func (_i *chatScheduleController) UpdateChatSchedule(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authToken := c.Get("Authorization")

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

	err = _i.chatScheduleService.UpdateChatSchedule(authToken, uint(id), *req)
	if err != nil {
		return err
	}

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

// DeleteChatSchedule - Delete chat schedule
// @Summary      Delete chat schedule
// @Description  API for deleting chat schedule (only creator can delete)
// @Tags         Chat Schedule
// @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        id path int true "Chat Schedule ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /chat/schedules/{id} [delete]
func (_i *chatScheduleController) DeleteChatSchedule(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authToken := c.Get("Authorization")

	err = _i.chatScheduleService.DeleteChatSchedule(authToken, uint(id))
	if err != nil {
		return err
	}

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

// GetUpcomingSchedules - Get upcoming schedules for a user
// @Summary      Get upcoming schedules
// @Description  API for getting upcoming chat schedules for authenticated user
// @Tags         Chat Schedule
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        limit query int false "Limit number of results" default(10)
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /chat/schedules/upcoming [get]
func (_i *chatScheduleController) GetUpcomingSchedules(c *fiber.Ctx) error {
	authToken := c.Get("Authorization")

	limit := 10 // default limit
	if limitStr := c.Query("limit"); limitStr != "" {
		if parsedLimit, err := strconv.Atoi(limitStr); err == nil && parsedLimit > 0 {
			limit = parsedLimit
		}
	}

	chatSchedules, err := _i.chatScheduleService.GetUpcomingSchedules(authToken, limit)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Upcoming chat schedules successfully retrieved"},
		Data:     chatSchedules,
	})
}

// GetSchedulesByStatus - Get schedules by status
// @Summary      Get schedules by status
// @Description  API for getting chat schedules by status
// @Tags         Chat Schedule
// @Security     Bearer
// @Param        Authorization header string false "Insert your access token" default(Bearer <Add access token here>)
// @Param        status path string true "Schedule status (scheduled, ongoing, completed, cancelled)"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /chat/schedules/status/{status} [get]
func (_i *chatScheduleController) GetSchedulesByStatus(c *fiber.Ctx) error {
	status := c.Params("status")
	if status == "" {
		return utilRes.Resp(c, utilRes.Response{
			Success:  false,
			Messages: utilRes.Messages{"Status parameter is required"},
		})
	}

	authToken := c.Get("Authorization")

	chatSchedules, err := _i.chatScheduleService.GetSchedulesByStatus(authToken, status)
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Chat schedules by status successfully retrieved"},
		Data:     chatSchedules,
	})
}

// SendScheduleReminder - Send reminder for a schedule
// @Summary      Send schedule reminder
// @Description  API for sending reminder for a chat schedule (only creator can send)
// @Tags         Chat Schedule
// @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        id path int true "Chat Schedule ID"
// @Success      200  {object}  response.Response
// @Failure      400  {object}  response.BadRequestError
// @Failure      401  {object}  response.UnauthorizedError
// @Failure      500  {object}  response.InternalServerError
// @Router       /chat/schedules/{id}/reminder [post]
func (_i *chatScheduleController) SendScheduleReminder(c *fiber.Ctx) error {
	id, err := strconv.ParseUint(c.Params("id"), 10, 0)
	if err != nil {
		return err
	}

	authToken := c.Get("Authorization")

	err = _i.chatScheduleService.SendScheduleReminder(authToken, uint(id))
	if err != nil {
		return err
	}

	return utilRes.Resp(c, utilRes.Response{
		Success:  true,
		Messages: utilRes.Messages{"Schedule reminder successfully sent"},
	})
}
