package handlers

import (
	"archive/zip"
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"github.com/gabriel-vasile/mimetype"
	"github.com/valkey-io/valkey-go"
)

func DownloadFile(client valkey.Client) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		upload_id := r.PathValue("upload_id")
		if upload_id == "" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}
		file_id := r.PathValue("file_id")
		if file_id == "" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		files_json, err := client.Do(r.Context(),
			client.B().Get().Key(upload_id).Build()).ToString()
		if err != nil {
			http.Error(w, err.Error(), http.StatusNotFound)
			return
		}
		var files []string
		err = json.Unmarshal([]byte(files_json), &files)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		found := false
		found_id := 0
		for i, id := range files {
			if id == file_id {
				found = true
				found_id = i
			}
		}
		if !found {
			http.Error(w, "not found", http.StatusNotFound)
			return

		}

		file := files[found_id]

		filename, err := client.Do(r.Context(), client.B().Get().Key(file+":filename").Build()).ToString()
		if err != nil {
			return
		}
		fileContents, err := client.Do(r.Context(), client.B().Get().Key(file+":contents").Build()).AsBytes()
		if err != nil {
			return
		}
		w.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
		mime := mimetype.Detect(fileContents)
		w.Header().Add("mimetype", mime.String())
		w.Write(fileContents)
	}
}
func DownloadFilesZipped(client valkey.Client) func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		upload_id := r.PathValue("upload_id")
		if upload_id == "" {
			w.WriteHeader(http.StatusBadRequest)
			return
		}

		files_json, err := client.Do(r.Context(),
			client.B().Get().Key(upload_id).Build()).ToString()
		if err != nil {
			http.Error(w, err.Error(), http.StatusNotFound)
			return
		}

		var files []string

		err = json.Unmarshal([]byte(files_json), &files)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if len(files) == 1 {
			file := files[0]

			filename, err := client.Do(r.Context(), client.B().Get().Key(file+":filename").Build()).ToString()
			if err != nil {
				return
			}
			fileContents, err := client.Do(r.Context(), client.B().Get().Key(file+":contents").Build()).AsBytes()
			if err != nil {
				return
			}
			w.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
			mime := mimetype.Detect(fileContents)
			w.Header().Add("mimetype", mime.String())
			w.Write(fileContents)
			return
		}

		zipBuf := new(bytes.Buffer)
		zipWriter := zip.NewWriter(zipBuf)

		for _, file := range files {
			filename, err := client.Do(r.Context(), client.B().Get().Key(file+":filename").Build()).ToString()
			if err != nil {
				continue
			}
			fileContents, err := client.Do(r.Context(), client.B().Get().Key(file+":contents").Build()).AsBytes()
			if err != nil {
				continue
			}
			w, err := zipWriter.Create(filename)
			if err != nil {
				continue
			}
			w.Write(fileContents)

		}

		zipWriter.Close()
		w.Header().Add("mimetype", "application/zip")
		w.Header().Add("Content-Disposition", `attachment; filename="timeshare-download.zip"`)
		io.Copy(w, zipBuf)

	}
}
