package html

import (
	"embed"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"log"
	"time"

	"github.com/Jaculabilis/intake/core"
)

func rawHtml(str string) template.HTML {
	return template.HTML(str)
}

func dateFormat(tm time.Time) string {
	return tm.Format(time.DateTime)
}

func tsToDate(t int) time.Time {
	return time.Unix(int64(t), 0).UTC()
}

func until(tm time.Time) string {
	now := time.Now() // TODO pass this value in
	dur := tm.Sub(now).Round(time.Second)

	var format string
	if dur < 0 {
		format = "%s ago"
		dur = dur.Abs()
	} else {
		format = "in %s"
	}

	var length string
	if dur.Hours() > 24 {
		length = fmt.Sprintf("%dd", int(dur.Hours()/24))
	} else {
		length = dur.String()
	}

	return fmt.Sprintf(format, length)
}

func massDeactivateVals(items []core.Item) string {
	var shorts []string
	for _, item := range items {
		shorts = append(shorts, core.FormatAsShort(item))
	}
	massDeac := struct {
		Items []string `json:"items"`
	}{shorts}
	vals, err := json.Marshal(massDeac)
	if err != nil {
		log.Printf("error serializing mass deactivate list: %v", err)
	}
	return string(vals)
}

func page(i int, delta int) int {
	i = i + delta
	if i < 1 {
		return 1
	}
	return i
}

var funcs = template.FuncMap{
	"raw":          rawHtml,
	"dateFormat":   dateFormat,
	"tsToDate":     tsToDate,
	"until":        until,
	"massDeacVars": massDeactivateVals,
	"page":         page,
}

//go:embed intake.css
var Stylesheet []byte

//go:embed htmx.org@2.0.4.js
var Htmx []byte

//go:embed *.html
var templates embed.FS

func load(files ...string) *template.Template {
	files = append([]string{"layout.html"}, files...)
	return template.Must(template.New("layout.html").Funcs(funcs).ParseFS(templates, files...))
}

var home = load("home.html")

type ChannelData struct {
	Name   string
	Active int
}

type SourceData struct {
	Name string
}

type HomeData struct {
	Channels []ChannelData
	Sources  []SourceData
}

func Home(writer io.Writer, data HomeData) {
	if err := home.Execute(writer, data); err != nil {
		log.Printf("error: failed to render home: %v", err)
	}
}

var feed = load("feed.html", "item.html")

type FeedData struct {
	Items      []core.Item
	ShowHidden int
	Page       int
	Count      int
}

func Feed(writer io.Writer, data FeedData) {
	if err := feed.Execute(writer, data); err != nil {
		log.Printf("error: failed to render feed: %v", err)
	}
}

var item = load("itemPage.html", "item.html")

type ItemData struct {
	Item core.Item
}

func Item(writer io.Writer, data ItemData) {
	if err := item.Execute(writer, data); err != nil {
		log.Printf("error: failed to render item: %v", err)
	}
}

var login = load("login.html")

type LoginData struct {
	Error string
}

func Login(writer io.Writer, data LoginData) {
	err := login.Execute(writer, data)
	if err != nil {
		log.Printf("error: failed to render login: %v", err)
	}
}

var fetch = load("fetch.html")

type FetchData struct {
	Source  string
	Added   int
	Updated int
	Deleted int
	Items   []core.Item
}

func Fetch(writer io.Writer, data FetchData) {
	if err := fetch.Execute(writer, data); err != nil {
		log.Printf("error: failed to render fetch: %v", err)
	}
}