package controllers

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

	"fotbal-club/internal/models"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// SitemapController handles sitemap generation
type SitemapController struct {
	DB *gorm.DB
}

// URLSet represents the root sitemap element
type URLSet struct {
	XMLName xml.Name `xml:"urlset"`
	XMLNS   string   `xml:"xmlns,attr"`
	URLs    []URL    `xml:"url"`
}

// URL represents a single URL entry in sitemap
type URL struct {
	Loc        string  `xml:"loc"`
	LastMod    string  `xml:"lastmod,omitempty"`
	ChangeFreq string  `xml:"changefreq,omitempty"`
	Priority   float32 `xml:"priority,omitempty"`
}

// GetSitemap generates and returns sitemap.xml
func (sc *SitemapController) GetSitemap(c *gin.Context) {
	// Get base URL from request or settings
	scheme := "https"
	if c.Request.TLS == nil && c.Request.Header.Get("X-Forwarded-Proto") != "https" {
		scheme = "http"
	}
	baseURL := fmt.Sprintf("%s://%s", scheme, c.Request.Host)

	// Initialize sitemap
	sitemap := URLSet{
		XMLNS: "http://www.sitemaps.org/schemas/sitemap/0.9",
		URLs:  []URL{},
	}

	// Add homepage
	sitemap.URLs = append(sitemap.URLs, URL{
		Loc:        baseURL + "/",
		ChangeFreq: "daily",
		Priority:   1.0,
	})

	// Add static pages
	staticPages := []struct {
		path     string
		freq     string
		priority float32
	}{
		{"/blog", "daily", 0.9},
		{"/zapasy", "daily", 0.9},
		{"/tabulky", "weekly", 0.8},
		{"/hraci", "weekly", 0.8},
		{"/o-klubu", "monthly", 0.7},
		{"/kontakt", "monthly", 0.6},
		{"/galerie", "weekly", 0.7},
		{"/videa", "weekly", 0.7},
		{"/sponzori", "monthly", 0.5},
		{"/kalendar", "weekly", 0.7},
		{"/aktivity", "weekly", 0.7},
		{"/obleceni", "monthly", 0.6},
		{"/ankety", "weekly", 0.6},
	}

	for _, page := range staticPages {
		sitemap.URLs = append(sitemap.URLs, URL{
			Loc:        baseURL + page.path,
			ChangeFreq: page.freq,
			Priority:   page.priority,
		})
	}

	// Add published articles
	var articles []models.Article
	if err := sc.DB.Where("published = ?", true).
		Order("published_at DESC, created_at DESC").
		Limit(1000). // Reasonable limit
		Find(&articles).Error; err == nil {
		for _, article := range articles {
			lastMod := article.UpdatedAt.Format("2006-01-02")
			if !article.PublishedAt.IsZero() {
				lastMod = article.PublishedAt.Format("2006-01-02")
			}

			// Add both slug and ID URLs
			if article.Slug != "" {
				sitemap.URLs = append(sitemap.URLs, URL{
					Loc:        baseURL + "/articles/slug/" + article.Slug,
					LastMod:    lastMod,
					ChangeFreq: "weekly",
					Priority:   0.8,
				})
			}
			sitemap.URLs = append(sitemap.URLs, URL{
				Loc:        baseURL + fmt.Sprintf("/articles/%d", article.ID),
				LastMod:    lastMod,
				ChangeFreq: "weekly",
				Priority:   0.7,
			})
		}
	}

	// Add players
	var players []models.Player
	if err := sc.DB.Order("created_at DESC").Limit(500).Find(&players).Error; err == nil {
		for _, player := range players {
			sitemap.URLs = append(sitemap.URLs, URL{
				Loc:        baseURL + fmt.Sprintf("/hraci/%d", player.ID),
				LastMod:    player.UpdatedAt.Format("2006-01-02"),
				ChangeFreq: "monthly",
				Priority:   0.6,
			})
		}
	}

	// Generate XML
	output, err := xml.MarshalIndent(sitemap, "", "  ")
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate sitemap"})
		return
	}

	// Set headers and return
	c.Header("Content-Type", "application/xml; charset=utf-8")
	c.Header("Cache-Control", "public, max-age=3600") // Cache for 1 hour
	c.String(http.StatusOK, xml.Header+string(output))
}

// GetRobotsTxt returns robots.txt with sitemap reference
func (sc *SitemapController) GetRobotsTxt(c *gin.Context) {
	scheme := "https"
	if c.Request.TLS == nil && c.Request.Header.Get("X-Forwarded-Proto") != "https" {
		scheme = "http"
	}
	baseURL := fmt.Sprintf("%s://%s", scheme, c.Request.Host)

	// Check if indexing is disabled in settings
	var settings models.Settings
	allowIndex := true
	if err := sc.DB.First(&settings).Error; err == nil {
		allowIndex = settings.EnableIndexing
	}

	var robots strings.Builder
	robots.WriteString("# robots.txt for " + c.Request.Host + "\n")
	robots.WriteString("# Generated: " + time.Now().Format(time.RFC1123) + "\n\n")

	if !allowIndex {
		// Block all robots if indexing disabled
		robots.WriteString("User-agent: *\n")
		robots.WriteString("Disallow: /\n")
	} else {
		// Allow most content, block admin and API
		robots.WriteString("User-agent: *\n")
		robots.WriteString("Disallow: /admin/\n")
		robots.WriteString("Disallow: /api/\n")
		robots.WriteString("Disallow: /login\n")
		robots.WriteString("Disallow: /setup\n")
		robots.WriteString("Allow: /\n\n")

		// Add sitemap reference
		robots.WriteString("Sitemap: " + baseURL + "/sitemap.xml\n")
	}

	c.Header("Content-Type", "text/plain; charset=utf-8")
	c.Header("Cache-Control", "public, max-age=86400") // Cache for 24 hours
	c.String(http.StatusOK, robots.String())
}
