// internal/article/load.go
package article

// internal/article/load.go  (gekürzt)

import (
	"bytes"
	"encoding/json"
	"fmt"
	"html/template"
	"io/fs"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	md "github.com/gomarkdown/markdown"
	"github.com/gomarkdown/markdown/html"
)

// LoadDir liest alle *.html und *.md unter root/content,
// parst Front‑Matter (JSON‑Kommentar in der 1. Zeile) und liefert []Article.
func LoadDir(root string) ([]Article, error) {
	var out []Article
	seen := make(map[string]bool) // Duplikats‑Check

	mdRenderer := html.NewRenderer(html.RendererOptions{
		Flags: html.CommonFlags | html.HrefTargetBlank,
	})

	err := filepath.WalkDir(root, func(path string, d fs.DirEntry, walkErr error) error {
		if walkErr != nil {
			return walkErr
		}
		if d.IsDir() {
			return nil
		}

		ext := strings.ToLower(filepath.Ext(path))
		if ext != ".md" && ext != ".html" {
			return nil // uninteressante Datei
		}

		raw, err := os.ReadFile(path)
		if err != nil {
			return fmt.Errorf("read %s: %w", path, err)
		}

		parts := bytes.SplitN(raw, []byte("\n"), 2)
		if len(parts) < 2 {
			return fmt.Errorf("%s: missing front‑matter", path)
		}

		headerJSON, err := extractJSONHeader(parts[0])
		if err != nil {
			return fmt.Errorf("%s: %w", path, err)
		}

		var meta struct {
			Title string `json:"title"`
			Date  string `json:"date"`
			Slug  string `json:"slug"`
			Cover string `json:"cover"`
		}
		if err := json.Unmarshal(headerJSON, &meta); err != nil {
			return fmt.Errorf("%s: %w", path, err)
		}

		// Fallback‑Slug aus Dateinamen
		if meta.Slug == "" {
			meta.Slug = strings.TrimSuffix(filepath.Base(path), ext)
		}
		if seen[meta.Slug] {
			return fmt.Errorf("%s: duplicate slug %q", path, meta.Slug)
		}
		seen[meta.Slug] = true

		body := parts[1]
		if ext == ".md" {
			body = md.ToHTML(body, nil, mdRenderer) // frischer Parser pro Call
		}

		date, err := time.Parse("2006-01-02", meta.Date)
		if err != nil {
			return fmt.Errorf("%s: parse date: %w", path, err)
		}

		out = append(out, Article{
			Title: meta.Title,
			Slug:  meta.Slug,
			Date:  date,
			Cover: meta.Cover,
			Body:  template.HTML(body),
		})
		return nil
	})
	if err != nil {
		return nil, err
	}

	sort.Slice(out, func(i, j int) bool { return out[i].Date.After(out[j].Date) })
	return out, nil
}

// ---------- NEU ----------
type StaticPage struct {
	Title string
	Slug  string
	Body  template.HTML
}

// helper.go – einmal zentral verwenden
func extractJSONHeader(line []byte) ([]byte, error) {
	s := strings.TrimSpace(string(line))
	s = strings.TrimPrefix(s, "<!--")

	// alles bis zum ersten "-->" abschneiden
	if idx := strings.Index(s, "-->"); idx != -1 {
		s = s[:idx]
	}
	s = strings.TrimSpace(s)

	// optional: falls doch kein JSON, besserer Fehler
	if !strings.HasPrefix(s, "{") {
		return nil, fmt.Errorf("no JSON front‑matter found")
	}
	return []byte(s), nil
}

// LoadStatic liest alle .md/.html‑Dateien unter dir und liefert sie als Map[slug]StaticPage.
func LoadStatic(dir string) (map[string]StaticPage, error) {
	pages := make(map[string]StaticPage)

	entries, err := os.ReadDir(dir)
	if err != nil {
		return nil, err
	}

	for _, e := range entries {
		if e.IsDir() {
			continue
		}
		ext := filepath.Ext(e.Name())
		if ext != ".md" && ext != ".html" {
			continue // unbekanntes Format
		}

		path := filepath.Join(dir, e.Name())
		raw, err := os.ReadFile(path)
		if err != nil {
			return nil, fmt.Errorf("read %s: %w", path, err)
		}

		// Front‑Matter (erste Zeile) herauslösen
		parts := bytes.SplitN(raw, []byte("\n"), 2)
		if len(parts) < 2 {
			return nil, fmt.Errorf("%s: missing front‑matter", path)
		}

		headerJSON, err := extractJSONHeader(parts[0])
		if err != nil {
			return nil, fmt.Errorf("%s: %w", path, err)
		}

		var meta struct {
			Title string `json:"title"`
			Slug  string `json:"slug"`
		}
		if err := json.Unmarshal(headerJSON, &meta); err != nil {
			return nil, fmt.Errorf("%s: %w", path, err)
		}

		// Fallback: Slug aus Dateinamen ableiten, falls im Header leer
		if meta.Slug == "" {
			meta.Slug = strings.TrimSuffix(e.Name(), ext)
		}
		if _, dup := pages[meta.Slug]; dup {
			return nil, fmt.Errorf("%s: duplicate slug %q", path, meta.Slug)
		}

		body := parts[1]
		if ext == ".md" {
			body = md.ToHTML(body, nil, nil) // eigener Parser je Aufruf
		}

		pages[meta.Slug] = StaticPage{
			Title: meta.Title,
			Slug:  meta.Slug,
			Body:  template.HTML(body),
		}
	}
	return pages, nil
}
