package parser

import (
	"encoding/xml"
	"fmt"
	"io"
	"net/http"
	"time"

	"github.com/jackc/pgx/v5"
	sql "gitlab.ost.ch/marketminds/marketminds/pkg/data/sql"
	entity "gitlab.ost.ch/marketminds/marketminds/pkg/entity"
)

type Parser struct {
	repo *sql.SqlRepository
}

func NewParser(s *sql.SqlInstance) *Parser {
	return &Parser{
		repo: sql.NewSqlRepository(s),
	}
}

type RSS struct {
	XMLName xml.Name `xml:"rss"`
	Channel Channel  `xml:"channel"`
}

type Channel struct {
	XMLName xml.Name `xml:"channel"`
	Items   []Item   `xml:"item"`
}

type Item struct {
	XMLName        xml.Name       `xml:"item"`
	Title          string         `xml:"title"`
	Description    string         `xml:"description"`
	MediaThumbnail MediaThumbnail `xml:"http://search.yahoo.com/mrss/ thumbnail"`
	Link           string         `xml:"link"`
	PubDate        string         `xml:"pubDate"`
	Category       string         `xml:"category"`
	Guid           string         `xml:"guid"`
	Enclosure      Enclosure      `xml:"enclosure"`
	MediaCopyright MediaCopyright `xml:"http://search.yahoo.com/mrss/ copyright"`
	MediaTitle     MediaTitle     `xml:"http://search.yahoo.com/mrss/ title"`
}

type MediaThumbnail struct {
	XMLName xml.Name `xml:"http://search.yahoo.com/mrss/ thumbnail"`
	Url     string   `xml:"url,attr"`
}

type Enclosure struct {
	XMLName xml.Name `xml:"enclosure"`
	Url     string   `xml:"url,attr"`
}

type MediaCopyright struct {
	XMLName   xml.Name `xml:"http://search.yahoo.com/mrss/ copyright"`
	Copyright string   `xml:",chardata"`
}

type MediaTitle struct {
	XMLName xml.Name `xml:"http://search.yahoo.com/mrss/ title"`
	Title   string   `xml:",chardata"`
}

func isNewerThan(date time.Time, specifiedDate time.Time) bool {
	return date.After(specifiedDate)
}

func (p *Parser) Parse(newsChannel *entity.NewsChannel) {
	resp, err := http.Get(newsChannel.RssUrl)
	if err != nil {
		fmt.Println("Error fetching RSS feed:", err)
		return
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Error reading response body:", err)
		return
	}

	var rss RSS
	err = xml.Unmarshal(body, &rss)
	if err != nil {
		fmt.Println("Error parsing RSS XML:", err)
		return
	}

	lastEntry, err := p.repo.GetLastNewsItemEntryDate(int64(newsChannel.Id))
	if err != nil {
		fmt.Println("Error fetching last entry date:", err)
	}

	for i, item := range rss.Channel.Items {
		p.processItem(item, lastEntry, newsChannel, i)
	}
}

func (p *Parser) processItem(item Item, lastEntry time.Time, newsChannel *entity.NewsChannel, i int) {
	pubDate, err := time.Parse(time.RFC1123, item.PubDate)
	if err != nil {
		// handle error
		fmt.Println("Error parsing date:", err)
	}

	fmt.Println("parser", pubDate, " - last", lastEntry)

	_, err = p.repo.GetNewsItemByGuid(item.Guid)

	if err == pgx.ErrNoRows && (isNewerThan(pubDate, lastEntry) || lastEntry.IsZero()) {

		var newsItem = entity.NewNewsItem(
			0,
			item.Title,
			item.Description,
			item.MediaThumbnail.Url,
			item.Link,
			pubDate,
			item.Category,
			item.Guid,
			item.Enclosure.Url,
			item.MediaCopyright.Copyright,
			item.MediaTitle.Title,
			"",
			time.Now(),
			int64(newsChannel.Id),
		)

		// Save the news item
		_, err := p.repo.CreateNewsItem(newsItem)

		if err != nil {
			fmt.Println("Error saving news item:", err)
		}
	}
}
