package organization

import (
	"encoding/base64"

	"git.ex.umbach.dev/Alex/roese-utils/rsutils"
	"git.ex.umbach.dev/LMS/libcore/models"
	"github.com/gofiber/fiber/v2"
	"github.com/google/uuid"
	"github.com/rs/zerolog/log"
	"golang.org/x/crypto/bcrypt"
	"lms.de/backend/modules/database"
	"lms.de/backend/modules/structs"
	"lms.de/backend/modules/utils"
	"lms.de/backend/socketclients"
)

func GetTeamMembers(c *fiber.Ctx) error {
	// swagger:operation GET /organization/team/members organization getTeamMembers
	// ---
	// summary: Get team members
	// consumes:
	// - application/json
	// produces:
	// - application/json
	// responses:
	//   '200':
	//     description: Team members fetched successfully
	//     schema:
	//       type: array
	//       items:
	//         "$ref": "#/definitions/TeamMember"
	//   '400':
	//     description: Invalid request body
	//   '500':
	//     description: Failed to fetch team members

	var users []structs.TeamMember

	if err := database.DB.Model(&models.User{}).Where("organization_id = ?", c.Locals("organizationId")).Find(&users).Error; err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	return c.JSON(users)
}

func CreateTeamMember(c *fiber.Ctx) error {
	// swagger:operation POST /organization/team/members organization createTeamMember
	// ---
	// summary: Create team member
	// consumes:
	// - application/json
	// produces:
	// - application/json
	// parameters:
	// - name: body
	//   in: body
	//   schema:
	//     "$ref": "#/definitions/CreateTeamMemberRequest"
	// responses:
	//   '200':
	//     description: Team member created successfully
	//   '400':
	//     description: Invalid request body
	//   '500':
	//     description: Failed to create team member

	var body structs.CreateTeamMemberRequest

	if err := rsutils.BodyParserHelper(c, &body); err != nil {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	user := models.User{
		Id:             uuid.New().String(),
		FirstName:      body.FirstName,
		LastName:       body.LastName,
		Email:          body.Email,
		OrganizationId: c.Locals("organizationId").(string),
		RoleId:         body.RoleId,
	}

	decodedPassword, err := base64.StdEncoding.DecodeString(body.Password)

	if err != nil {
		log.Error().Msg("Failed to decode base64 password, err: " + err.Error())
		return c.SendStatus(fiber.StatusBadRequest)
	}

	if passwordValid := utils.IsPasswordLengthValid(string(decodedPassword)); !passwordValid {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	// Hash password
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(body.Password), bcrypt.DefaultCost)

	if err != nil {
		log.Error().Msg("Failed to hash password, err: " + err.Error())
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	user.Password = string(hashedPassword)

	// Create user

	if err := database.DB.Create(&user).Error; err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	socketclients.BroadcastMessageToTopicExceptBrowserTabSession(
		c.Locals("organizationId").(string),
		utils.SubscribedTopicTeam,
		c.Locals("browserTabSession").(string),
		structs.SendSocketMessage{
			Cmd: utils.SendCmdTeamAddedMember,
			Body: struct {
				Id        string
				FirstName string
				LastName  string
				Email     string
				RoleId    string
			}{
				Id:        user.Id,
				FirstName: user.FirstName,
				LastName:  user.LastName,
				Email:     user.Email,
				RoleId:    user.RoleId,
			},
		},
	)

	return c.JSON(fiber.Map{
		"message": "Team member created successfully",
	})
}
