package controllers

import (
	"errors"
	"net/http"
	"net/url"
	"strconv"
	"strings"
	"time"

	"fotbal-club/internal/config"
	"fotbal-club/internal/services"
	"fotbal-club/pkg/logger"
	"github.com/gin-gonic/gin"
)

type UmamiController struct {
	umamiService *services.UmamiService
}

func NewUmamiController() *UmamiController {
	return &UmamiController{
		umamiService: services.NewUmamiService(),
	}
}

// resolveWebsiteID attempts to obtain a usable Umami website ID for requests.
// Preference order:
//   1. Cached value in configuration.
//   2. Match by configured frontend domain.
//   3. Fall back to the first website available in Umami.
func (uc *UmamiController) resolveWebsiteID() (string, error) {
	if id := strings.TrimSpace(config.AppConfig.UmamiWebsiteID); id != "" {
		logger.Info("Using cached Umami website ID: %s", id)
		return id, nil
	}

	logger.Info("UMAMI_WEBSITE_ID is empty, attempting to auto-detect...")

	if frontendURL := strings.TrimSpace(config.AppConfig.FrontendBaseURL); frontendURL != "" {
		parsed, err := url.Parse(frontendURL)
		if err != nil {
			logger.Warn("Failed to parse FRONTEND_BASE_URL '%s': %v", frontendURL, err)
		} else if host := parsed.Hostname(); host != "" {
			logger.Info("Attempting to find Umami website by domain: %s", host)
			id, err := uc.umamiService.FindWebsiteIDByDomain(host)
			if err != nil {
				logger.Warn("Failed to find website by domain '%s': %v", host, err)
			} else if id != "" {
				logger.Info("Found Umami website by domain match: %s", id)
				config.AppConfig.UmamiWebsiteID = id
				return id, nil
			} else {
				logger.Info("No Umami website found with domain '%s'", host)
			}
		}
	}

	logger.Info("Falling back to first available Umami website...")
	id, err := uc.umamiService.GetDefaultWebsiteID()
	if err != nil {
		return "", err
	}

	config.AppConfig.UmamiWebsiteID = id
	logger.Info("Auto-detected and cached Umami website ID: %s", id)
	return id, nil
}

// GetUmamiConfig returns the Umami configuration for the frontend
func (uc *UmamiController) GetUmamiConfig(c *gin.Context) {
	if config.AppConfig.UmamiURL == "" || config.AppConfig.UmamiUsername == "" || config.AppConfig.UmamiPassword == "" {
		reason := "No website ID configured - run initial setup"
		switch {
		case config.AppConfig.UmamiURL == "":
			reason = "UMAMI_URL not set in .env"
		case config.AppConfig.UmamiUsername == "":
			reason = "UMAMI_USERNAME not set in .env"
		case config.AppConfig.UmamiPassword == "":
			reason = "UMAMI_PASSWORD not set in .env"
		}
		logger.Warn("Umami not configured: %s", reason)
		c.JSON(http.StatusOK, gin.H{
			"enabled":    false,
			"website_id": "",
			"script_url": "",
			"reason":     reason,
		})
		return
	}

	websiteID, err := uc.resolveWebsiteID()
	if err != nil {
		if errors.Is(err, services.ErrUmamiNoWebsites) {
			c.JSON(http.StatusOK, gin.H{
				"enabled":    false,
				"website_id": "",
				"script_url": "",
				"reason":     "No websites found in Umami",
			})
		} else {
			logger.Error("Failed to resolve Umami website ID: %v", err)
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to resolve Umami website ID"})
		}
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"enabled":    true,
		"website_id": websiteID,
		"script_url": config.AppConfig.UmamiURL + "/script.js",
	})
}

// InitializeUmamiSetup is called during initial setup (no auth required).
// It auto-detects the domain from the Host header (works with Cloudflare Tunnel).
func (uc *UmamiController) InitializeUmamiSetup(c *gin.Context) {
	if config.AppConfig.UmamiWebsiteID != "" {
		c.JSON(http.StatusOK, gin.H{
			"message":    "Umami already configured",
			"website_id": config.AppConfig.UmamiWebsiteID,
		})
		return
	}

	var payload struct {
		Name string `json:"name"`
	}

	if err := c.ShouldBindJSON(&payload); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request payload"})
		return
	}

	if payload.Name == "" {
		payload.Name = "Fotbal Club"
	}

	domain := c.Request.Host
	if i := strings.Index(domain, ":"); i >= 0 {
		domain = domain[:i]
	}

	logger.Info("Initializing Umami website: name='%s', domain='%s'", payload.Name, domain)

	websiteID, err := uc.umamiService.EnsureWebsite(payload.Name, domain)
	if err != nil {
		logger.Error("Failed to create Umami website: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create Umami website: " + err.Error()})
		return
	}

	config.AppConfig.UmamiWebsiteID = websiteID
	logger.Info("Umami website created successfully: ID=%s", websiteID)

	c.JSON(http.StatusOK, gin.H{
		"message":    "Umami initialized successfully",
		"website_id": websiteID,
		"script_url": config.AppConfig.UmamiURL + "/script.js",
		"domain":     domain,
	})
}

