package controllers

import (
    "encoding/json"
    "net/http"
    "os"
    "path/filepath"
    "strconv"
    "strings"
    "time"

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

// PrefetchController exposes admin endpoints to inspect and trigger background prefetch cycles.
type PrefetchController struct{}

// isDuringMatchFromCache checks cached FACR JSONs to determine if a match is ongoing.
func isDuringMatchFromCache(cacheDir string) bool {
    now := time.Now()
    parseDT := func(s string) (time.Time, bool) {
        s = strings.TrimSpace(s)
        if s == "" { return time.Time{}, false }
        layouts := []string{"02.01.2006 15:04", time.RFC3339, "2006-01-02 15:04"}
        for _, layout := range layouts {
            if t, err := time.ParseInLocation(layout, s, time.Local); err == nil { return t, true }
        }
        return time.Time{}, false
    }
    within := func(ts time.Time) bool {
        start := ts.Add(-15 * time.Minute)
        end := ts.Add(150 * time.Minute)
        return now.After(start) && now.Before(end)
    }
    type flatMatch struct {
        DateTime string `json:"date_time"`
        Date     string `json:"date"`
        Time     string `json:"time"`
        Kickoff  string `json:"kickoff"`
    }
    check := func(b []byte) bool {
        if len(b) == 0 { return false }
        var payload struct {
            Competitions []struct { Matches []struct {
                DateTime string `json:"date_time"`
                Date string `json:"date"`
                Time string `json:"time"`
                Kickoff string `json:"kickoff"`
            } `json:"matches"` } `json:"competitions"`
            Matches []flatMatch `json:"matches"`
        }
        _ = json.Unmarshal(b, &payload)
        for _, c := range payload.Competitions {
            for _, m := range c.Matches {
                var ts time.Time; var ok bool
                if m.DateTime != "" { ts, ok = parseDT(m.DateTime) } else if m.Date != "" || m.Time != "" { ts, ok = parseDT(strings.TrimSpace(m.Date+" "+m.Time)) } else if m.Kickoff != "" { ts, ok = parseDT(m.Kickoff) }
                if ok && within(ts) { return true }
            }
        }
        for _, m := range payload.Matches {
            var ts time.Time; var ok bool
            if m.DateTime != "" { ts, ok = parseDT(m.DateTime) } else if m.Date != "" || m.Time != "" { ts, ok = parseDT(strings.TrimSpace(m.Date+" "+m.Time)) } else if m.Kickoff != "" { ts, ok = parseDT(m.Kickoff) }
            if ok && within(ts) { return true }
        }
        return false
    }
    files := []string{ filepath.Join(cacheDir, "facr_club_info.json"), filepath.Join(cacheDir, "facr_tables.json") }
    for _, p := range files {
        if b, err := os.ReadFile(p); err == nil {
            if check(b) { return true }
        }
    }
    return false
}

func NewPrefetchController() *PrefetchController { return &PrefetchController{} }

// Status returns info about the last fetch and the approximate next run time.
// GET /api/v1/admin/prefetch/status
func (pc *PrefetchController) Status(c *gin.Context) {
    if c.GetString("userRole") != "admin" {
        c.JSON(http.StatusForbidden, gin.H{"error": "Access denied"})
        return
    }

    cacheDir := filepath.Join("cache", "prefetch")
    metaPath := filepath.Join(cacheDir, "meta.json")
    var lastUpdated string
    if b, err := os.ReadFile(metaPath); err == nil {
        var m struct{ LastUpdated string `json:"lastUpdated"` }
        if json.Unmarshal(b, &m) == nil {
            lastUpdated = m.LastUpdated
        }
    }

    // Determine configured interval
    interval := 30 * time.Minute
    if v := strings.TrimSpace(os.Getenv("PREFETCH_INTERVAL_MINUTES")); v != "" {
        if mins, err := strconv.Atoi(v); err == nil && mins > 0 {
            interval = time.Duration(mins) * time.Minute
        }
    }

    // Fast mode if during match
    fast := isDuringMatchFromCache(cacheDir)
    next := time.Now().Add(interval)
    if fast {
        next = time.Now().Add(5 * time.Minute)
    }

    c.JSON(http.StatusOK, gin.H{
        "lastUpdated":      lastUpdated,
        "intervalMinutes":  int(interval / time.Minute),
        "fastMode":         fast,
        "nextApproximate":  next.Format(time.RFC3339),
    })
}

// Trigger starts an immediate prefetch cycle (best effort)
// POST /api/v1/admin/prefetch/trigger
func (pc *PrefetchController) Trigger(c *gin.Context) {
    if c.GetString("userRole") != "admin" {
        c.JSON(http.StatusForbidden, gin.H{"error": "Access denied"})
        return
    }
    // Resolve the base URL similar to main.go logic
    base := os.Getenv("PREFETCH_TARGET")
    if strings.TrimSpace(base) == "" {
        port := strings.TrimSpace(os.Getenv("PORT"))
        if port == "" { port = "8080" }
        base = "http://127.0.0.1:" + port + "/api/v1"
    }
    go func() {
        // fire-and-forget
        services.PrefetchOnce(base)
        // Additionally trigger an immediate Zonerama refresh based on cached settings
        // This ensures the admin trigger updates the gallery right away.
        cacheDir := filepath.Join("cache", "prefetch")
        b, err := os.ReadFile(filepath.Join(cacheDir, "settings.json"))
        if err == nil {
            var s struct{
                ZoneramaURL string `json:"zonerama_url"`
                GalleryURL  string `json:"gallery_url"`
            }
            if jsonErr := json.Unmarshal(b, &s); jsonErr == nil {
                link := strings.TrimSpace(s.ZoneramaURL)
                if link == "" { link = strings.TrimSpace(s.GalleryURL) }
                if link != "" {
                    _ = services.RefreshZoneramaNow(link)
                }
            }
        }
        // Regenerate flat gallery files from existing albums
        _ = services.RegenerateFlatGalleryFiles()
    }()
    c.JSON(http.StatusOK, gin.H{"message": "Prefetch started"})
}
