package seo

import (
	"encoding/json"
	"encoding/xml"
	"fmt"
	"net/http"
	"path"
	"time"

	"github.com/pocketbase/pocketbase"
	"github.com/pocketbase/pocketbase/core"
	"github.com/pocketbase/pocketbase/tools/router"
)

type MenuRecord struct {
	Active          bool   `json:"active"`
	CollectionID    string `json:"collectionId"`
	CollectionName  string `json:"collectionName"`
	Created         string `json:"created"`
	ID              string `json:"id"`
	IDLang          string `json:"id_lang"`
	IDPage          string `json:"id_page"`
	IDParent        string `json:"id_parent"`
	IsDefault       bool   `json:"is_default"`
	IsRoot          bool   `json:"is_root"`
	LinkRewrite     string `json:"link_rewrite"`
	LinkTitle       string `json:"link_title"`
	MetaDescription string `json:"meta_description"`
	MetaTitle       string `json:"meta_title"`
	Name            string `json:"name"`
	PageName        string `json:"page_name"`
	PositionID      int    `json:"position_id"`
	Updated         string `json:"updated"`
	Url             string `json:"url"`
}

type UrlSet struct {
	XMLName xml.Name `xml:"urlset"`
	Xmlns   string   `xml:"xmlns,attr"`
	Urls    []Url    `xml:"url"`
}

type Url struct {
	Loc        string `xml:"loc"`
	LastMod    string `xml:"lastmod,omitempty"`
	ChangeFreq string `xml:"changefreq,omitempty"`
	Priority   string `xml:"priority,omitempty"`
}

func ServeFeeds(app *pocketbase.PocketBase, se *core.ServeEvent) *router.Route[*core.RequestEvent] {
	return se.Router.GET("/feeds/{lang}/sitemap.xml", func(e *core.RequestEvent) error {

		lang := e.Request.PathValue("lang")

		urls, err := getLocations(app, lang)
		if err != nil {
			return err
		}

		xx := UrlSet{
			Xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9",
			Urls:  urls,
		}

		bytes, err := xml.MarshalIndent(xx, "", "  ")
		if err != nil {
			return err
		}

		e.Response.Header().Add("content-type", "text/xml")
		return e.String(http.StatusOK, xml.Header+string(bytes))
	})
}

func getLocations(app *pocketbase.PocketBase, lang string) ([]Url, error) {
	records, err := app.FindRecordsByFilter("menu_view", fmt.Sprintf("id_lang='%s'&&active=true", lang), "position_id", 200, 0)
	if err != nil {
		return nil, err
	}

	baseUrl, err := getBaseUrl(app)
	if err != nil {
		return nil, err
	}

	locations := []Url{}
	lastMod := time.Now().Add(time.Hour * 24 * 7 * -1).Format("2006-01-02")

	for _, r := range records {
		rec := MenuRecord{}
		x, _ := r.MarshalJSON()
		json.Unmarshal(x, &rec)
		if rec.IsRoot {
			continue
		}
		if len(rec.Url) > 0 {
			continue
		}
		if rec.IsDefault {

			locations = append(locations, Url{
				Loc:        baseUrl + path.Join(lang),
				LastMod:    lastMod,
				ChangeFreq: "weekly",
				Priority:   "1.0",
			})
		}
		locations = append(locations, Url{
			Loc:        baseUrl + path.Join(lang, rec.IDPage, rec.LinkRewrite),
			LastMod:    lastMod,
			ChangeFreq: "weekly",
			Priority:   "1.0",
		})
	}

	return locations, nil
}

type BaseUrl struct {
	BaseURL string `json:"baseUrl"`
}

func getBaseUrl(app *pocketbase.PocketBase) (string, error) {
	record, err := app.FindFirstRecordByFilter("settings", "key='baseUrl'", nil)
	if err != nil {
		return "", err
	}

	settings := BaseUrl{}
	json.Unmarshal([]byte(record.GetString("value")), &settings)

	if err != nil {
		return "", err
	}

	return settings.BaseURL, nil
}

type SitemapIndex struct {
	XMLName  xml.Name  `xml:"sitemapindex"`
	Xmlns    string    `xml:"xmlns,attr"`
	Sitemaps []Sitemap `xml:"sitemap"`
}

// Sitemap represents each <sitemap> entry
type Sitemap struct {
	Loc     string `xml:"loc"`
	LastMod string `xml:"lastmod"`
}

func ServeFeedsIndex(app *pocketbase.PocketBase, se *core.ServeEvent) *router.Route[*core.RequestEvent] {
	return se.Router.GET("/feeds/index.xml", func(e *core.RequestEvent) error {
		index, err := makeSiteMapIndex(app)
		if err != nil {
			return err
		}

		bytes, err := xml.MarshalIndent(index, "", "  ")
		if err != nil {
			return err
		}

		e.Response.Header().Add("content-type", "text/xml")
		return e.String(http.StatusOK, xml.Header+string(bytes))
	})
}

func makeSiteMapIndex(app *pocketbase.PocketBase) (*SitemapIndex, error) {
	index := &SitemapIndex{
		Xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9",
	}

	bseUrl, err := getBaseUrl(app)
	if err != nil {
		return nil, err
	}

	langs, err := app.FindRecordsByFilter("lang", "active=true", "", 200, 0)
	if err != nil {
		return index, err
	}

	lastMod := time.Now().Add(time.Hour * 24 * 7 * -1).Format("2006-01-02")

	for _, l := range langs {
		index.Sitemaps = append(index.Sitemaps, Sitemap{
			Loc:     bseUrl + path.Join("feeds/", l.Id, "sitemap.xml"),
			LastMod: lastMod,
		})
	}

	return index, nil
}
