package equipment

import (
	"encoding/base64"
	"encoding/json"
	"jannex/admin-dashboard-backend/modules/config"
	"jannex/admin-dashboard-backend/modules/database"
	"jannex/admin-dashboard-backend/modules/equipment"
	"jannex/admin-dashboard-backend/modules/structs"
	"jannex/admin-dashboard-backend/modules/utils"
	"os"
	"strings"

	"github.com/gofiber/fiber/v2"
	"github.com/google/uuid"
	"github.com/rs/zerolog/log"
)

func getImageType(data string) string {
	switch data {
	case "data:image/png;base64":
		return "png"
	default:
		return "jpeg"
	}
}

type Notes struct {
	Image       string
	Description string
}

func CreateEquipmentDocumentation(c *fiber.Ctx) error {
	var body structs.ApiCreateEquipmentDocumentationRequest

	if err := c.BodyParser(&body); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(err)
	}

	var bodyNotes []map[string]string

	err := json.Unmarshal(body.Notes, &bodyNotes)

	if err != nil {
		log.Error().Msgf("Failed to unmarshal json, err: %s", err)
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	newEquipmentDocumentation := structs.EquipmentDocumentation{
		Id:          uuid.New().String(),
		StockItemId: body.StockItemId,
		Type:        body.Type,
		Title:       body.Title,
	}

	// TODO: only create folder if there is an image
	if err := os.Mkdir(config.Cfg.FolderPaths.PublicStatic+"/equipmentdocumentation/"+newEquipmentDocumentation.Id, os.ModePerm); err != nil {
		log.Error().Msgf("Failed to create folder, err: %s", err)
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	var notes []Notes

	// loop throught bodyNotes and save image to static folder under random name
	for _, bodyNote := range bodyNotes {
		var newFileName string

		if bodyNote["image"] != "" {
			// image is sent as base64 string
			// decode it and save it to the static folder

			// encoded base64 image structure is: data:image/jpeg;base64,/9j/4AA...
			splittedImageData := strings.Split(bodyNote["image"], ",")

			decodedImage, err := base64.StdEncoding.DecodeString(splittedImageData[1])

			if err != nil {
				log.Error().Msgf("Failed to decode base64 string, err: %s", err)
				return c.SendStatus(fiber.StatusInternalServerError)

			}

			newFileName = uuid.New().String() + "." + getImageType(splittedImageData[0])

			err = os.WriteFile(config.Cfg.FolderPaths.PublicStatic+"/equipmentdocumentation/"+newEquipmentDocumentation.Id+"/"+newFileName, decodedImage, 0644)

			if err != nil {
				log.Error().Msgf("Failed to save image, err: %s", err)
				return c.SendStatus(fiber.StatusInternalServerError)
			}
		}

		notes = append(notes, Notes{
			Image:       newFileName,
			Description: bodyNote["description"],
		})
	}

	marshaledNotes, err := json.Marshal(notes)

	if err != nil {
		log.Error().Msgf("Failed to marshal notes, err: %s", err)
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	newEquipmentDocumentation.Notes = string(marshaledNotes)

	database.DB.Create(&newEquipmentDocumentation)

	return c.JSON(fiber.Map{"message": "ok"})
}

func GetEquipmentDocumentation(c *fiber.Ctx) error {
	var body structs.ApiEquipmentParamsRequest

	if err := c.ParamsParser(&body); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(err)
	}

	if errValidation := utils.ValidateStruct(body); errValidation != nil {
		log.Error().Msgf("Failed to validate body, err: %v", errValidation)
		return c.Status(fiber.StatusBadRequest).JSON(errValidation)
	}

	return equipment.GetEquipmentDocumentation(body.StockItemId, c)
}

// fetching the thumbnail from the invex server and sending it back to the client
func GetEquipmentThumbnail(c *fiber.Ctx) error {
	//resp, err := http.Get(equipment.Base + "/media/part_images/part_152_image.thumbnail.png")

	a := fiber.AcquireAgent()

	a.Add("Authorization", "Token "+equipment.ApiToken)

	req := a.Request()
	req.Header.SetMethod(fiber.MethodGet)
	req.SetRequestURI(equipment.Base + "/media/part_images/" + c.Params("stockItemThumbnail"))

	if err := a.Parse(); err != nil {
		log.Error().Msgf("Failed to parse request, err: %s", err)
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	code, body, errs := a.Bytes()

	log.Info().Msgf("code %d %s", code, errs)

	c.Set("Content-Type", "image/png")

	return c.Send(body)

}
