package jxscanner

import (
	"jannex/admin-dashboard-backend/modules/database"
	"jannex/admin-dashboard-backend/modules/logger"
	"jannex/admin-dashboard-backend/modules/structs"
	"jannex/admin-dashboard-backend/modules/utils"
	"jannex/admin-dashboard-backend/socketclients"
	"time"

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

func AddScanner(c *fiber.Ctx) error {
	var body structs.ScannerRequest

	if err := c.BodyParser(&body); err != nil {
		log.Error().Msg("Failed to parse body, err: " + err.Error())
		return c.Status(fiber.StatusBadRequest).JSON(err)
	}

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

	id := uuid.V4()
	session, err := utils.GenerateSession()

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

	scanner := &structs.Scanner{
		Id:           id,
		Session:      session,
		Name:         body.ScannerName,
		UserAgent:    string(c.Context().UserAgent()),
		RegisteredAt: time.Now(),
	}

	database.DB.Create(scanner)

	// clear session to prevent leaking and sending to ui
	scanner.Session = ""

	socketclients.BroadcastMessage(structs.SendSocketMessage{
		Cmd:  utils.SentCmdNewScanner,
		Body: scanner,
	})

	logger.AddSystemLog(structs.LogMessage{
		Id:   14,
		Type: utils.LogTypeInfo,
		Messages: []structs.LogData{
			{
				Type:  "scannerId",
				Value: scanner.Id,
			},
			{
				Type:  "scannerName",
				Value: scanner.Name,
			},
		},
	})

	return c.JSON(structs.ScannerResponse{Id: id, Session: session})
}

func ScanResult(c *fiber.Ctx) error {
	var body structs.ScanResultRequest

	if err := c.BodyParser(&body); err != nil {
		log.Error().Msg("Failed to parse body, err: " + err.Error())
		return c.Status(fiber.StatusBadRequest).JSON(err)
	}

	if body.ScanResult == "" {
		return c.SendStatus(fiber.StatusBadRequest)
	}

	scannerId := c.Locals("scannerId").(string)
	lastUsed := time.Now()

	database.DB.Model(&structs.Scanner{}).Where("id = ?", scannerId).Updates(&structs.Scanner{LastUsed: lastUsed})

	socketclients.BroadcastMessage(structs.SendSocketMessage{
		Cmd: utils.SentCmdUpdateScannerLastUsed,
		Body: struct {
			ScannerId string
			LastUsed  time.Time
		}{
			ScannerId: scannerId,
			LastUsed:  lastUsed,
		},
	})

	socketclients.SendMessageToUser(c.Locals("usedByUserId").(string), "", structs.SendSocketMessage{
		Cmd:  utils.SentCmdScanResult,
		Body: body.ScanResult,
	})

	logger.AddSystemLog(structs.LogMessage{
		Id:   15,
		Type: utils.LogTypeInfo,
		Messages: []structs.LogData{
			{
				Type:  "scannerId",
				Value: scannerId,
			},
			{
				Type:  "scanResult",
				Value: body.ScanResult,
			},
		},
	})

	return c.SendStatus(fiber.StatusOK)
}

func DeleteScanner(c *fiber.Ctx) error {
	session := utils.GetXAuhorizationHeader(c)

	var scanner structs.Scanner

	database.DB.First(&scanner, "session = ?", session)

	database.DB.Delete(&structs.Scanner{}, "session = ?", session)

	socketclients.BroadcastMessage(structs.SendSocketMessage{
		Cmd: utils.SentCmdDeleteScanner,
		Body: struct {
			Id string
		}{
			Id: scanner.Id,
		},
	})

	logger.AddSystemLog(structs.LogMessage{
		Id:   16,
		Type: utils.LogTypeInfo,
		Messages: []structs.LogData{
			{
				Type:  "scannerId",
				Value: scanner.Id,
			},
		},
	})

	return c.SendStatus(fiber.StatusOK)
}
