package analyzer

import (
	"fmt"
	"strings"
	"time"

	"gitlab.ost.ch/marketminds/marketminds/pkg/api"
	sql "gitlab.ost.ch/marketminds/marketminds/pkg/data/sql"
	"gitlab.ost.ch/marketminds/marketminds/pkg/entity"
	"gitlab.ost.ch/marketminds/marketminds/pkg/utils"
	"google.golang.org/grpc"
)

type Analyzer struct {
	repo *sql.SqlRepository
	conn *grpc.ClientConn
}

func NewAnalyzer(repo *sql.SqlRepository) *Analyzer {
	return &Analyzer{repo: repo}
}

func (a *Analyzer) BuildConnection() (*grpc.ClientConn, error) {
	conn, err := api.CreateGrpcConnection()
	if err != nil {
		fmt.Println("Error creating grpc connection:", err)
		return nil, err
	}
	a.conn = conn
	return conn, err
}

func (a *Analyzer) AnalyzeSentimentResult(newsItem *entity.NewsItem) error {
	analyzeSentiment := api.NewAnalyzeSentiment(a.conn)

	responseTitle, titleErr := analyzeSentiment.Analyze(newsItem.Title)
	if titleErr != nil {
		fmt.Println("Error analyzing title:", titleErr)
		return titleErr
	}

	responseDescription, descErr := analyzeSentiment.Analyze(newsItem.Description.String)
	if descErr != nil {
		fmt.Println("Error analyzing description:", descErr)
		return descErr
	}

	sentiment := entity.NewSentimentResult(
		0,
		responseTitle.PositiveScore,
		responseTitle.NeutralScore,
		responseTitle.NegativeScore,
		responseDescription.PositiveScore,
		responseDescription.NeutralScore,
		responseDescription.NegativeScore,
		time.Now(),
		newsItem.Id,
	)

	// print the sentiment
	fmt.Println("Sentiment for title: ", responseTitle.PositiveScore, responseTitle.NeutralScore, responseTitle.NegativeScore)
	fmt.Println("Sentiment for description: ", responseDescription, responseDescription.NeutralScore, responseDescription.NegativeScore)

	a.repo.CreateSentimentResult(sentiment)

	return nil
}

func (a *Analyzer) AnalyzeNERResult(newsItem *entity.NewsItem) error {
	analyzeNER := api.NewAnalyzeNER(a.conn)

	// concatenate title and description to analyze
	analyzeString := newsItem.Title + " " + newsItem.Description.String

	response, err := analyzeNER.Analyze(analyzeString)
	if err != nil {
		fmt.Println("Error analyzing NER:", err)
		return err
	}

	currentTime := time.Now()

	entityFullName := ""
	reversed := utils.Reverse(response.Entities)
	for _, nEntityResponse := range reversed {
		fmt.Println("Entity: ", nEntityResponse.Name, nEntityResponse.Type, nEntityResponse.Saliency)

		separator := " "
		if strings.Contains(nEntityResponse.Name, "##") {
			separator = ""
			nEntityResponse.Name = strings.Replace(nEntityResponse.Name, "##", "", -1)
		}
		entityFullName = separator + nEntityResponse.Name + entityFullName
		if nEntityResponse.Type[0] == 'I' {
			continue
		}
		entityFullName = strings.TrimPrefix(entityFullName, " ")

		namedEntity := entity.NewNamedEntity(
			entityFullName,
			nEntityResponse.Type,
			currentTime,
		)

		insertedEntityName, err := a.repo.GetOrCreateNamedEntity(namedEntity)
		if err != nil {
			fmt.Println("Error getting or creating named entity:", err)
			break
		}

		nerResult := entity.NewNERResult(
			0,
			currentTime,
			newsItem.Id,
			insertedEntityName,
		)
		fmt.Println("Named Entity: ", nerResult)

		a.repo.CreateNERResult(nerResult)
		fmt.Println("******* Named Entity created *********")
		entityFullName = ""
	}

	return nil
}
