package frontend

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"

	b "streifling.com/jason/cpolis/cmd/backend"
)

func serveBase64Image(c *b.Config, filename string) (string, error) {
	file := c.PicsDir + "/" + filename

	img, err := os.Open(file)
	if err != nil {
		return "", fmt.Errorf("error opening file %v: %v", file, err)
	}
	defer img.Close()

	imgBytes, err := io.ReadAll(img)
	if err != nil {
		return "", fmt.Errorf("error turning %v into bytes: %v", file, err)
	}

	return base64.StdEncoding.EncodeToString(imgBytes), nil
}

func UploadImage(c *b.Config, s *b.CookieStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if _, err := getSession(w, r, c, s); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if err := r.ParseMultipartForm(10 << 20); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		file, _, err := r.FormFile("article-image")
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		defer file.Close()

		filename, err := b.SaveImage(c, file)
		if err != nil {
			if err == b.ErrUnsupportedFormat {
				http.Error(w, "Das Dateiformat wird nicht unterstützt.", http.StatusBadRequest)
				return
			}
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		url := c.Domain + "/image/serve/" + filename
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(url)
	}
}

func UploadIssueImage(c *b.Config, s *b.CookieStore) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		session, err := getSession(w, r, c, s)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if err := r.ParseMultipartForm(10 << 20); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}

		file, _, err := r.FormFile("issue-image")
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		defer file.Close()

		filename, err := b.SaveImage(c, file)
		if err != nil {
			if err == b.ErrUnsupportedFormat {
				http.Error(w, "Das Dateiformat wird nicht unterstützt.", http.StatusBadRequest)
				return
			}
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		session.Values["issue-image"] = filename
		if err = session.Save(r, w); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		w.WriteHeader(http.StatusOK)
	}
}

func UploadBanner(c *b.Config, s *b.CookieStore, fileKey, htmlFile, htmlTemplate string) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if _, err := getSession(w, r, c, s); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		file, _, err := r.FormFile(fileKey)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusBadRequest)
			return
		}
		defer file.Close()

		filename, err := b.SaveImage(c, file)
		if err != nil {
			if err == b.ErrUnsupportedFormat {
				http.Error(w, "Das Dateiformat wird nicht unterstützt.", http.StatusBadRequest)
				return
			}
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		base64Img, err := serveBase64Image(c, filename)
		if err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		data := new(struct {
			BannerImage string
			URL         string
		})

		data.BannerImage = base64Img
		data.URL = c.Domain + "/image/serve/" + filename

		tmpl, err := template.ParseFiles(c.WebDir + "/templates/" + htmlFile)
		if err = template.Must(tmpl, err).ExecuteTemplate(w, htmlTemplate, data); err != nil {
			log.Println(err)
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
	}
}