// InitializeUmami sets up Umami tracking (admin endpoint with manual domain).
func (uc *UmamiController) InitializeUmami(c *gin.Context) {
	if config.AppConfig.UmamiWebsiteID != "" {
		c.JSON(http.StatusOK, gin.H{
			"message":    "Umami already configured",
			"website_id": config.AppConfig.UmamiWebsiteID,
		})
		return
	}

	var payload struct {
		Name   string `json:"name"`
		Domain string `json:"domain"`
	}

	if err := c.ShouldBindJSON(&payload); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request payload"})
		return
	}

	if payload.Name == "" || payload.Domain == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Name and domain are required"})
		return
	}

	websiteID, err := uc.umamiService.EnsureWebsite(payload.Name, payload.Domain)
	if err != nil {
		logger.Error("Failed to create Umami website: %v", err)
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create Umami website: " + err.Error()})
		return
	}

	config.AppConfig.UmamiWebsiteID = websiteID
	c.JSON(http.StatusOK, gin.H{
		"message":    "Umami initialized successfully",
		"website_id": websiteID,
		"script_url": config.AppConfig.UmamiURL + "/script.js",
	})
}

// GetStats returns analytics stats from Umami
func (uc *UmamiController) GetStats(c *gin.Context) {
	// Check if Umami is configured
	if config.AppConfig.UmamiURL == "" || config.AppConfig.UmamiUsername == "" || config.AppConfig.UmamiPassword == "" {
		logger.Warn("Umami not configured - UMAMI_URL='%s', username empty=%v, password empty=%v", 
			config.AppConfig.UmamiURL, 
			config.AppConfig.UmamiUsername == "", 
			config.AppConfig.UmamiPassword == "")
		c.JSON(http.StatusOK, gin.H{})
		return
	}

	websiteID, err := uc.resolveWebsiteID()
	if err != nil {
		if errors.Is(err, services.ErrUmamiNoWebsites) {
			logger.Warn("No Umami websites found in instance at %s - returning empty stats", config.AppConfig.UmamiURL)
			c.JSON(http.StatusOK, gin.H{})
		} else {
			logger.Error("Failed to resolve Umami website ID: %v", err)
			c.JSON(http.StatusOK, gin.H{})
		}
		return
	}
	logger.Info("Using Umami website ID: %s", websiteID)

	// Get time range from query params (default to last 30 days)
	days := 30
	if d := c.Query("days"); d != "" {
		if parsed, err := strconv.Atoi(d); err == nil && parsed >= 0 {
			days = parsed
		}
	}
	
	// Calculate time range
	var startAt, endAt int64
	endDate := time.Now()
	if days == 0 {
		// Today: from midnight to now
		startDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, endDate.Location())
		startAt = startDate.Unix() * 1000
		endAt = endDate.Unix() * 1000
	} else {
		// Other ranges: from X days ago to now
		startDate := endDate.AddDate(0, 0, -days)
		startAt = startDate.Unix() * 1000
		endAt = endDate.Unix() * 1000
	}

	stats, err := uc.umamiService.GetWebsiteStats(websiteID, startAt, endAt)
	if err != nil {
		logger.Error("Failed to get Umami stats for websiteID=%s (days=%d): %v", websiteID, days, err)
		// Return empty stats instead of error
		c.JSON(http.StatusOK, gin.H{})
		return
	}

	logger.Info("Successfully fetched Umami stats for websiteID=%s (days=%d)", websiteID, days)
	c.JSON(http.StatusOK, stats)
}

