package controller

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

	"github.com/gin-gonic/gin"
	"gitlab.ost.ch/marketminds/marketminds/pkg/api"
	"gitlab.ost.ch/marketminds/marketminds/pkg/api/response"
	datasql "gitlab.ost.ch/marketminds/marketminds/pkg/data/sql"
	"gitlab.ost.ch/marketminds/marketminds/pkg/services"
)

type Controller struct {
	service *services.Service
}

func NewController(db *datasql.SqlInstance) *Controller {
	return &Controller{service: services.NewService(db)}
}

func (c *Controller) ImportJob() {
	locked, err := c.service.AcquireLock(666)
	if err != nil {
		fmt.Printf("Error acquiring lock: %v\n", err)
		return
	}
	if !locked {
		fmt.Printf("Lock already acquired.\n")
		return
	}
	defer c.service.ReleaseLock(666)

	fmt.Printf("Importing news from news channels.\n")

	err = c.service.ImportNewsItems()
	if err != nil {
		fmt.Printf("Error importing news from news channels.")
	}

	err = c.service.ImportSentimentResults()
	if err != nil {
		fmt.Printf("Error importing sentiment results.")
	}

	err = c.service.ImportNERResults()
	if err != nil {
		fmt.Printf("Error importing NER results.")
	}

	fmt.Printf("Imported successfully.\n")
}

func (c *Controller) Status(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	// check grpc connection
	aiServiceStatus := "UP"
	conn, err := api.CreateGrpcConnection()
	if err != nil {
		aiServiceStatus = "DOWN"
	} else {
		aiServiceStatus = conn.GetState().String()
	}

	response.SetServiceStatus(aiServiceStatus)
}

func (c *Controller) Import(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	err := c.service.ImportNewsItems()
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error importing news from news channels.")
		return
	}

	err = c.service.ImportSentimentResults()
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error importing sentiment results.")
		return
	}

	err = c.service.ImportNERResults()
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error importing NER results.")
		return
	}

	response.Info(http.StatusOK, "Imported successfully")
}

func (c *Controller) GetAllNewsChannel(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	newsChannels, err := c.service.GetAllNewsChannels()
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error getting news channels.")
		return
	}

	response.SetNewsChannels(newsChannels...)
}

func (c *Controller) GetNewsChannelById(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	id := ctx.Param("id")
	newsChannel, err := c.service.GetNewsChannelById(id)
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error getting news channel with id "+id+".")
		return
	}

	response.SetNewsChannel(newsChannel)
}

func (c *Controller) GetNews(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	page, _ := strconv.Atoi(ctx.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(ctx.DefaultQuery("limit", "20"))
	offset := (page - 1) * pageSize

	newsItems, err := c.service.GetNews(pageSize, offset)
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error getting news.")
		return
	}

	response.SetPagination(newsItems, page, pageSize)
}

func (c *Controller) GetNewsItemById(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	id := ctx.Param("id")
	newsItem, err := c.service.GetNewsItemById(id)
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error getting news item with id "+id+".")
		return
	}

	response.SetNewsItem(newsItem)
}

func (c *Controller) GetAllNamedEntities(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	namedEntities, err := c.service.GetAllNamedEntities()
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error getting named entities.")
		return
	}

	response.SetNamedEntities(namedEntities...)
}

func (c *Controller) GetNamedEntity(ctx *gin.Context) {
	response := response.NewResponse(ctx)
	defer response.Respond()

	id := ctx.Param("id")
	namedEntity, err := c.service.GetNamedEntity(id)
	if err != nil {
		response.Error(http.StatusInternalServerError, "Error getting named entity with id "+id+".")
		return
	}

	response.SetNamedEntity(namedEntity)
}
