package handlers

import (
	"strconv"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/google/uuid"
	"github.com/tapper/backend/database"
	"github.com/tapper/backend/models"
	"github.com/tapper/backend/services"
)

func OwnerGetConfig(c *fiber.Ctx) error {
	configs, err := services.GetAllPlatformConfig()
	if err != nil {
		return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
			"error": "Failed to load platform configuration",
		})
	}

	for i := range configs {
		if configs[i].Encrypted {
			configs[i].Value = "********"
		}
	}

	return c.JSON(fiber.Map{
		"config": configs,
	})
}

func OwnerUpdateConfig(c *fiber.Ctx) error {
	actorID := c.Locals("user_id").(uuid.UUID)

	var req struct {
		Config map[string]struct {
			Value     string `json:"value"`
			Encrypted bool   `json:"encrypted"`
		} `json:"config"`
	}
	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "Invalid request body",
		})
	}

	for key, entry := range req.Config {
		if err := services.SetPlatformConfig(key, entry.Value, entry.Encrypted); err != nil {
			return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
				"error": "Failed to update config key: " + key,
			})
		}
	}

	services.LogAudit(actorID, models.AuditEditConfig, "config", nil, map[string]interface{}{
		"keys_updated": len(req.Config),
	}, c.IP())

	return c.JSON(fiber.Map{
		"message":      "Configuration updated",
		"keys_updated": len(req.Config),
	})
}

func OwnerGetCS2Config(c *fiber.Ctx) error {
	var totalPorts, allocatedPorts int64
	database.DB.Model(&models.PortPool{}).Count(&totalPorts)
	database.DB.Model(&models.PortPool{}).Where("allocated = true").Count(&allocatedPorts)

	var ports []models.PortPool
	database.DB.Order("port ASC").Find(&ports)

	return c.JSON(fiber.Map{
		"total_ports":      totalPorts,
		"allocated_ports":  allocatedPorts,
		"ports":            ports,
		"port_range_start": services.GetPlatformConfig("port_range_start", "27015"),
		"port_range_end":   services.GetPlatformConfig("port_range_end", "27064"),
	})
}

func OwnerUpdateCS2Config(c *fiber.Ctx) error {
	actorID := c.Locals("user_id").(uuid.UUID)

	var req struct {
		PortRangeStart *int `json:"port_range_start"`
		PortRangeEnd   *int `json:"port_range_end"`
	}
	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "Invalid request body",
		})
	}

	details := map[string]interface{}{}
	if req.PortRangeStart != nil {
		_ = services.SetPlatformConfig("port_range_start", strconv.Itoa(*req.PortRangeStart), false)
		details["port_range_start"] = *req.PortRangeStart
	}
	if req.PortRangeEnd != nil {
		_ = services.SetPlatformConfig("port_range_end", strconv.Itoa(*req.PortRangeEnd), false)
		details["port_range_end"] = *req.PortRangeEnd
	}

	services.LogAudit(actorID, models.AuditEditConfig, "config", nil, details, c.IP())
	return c.JSON(fiber.Map{"message": "CS2 configuration updated"})
}

func OwnerGetSystem(c *fiber.Ctx) error {
	metrics := services.GetSystemMetrics()
	return c.JSON(metrics)
}

func OwnerGetContainers(c *fiber.Ctx) error {
	var servers []models.GameServer
	database.DB.Order("created_at DESC").Limit(50).Find(&servers)

	return c.JSON(fiber.Map{
		"containers": servers,
	})
}

func OwnerRestartContainer(c *fiber.Ctx) error {
	actorID := c.Locals("user_id").(uuid.UUID)
	containerID := c.Params("id")

	services.LogAudit(actorID, "restart_container", "container", nil, map[string]interface{}{
		"container_id": containerID,
	}, c.IP())

	return c.JSON(fiber.Map{
		"message":      "Container restart requested",
		"container_id": containerID,
	})
}

func OwnerGetServiceLogs(c *fiber.Ctx) error {
	service := c.Params("service")
	if service == "" {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "Service name is required",
		})
	}

	return c.JSON(fiber.Map{
		"service": service,
		"logs":    []string{"Log streaming requires Docker socket access"},
	})
}

func OwnerToggleMaintenance(c *fiber.Ctx) error {
	actorID := c.Locals("user_id").(uuid.UUID)

	var req struct {
		Enabled bool `json:"enabled"`
	}
	if err := c.BodyParser(&req); err != nil {
		return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
			"error": "Invalid request body",
		})
	}

	val := "false"
	if req.Enabled {
		val = "true"
	}
	_ = services.SetPlatformConfig("maintenance_mode", val, false)

	services.LogAudit(actorID, models.AuditMaintenance, "config", nil, map[string]interface{}{
		"enabled": req.Enabled,
	}, c.IP())

	return c.JSON(fiber.Map{
		"message":          "Maintenance mode updated",
		"maintenance_mode": req.Enabled,
	})
}

func OwnerSeed(ownerEmail string, portStart, portEnd int) fiber.Handler {
	return func(c *fiber.Ctx) error {
		actorID := c.Locals("user_id").(uuid.UUID)

		database.Seed(ownerEmail, portStart, portEnd)

		services.LogAudit(actorID, models.AuditSeed, "system", nil, map[string]interface{}{
			"triggered_at": time.Now().UTC(),
		}, c.IP())

		return c.JSON(fiber.Map{
			"message": "Seed scripts executed",
		})
	}
}
