package webhandler

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"sort"

	"git.agecem.com/agecem/agecem-org/api"
	"git.agecem.com/agecem/agecem-org/apiresponse"
	"git.agecem.com/agecem/agecem-org/models"
	"git.agecem.com/agecem/agecem-org/webresponse"
	"github.com/labstack/echo/v4"
)

type WebHandler struct {
	ApiClient *api.API
}

func HandleIndex(c echo.Context) error {
	return c.Render(http.StatusOK, "index-html", nil)
}

/*
func HandleAPropos(c echo.Context) error {
	return c.Render(http.StatusOK, "a-propos-html", nil)
}
*/

/*
func HandleActualite(c echo.Context) error {
	return c.Render(http.StatusOK, "actualite-html", nil)
}
*/

/*
func HandleActualiteArticle(c echo.Context) error {
	article := c.Param("article")
	return c.String(http.StatusOK, fmt.Sprintf("Article: %s", article))
}
*/

func HandleVieEtudiante(c echo.Context) error {
	return c.Render(http.StatusOK, "vie-etudiante-html", nil)
}

func HandleVieEtudianteOrganisme(c echo.Context) error {
	organisme := c.Param("organisme")
	return c.String(http.StatusOK, fmt.Sprintf("Organisme: %s", organisme))
}

func (h *WebHandler) HandleDocumentation(c echo.Context) error {
	var response webresponse.HandleDocumentationResponse

	v1BucketsGET, err := h.ApiClient.ListBuckets()
	if err != nil {
		response.Error = err.Error()
		response.Message = v1BucketsGET.Message
		response.StatusCode = v1BucketsGET.StatusCode

		return c.Render(response.StatusCode, "documentation-html", response)
	}

	//TODO check v1BucketsGET StatusCode and Error

	for bucket, displayName := range v1BucketsGET.Data.Buckets {
		// TODO move call to dedicated API client method
		var v1BucketReadResponse apiresponse.V1BucketGET

		if err = h.ApiClient.Voki.Unmarshal(http.MethodGet, fmt.Sprintf("/v1/bucket/%s", bucket), nil, true, &v1BucketReadResponse); err != nil {
			response.Error = err.Error()
			response.Message = "Error during json.Unmarshal /v1/bucket/:bucket"
			response.StatusCode = http.StatusInternalServerError

			return c.Render(http.StatusOK, "documentation-html", response)
		}

		response.Data.Buckets = append(response.Data.Buckets, models.Bucket{
			Name:        bucket,
			DisplayName: displayName,
			Documents:   v1BucketReadResponse.Data.Keys,
		})
	}

	sort.SliceStable(response.Data.Buckets, func(i, j int) bool { return response.Data.Buckets[i].Name < response.Data.Buckets[j].Name })

	response.StatusCode = http.StatusOK
	//response.Message = "HandleDocumentation ok"

	// TODO render .Message
	return c.Render(http.StatusOK, "documentation-html", response)
	//return c.Render(response.StatusCode, "documentation-html", response.Data.Buckets)
}

func HandleFormulaires(c echo.Context) error {
	return c.Render(http.StatusOK, "formulaires-html", nil)
}

func (h *WebHandler) HandlePublicDocumentation(c echo.Context) error {
	bucket := c.Param("bucket")
	document := c.Param("document")

	unescaped, err := url.QueryUnescape(fmt.Sprintf("/v1/bucket/%s/%s", bucket, document))
	if err != nil {
		return c.JSON(http.StatusBadRequest, map[string]string{"message": "Bad Request"})
	}

	response, err := h.ApiClient.Voki.Call(http.MethodGet, unescaped, nil, true)
	if err != nil {
		return c.JSON(apiresponse.NotFoundResponse())
	}
	defer response.Body.Close()

	switch response.StatusCode {
	case http.StatusNotFound:
		return c.JSON(apiresponse.NotFoundResponse())
	case http.StatusInternalServerError:
		return c.JSON(http.StatusInternalServerError, map[string]string{"message": "Internal Server Error"})
	}

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return c.JSON(http.StatusInternalServerError, map[string]string{"message": "Internal Server Error"})
	}

	return c.Blob(http.StatusOK, "application/octet-stream", body)
}

func HandleAdmin(c echo.Context) error {
	return c.Render(http.StatusOK, "admin-html", nil)
}

func (h *WebHandler) HandleAdminDocumentsUpload(c echo.Context) error {
	var response webresponse.HandleAdminDocumentsUploadResponse

	v1BucketsGET, err := h.ApiClient.ListBuckets()
	if err != nil {
		response.StatusCode = v1BucketsGET.StatusCode
		response.Error = err.Error()
		response.Message = v1BucketsGET.Message

		return c.Render(response.StatusCode, "admin-upload-html", nil)
	}

	for bucketName, displayName := range v1BucketsGET.Data.Buckets {
		response.Data.Buckets = append(response.Data.Buckets, models.Bucket{
			Name:        bucketName,
			DisplayName: displayName,
		})
	}
	response.StatusCode = http.StatusOK

	return c.Render(response.StatusCode, "admin-upload-html", response)
}

func (h *WebHandler) HandleAdminDocumentsUploadPOST(c echo.Context) error {
	var response webresponse.HandleAdminDocumentsUploadResponse

	v1BucketsGET, err := h.ApiClient.ListBuckets()
	if err != nil {
		response.StatusCode = v1BucketsGET.StatusCode
		response.Message = v1BucketsGET.Message
		response.Error = err.Error()

		return c.Render(response.StatusCode, "admin-upload-html", response)
	}

	for bucketName, displayName := range v1BucketsGET.Data.Buckets {
		response.Data.Buckets = append(response.Data.Buckets, models.Bucket{
			Name:        bucketName,
			DisplayName: displayName,
		})
	}

	bucket := c.FormValue("bucket")

	document, err := c.FormFile("document")
	if err != nil {
		response.StatusCode = http.StatusBadRequest
		response.Message = "Formulaire invalide"
		response.Error = err.Error()

		return c.Render(response.StatusCode, "admin-upload-html", response)
	}

	uploadDocumentResponse, err := h.ApiClient.UploadDocument(bucket, document)
	if err != nil {
		response.StatusCode = uploadDocumentResponse.StatusCode
		response.Message = uploadDocumentResponse.Message
		response.Error = err.Error()

		return c.Render(response.StatusCode, "admin-upload-html", response)
	}

	// Format response
	var info, status string

	info = fmt.Sprintf("[%d] /public/documentation/%s/%s", uploadDocumentResponse.Data.Size, uploadDocumentResponse.Data.Bucket, uploadDocumentResponse.Data.Key)

	status = uploadDocumentResponse.Message

	response.StatusCode = http.StatusOK
	response.Message = fmt.Sprintf("%s - %s", status, info)

	return c.Render(response.StatusCode, "admin-upload-html", response)
}
