package organization

import (
	"strings"

	"github.com/gofiber/fiber/v2"
	"github.com/google/uuid"
	"lms.de/backend/modules/database"
	"lms.de/backend/modules/structs"
	"lms.de/backend/modules/utils"
)

func GetOrganizationSettings(c *fiber.Ctx) error {
	// swagger:operation GET /organization/settings organization getOrganizationSettings
	// ---
	// summary: Get settings
	// consumes:
	// - application/json
	// produces:
	// - application/json
	// responses:
	//   '200':
	//     description: Settings fetched successfully
	//     schema:
	//       "$ref": "#/definitions/GetOrganizationSettingsResponse"
	//   '400':
	//     description: Invalid request body
	//   '500':
	//     description: Failed to fetch settings

	var organizationSettings structs.GetOrganizationSettingsResponse

	database.DB.Model(&structs.Organization{}).Select("subdomain", "company_name", "primary_color", "logo_url", "banner_url").First(&organizationSettings)

	return c.JSON(organizationSettings)
}

func UpdateOrganizationSettings(c *fiber.Ctx) error {
	// swagger:operation PATCH /organization/settings organization updateOrganizationSettings
	// ---
	// summary: Update settings
	// consumes:
	// - application/json
	// produces:
	// - application/json
	// parameters:
	// - name: body
	//   in: body
	//   schema:
	//     "$ref": "#/definitions/GetOrganizationSettingsResponse"
	// responses:
	//   '200':
	//     description: Settings updated successfully
	//   '400':
	//     description: Invalid request body
	//   '500':
	//     description: Failed to update settings

	var organizationSettings structs.UpdateOrganizationSettingsRequest

	if err := c.BodyParser(&organizationSettings); err != nil {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	database.DB.Model(&structs.Organization{
		Id: c.Locals("organizationId").(string),
	}).Updates(organizationSettings)

	return c.SendStatus(fiber.StatusOK)
}

func UpdateOrganizationFile(c *fiber.Ctx) error {
	// swagger:operation POST /organization/file/{type} organization updateOrganizationFiles
	// ---
	// summary: Update files
	// consumes:
	// - multipart/form-data
	// produces:
	// - application/json
	// parameters:
	// - name: logo
	//   in: formData
	//   type: file
	//   required: false
	// - name: banner
	//   in: formData
	//   type: file
	//   required: false
	// responses:
	//   '200':
	//     description: Files updated successfully
	//   '400':
	//     description: Invalid request body
	//   '500':
	//     description: Failed to update files

	var params structs.UpdateOrganizationFileParam

	if err := c.ParamsParser(&params); err != nil {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	fileHeader, err := c.FormFile("file")

	if err != nil {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	if params.Type == "logo" || params.Type == "banner" {
		if fileHeader.Size > utils.MaxImageSize {
			return c.SendStatus(fiber.StatusBadRequest)
		}

		if !utils.IsFileTypeAllowed(fileHeader.Header.Get("Content-Type"), utils.AcceptedImageFileTypes) {
			return c.SendStatus(fiber.StatusBadRequest)
		}
	} else {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	// get current file

	organization := structs.Organization{}

	selectField := "logo_url"

	if params.Type == "banner" {
		selectField = "banner_url"
	}

	database.DB.Model(&structs.Organization{
		Id: c.Locals("organizationId").(string),
	}).Select(selectField).First(&organization)

	// delete current file

	if organization.LogoUrl != "" {
		utils.DeleteFile(organization.LogoUrl)
	}

	if organization.BannerUrl != "" {
		utils.DeleteFile(organization.BannerUrl)
	}

	fileName := uuid.New().String() + "." + strings.Split(fileHeader.Header["Content-Type"][0], "/")[1]

	databasePath, publicPath := utils.GetFullImagePath(c.Locals("organizationId").(string), "")

	utils.CreateFolderStructureIfNotExists(publicPath)

	update := structs.Organization{}

	if params.Type == "logo" {
		update.LogoUrl = databasePath + fileName
	} else {
		update.BannerUrl = databasePath + fileName
	}

	database.DB.Model(&structs.Organization{
		Id: c.Locals("organizationId").(string),
	}).Updates(update)

	if err := c.SaveFile(fileHeader, publicPath+fileName); err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"error": "Failed to save file",
		})
	}

	return c.JSON(fiber.Map{
		"Data": databasePath + fileName,
	})
}
