package controllers

import (
	"fmt"
	"net/http"
	"strconv"
	"time"

	"learnsteam/learsteam-quiz-api/internal/models"
	"learnsteam/learsteam-quiz-api/internal/services"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

type ProgramController interface {
	List(*gin.Context)
	Find(*gin.Context)
	Create(*gin.Context)
	Update(*gin.Context)
}

type programController struct {
	service services.ProgramService
}

func NewProgramController(service services.ProgramService) ProgramController {
	return &programController{
		service: service,
	}
}

// Program List
//
// @Summary			프로그램 목록 가져오기
// @Description	퀴즈 프로그램 목록을 가져옵니다.
// @Tags 				Program
//
// @Accept json
// @Produce json
//
// @Param tag query string false "태그"
// @Param q query string false "검색어"
// @Param page query int false "페이지"
// @Param limit query int false "페이지 사이즈"
//
// @Success 200 {object} models.ProgramListResponse
// @Router /program  [get]
func (controller *programController) List(c *gin.Context) {
	tag := c.DefaultQuery("tag", "")
	q := c.DefaultQuery("q", "")
	page, err := strconv.Atoi(c.DefaultQuery("page", "1"))
	if err != nil {
		fmt.Println("error : page")
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	limit, err := strconv.Atoi(c.DefaultQuery("limit", "10"))
	if err != nil {
		fmt.Println("error : limit")
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	result, err := controller.service.List(q, tag, page, limit)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	totalNumber, err := controller.service.Total(q, tag)
	if err != nil {
		fmt.Println("error : list")
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	totalPage := int64(totalNumber/int64(limit) + 1)

	response := models.ProgramListResponse{
		Data:      *result,
		Total:     totalPage,
		Page:      page,
		TotalPage: totalPage,
		PageSize:  limit,
	}

	c.JSON(http.StatusOK, response)
}

// Get program
//
// @Summary 		퀴즈 프로그램 가져오기
// @Description	ID로 퀴즈 프로그램을 가져옵니다.
// @Tags 				Program
//
// @Accept json
// @Produce json
//
// @Param id path string true "퀴즈 프로그램 ID"
//
// @Success 200 {object} models.ProgramResponse
// @Router /program/{id} [get]
func (controller *programController) Find(c *gin.Context) {
	id := c.Param("id")

	result, err := controller.service.Find(id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, result)
}

// Create Program
//
// @Summary 		퀴즈 프로그램 생성
// @Description	퀴즈 프로그램을 만듭니다.
// @Tags 				Program
//
// @Accept json
// @Produce json
//
// @Param subject body string true "프로그램 제목"
// @Param course body string true "프로그램 코스"
// @Param content body string true "프로그램 내용"
// @Param tag body []string true "프로그램 태그"
// @Param status body string true "프로그램 상태 on 또는 off"
// @Param publish_at body string true "프로그램 발행 날짜"
//
// @Success 200 {object} models.ProgramResponse
// @Router /program [post]
func (controller *programController) Create(c *gin.Context) {
	var request models.ProgramRequest
	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	publish_at, err := time.Parse("2006-01-02", request.PublishAt)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	program := &models.Program{
		ID:        uuid.NewString(),
		Subject:   request.Subject,
		Course:    request.Course,
		Content:   request.Content,
		Tag:       request.Tag,
		Tags:      request.Tag.String(),
		PublishAt: publish_at,
		Status:    request.Status,
		CreatedAt: time.Now(),
		UpdatedAt: time.Now(),
	}

	fmt.Println("publish_at", program.PublishAt)
	result, err := controller.service.Create(program)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, result)
}

// Update Program
//
// @Summary			퀴즈 프로그램 수정
// @Description 퀴즈 프로그램을 수정합니다.
// @Tags 				Program
//
// @Accept json
// @Produce json
//
// @Param subject body string true "프로그램 제목"
// @Param course body string true "프로그램 코스"
// @Param content body string true "프로그램 내용"
// @Param tag body []string true "프로그램 태그"
// @Param status body string true "프로그램 상태 on 또는 off"
// @Param publish_at body string true "프로그램 발행 날짜"
//
// @Success 200 {object} models.ProgramResponse
// @Router /program [put]
func (controller *programController) Update(c *gin.Context) {
	id := c.Param("id")
	var request models.ProgramRequest
	if err := c.ShouldBindJSON(&request); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	program, err := controller.service.Find(id)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	publish_at, err := time.Parse("2006-01-02", request.PublishAt)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	program.Subject = request.Subject
	program.Course = request.Course
	program.Content = request.Content
	program.Tag = request.Tag
	program.Tags = request.Tag.String()
	program.PublishAt = publish_at
	program.Status = request.Status
	program.UpdatedAt = time.Now()

	result, err := controller.service.Update(program)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, result)
}
