package web

import (
	"log"
	"net"
	"net/http"
	"strconv"

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

type Env struct {
	db core.DB
}

func logged(handler http.HandlerFunc) http.HandlerFunc {
	return func(writer http.ResponseWriter, req *http.Request) {
		log.Printf("%s %s", req.Method, req.URL.Path)
		handler(writer, req)
	}
}

func handleFunc(
	pattern string,
	handler http.HandlerFunc,
	middlewares ...func(http.HandlerFunc) http.HandlerFunc,
) {
	for _, middleware := range middlewares {
		handler = middleware(handler)
	}
	http.HandleFunc(pattern, handler)
}

func RunServer(db core.DB, addr string, port string) error {
	env := &Env{db}
	bind := net.JoinHostPort(addr, port)

	handleFunc("GET    /", env.getRoot, env.authed, logged)
	handleFunc("GET    /style.css", env.getStyle, logged)
	handleFunc("GET    /htmx.org@2.0.4.js", env.getScript, logged)
	handleFunc("POST   /login", env.login, logged)
	handleFunc("POST   /source", env.addSource, env.authed, logged)
	handleFunc("GET    /source/{source}", env.getSource, env.authed, logged)
	handleFunc("GET    /source/{source}/edit", env.getEditSource, env.authed, logged)
	handleFunc("POST   /source/{source}/edit", env.editSource, env.authed, logged)
	handleFunc("POST   /source/{source}/fetch", env.fetchSource, env.authed, logged)
	handleFunc("GET    /channel/", env.getChannels, env.authed, logged)
	handleFunc("POST   /channel/", env.editChannel, env.authed, logged)
	handleFunc("DELETE /channel/", env.editChannel, env.authed, logged)
	handleFunc("GET    /channel/{channel}", env.getChannel, env.authed, logged)
	handleFunc("POST   /item", env.addItem, env.authed, logged)
	handleFunc("GET    /item/{source}/{id}", env.getItem, env.authed, logged)
	handleFunc("DELETE /item/{source}/{id}", env.deleteItem, env.authed, logged)
	handleFunc("POST   /item/{source}/{id}/action/{action}", env.doAction, env.authed, logged)
	handleFunc("PATCH  /item/{source}/{id}/punt", env.puntItem, env.authed, logged)
	handleFunc("POST   /mass-deactivate", env.massDeactivate, env.authed, logged)

	log.Printf("listening on %s", bind)
	return http.ListenAndServe(bind, nil)
}

func getQueryInt(req *http.Request, name string, def int) int {
	s := req.URL.Query().Get(name)
	i, err := strconv.Atoi(s)
	if err != nil {
		return def
	} else {
		return i
	}
}