// GetMetrics returns specific metrics from Umami (pageviews, referrers, browsers, os, devices, countries, events)
func (uc *UmamiController) GetMetrics(c *gin.Context) {
	// Check if Umami is configured
	if config.AppConfig.UmamiURL == "" || config.AppConfig.UmamiUsername == "" || config.AppConfig.UmamiPassword == "" {
		logger.Warn("Umami not configured - returning empty metrics")
		c.JSON(http.StatusOK, []map[string]interface{}{})
		return
	}

	websiteID, err := uc.resolveWebsiteID()
	if err != nil {
		if errors.Is(err, services.ErrUmamiNoWebsites) {
			logger.Warn("No Umami websites found - returning empty metrics")
			c.JSON(http.StatusOK, []map[string]interface{}{})
		} else {
			logger.Error("Failed to resolve Umami website ID: %v", err)
			c.JSON(http.StatusOK, []map[string]interface{}{})
		}
		return
	}

	metricType := c.Param("type")
	if metricType == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Metric type is required"})
		return
	}

	days := 30
	if d := c.Query("days"); d != "" {
		if parsed, err := strconv.Atoi(d); err == nil && parsed >= 0 {
			days = parsed
		}
	}

	// Calculate time range
	var startAt, endAt int64
	endDate := time.Now()
	if days == 0 {
		// Today: from midnight to now
		startDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, endDate.Location())
		startAt = startDate.Unix() * 1000
		endAt = endDate.Unix() * 1000
	} else {
		// Other ranges: from X days ago to now
		startDate := endDate.AddDate(0, 0, -days)
		startAt = startDate.Unix() * 1000
		endAt = endDate.Unix() * 1000
	}

	metrics, err := uc.umamiService.GetWebsiteMetrics(websiteID, metricType, startAt, endAt)
	if err != nil {
		logger.Error("Failed to get Umami metrics (websiteID=%s, type=%s, days=%d): %v", websiteID, metricType, days, err)
		// Return empty metrics instead of error
		c.JSON(http.StatusOK, []map[string]interface{}{})
		return
	}

	logger.Info("Successfully fetched %d Umami metrics (websiteID=%s, type=%s, days=%d)", len(metrics), websiteID, metricType, days)
	c.JSON(http.StatusOK, metrics)
}

// GetPageviews returns pageviews data over time from Umami
func (uc *UmamiController) GetPageviews(c *gin.Context) {
	// Check if Umami is configured
	if config.AppConfig.UmamiURL == "" || config.AppConfig.UmamiUsername == "" || config.AppConfig.UmamiPassword == "" {
		logger.Warn("Umami not configured - returning empty pageviews")
		c.JSON(http.StatusOK, []map[string]interface{}{})
		return
	}

	websiteID, err := uc.resolveWebsiteID()
	if err != nil {
		if errors.Is(err, services.ErrUmamiNoWebsites) {
			logger.Warn("No Umami websites found - returning empty pageviews")
			c.JSON(http.StatusOK, []map[string]interface{}{})
		} else {
			logger.Error("Failed to resolve Umami website ID: %v", err)
			c.JSON(http.StatusOK, []map[string]interface{}{})
		}
		return
	}

	days := 30
	if d := c.Query("days"); d != "" {
		if parsed, err := strconv.Atoi(d); err == nil && parsed >= 0 {
			days = parsed
		}
	}

	// Determine time unit based on range
	unit := "day"
	if days == 0 || days == 1 {
		unit = "hour"
	} else if days <= 90 {
		unit = "day"
	} else {
		unit = "month"
	}

	// Calculate time range
	var startAt, endAt int64
	endDate := time.Now()
	if days == 0 {
		// Today: from midnight to now
		startDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, endDate.Location())
		startAt = startDate.Unix() * 1000
		endAt = endDate.Unix() * 1000
	} else {
		// Other ranges: from X days ago to now
		startDate := endDate.AddDate(0, 0, -days)
		startAt = startDate.Unix() * 1000
		endAt = endDate.Unix() * 1000
	}

	logger.Info("Fetching pageviews: websiteID=%s, days=%d, unit=%s, startAt=%d, endAt=%d", websiteID, days, unit, startAt, endAt)

	pageviews, err := uc.umamiService.GetWebsitePageviews(websiteID, startAt, endAt, unit)
	if err != nil {
		logger.Error("Failed to get Umami pageviews (websiteID=%s, days=%d, unit=%s): %v", websiteID, days, unit, err)
		// Return empty array instead of error to prevent frontend crash
		c.JSON(http.StatusOK, []map[string]interface{}{})
		return
	}

	c.JSON(http.StatusOK, pageviews)
}
