--[[
    SocietixM Plugin - Server Management
    Handles server creation, configuration, and management within Roblox Studio
]]

local SocietixMPlugin = script.Parent.Parent
local Core = require(SocietixMPlugin.Core)
local UI = require(SocietixMPlugin.UI)
local Network = require(SocietixMPlugin.Network)

local Server = {}
Server.__index = Server

-- Server configuration
local DEFAULT_CONFIG = {
    Name = "SocietixM Server",
    Description = "A custom server created with SocietixM",
    MaxPlayers = 20,
    IsPrivate = true,
    AllowFriends = true,
    AllowSpectators = false,
    Region = "US-East",
    EnableMods = true,
    Password = "",
    MapName = "Default Map",
    GameMode = "Free Play"
}

function Server.new()
    local self = setmetatable({}, Server)
    
    self.Config = Core.Utils.deepCopy(DEFAULT_CONFIG)
    self.IsRunning = false
    self.ServerId = nil
    self.SocietixId = nil
    self.Players = {}
    self.Modules = {}
    
    return self
end

function Server:Initialize()
    print("[SocietixM] Initializing server...")
    
    -- Load server modules
    self:LoadModules()
    
    -- Set up server events
    self:SetupEvents()
    
    -- Initialize networking
    Network:Initialize()
    
    print("[SocietixM] Server initialized successfully")
end

function Server:LoadModules()
    local modulesFolder = SocietixMPlugin:FindFirstChild("Modules")
    if not modulesFolder then
        warn("[SocietixM] No modules folder found")
        return
    end
    
    for _, module in pairs(modulesFolder:GetChildren()) do
        if module:IsA("ModuleScript") then
            local success, moduleScript = pcall(require, module)
            if success then
                self.Modules[module.Name] = moduleScript
                print("[SocietixM] Loaded module:", module.Name)
            else
                warn("[SocietixM] Failed to load module:", module.Name, moduleScript)
            end
        end
    end
end

function Server:SetupEvents()
    -- Player connection events
    game.Players.PlayerAdded:Connect(function(player)
        self:OnPlayerJoined(player)
    end)
    
    game.Players.PlayerRemoving:Connect(function(player)
        self:OnPlayerLeft(player)
    end)
    
    -- Server shutdown event
    game:BindToClose(function()
        self:Shutdown()
    end)
end

function Server:OnPlayerJoined(player)
    print("[SocietixM] Player joined:", player.Name)
    
    -- Add to players list
    self.Players[player.UserId] = {
        Name = player.Name,
        UserId = player.UserId,
        JoinTime = tick(),
        IsSpectator = false
    }
    
    -- Send server info to player
    self:SendServerInfo(player)
    
    -- Notify other players
    self:BroadcastPlayerJoined(player)
end

function Server:OnPlayerLeft(player)
    print("[SocietixM] Player left:", player.Name)
    
    -- Remove from players list
    self.Players[player.UserId] = nil
    
    -- Notify other players
    self:BroadcastPlayerLeft(player)
end

function Server:SendServerInfo(player)
    local serverInfo = {
        Name = self.Config.Name,
        Description = self.Config.Description,
        MaxPlayers = self.Config.MaxPlayers,
        PlayerCount = #game.Players:GetPlayers(),
        MapName = self.Config.MapName,
        GameMode = self.Config.GameMode,
        Version = "1.0.0",
        IsPrivate = self.Config.IsPrivate
    }
    
    -- Send via RemoteEvent
    local remoteEvent = SocietixMPlugin:FindFirstChild("ServerInfoEvent")
    if remoteEvent then
        remoteEvent:FireClient(player, serverInfo)
    end
end

function Server:BroadcastPlayerJoined(player)
    local remoteEvent = SocietixMPlugin:FindFirstChild("PlayerJoinedEvent")
    if remoteEvent then
        remoteEvent:FireAllClients(player.Name, #game.Players:GetPlayers())
    end
end

function Server:BroadcastPlayerLeft(player)
    local remoteEvent = SocietixMPlugin:FindFirstChild("PlayerLeftEvent")
    if remoteEvent then
        remoteEvent:FireAllClients(player.Name, #game.Players:GetPlayers())
    end
end

function Server:Create(config)
    print("[SocietixM] Creating server with config...")
    
    -- Merge config with defaults
    for key, value in pairs(config) do
        if self.Config[key] ~= nil then
            self.Config[key] = value
        end
    end
    
    -- Generate server ID
    self.ServerId = self:GenerateServerId()
    
    -- Generate Societix ID
    self.SocietixId = self:GenerateSocietixId()
    
    -- Set up server settings
    game.Players.MaxPlayers = self.Config.MaxPlayers
    
    -- Create server UI
    self:CreateServerUI()
    
    print("[SocietixM] Server created successfully")
    print("[SocietixM] Server ID:", self.ServerId)
    print("[SocietixM] Societix ID:", self.SocietixId)
    
    return true
end

function Server:Start()
    if self.IsRunning then
        warn("[SocietixM] Server is already running")
        return false
    end
    
    print("[SocietixM] Starting server...")
    
    self.IsRunning = true
    
    -- Register server with SocietixM network
    self:RegisterServer()
    
    -- Start server modules
    self:StartModules()
    
    print("[SocietixM] Server started successfully")
    return true
end

function Server:Stop()
    if not self.IsRunning then
        warn("[SocietixM] Server is not running")
        return false
    end
    
    print("[SocietixM] Stopping server...")
    
    self.IsRunning = false
    
    -- Unregister server from network
    self:UnregisterServer()
    
    -- Stop server modules
    self:StopModules()
    
    print("[SocietixM] Server stopped")
    return true
end

function Server:Shutdown()
    print("[SocietixM] Shutting down server...")
    
    if self.IsRunning then
        self:Stop()
    end
    
    -- Clean up resources
    self:Cleanup()
    
    print("[SocietixM] Server shutdown complete")
end

function Server:RegisterServer()
    local serverData = {
        Id = self.ServerId,
        Name = self.Config.Name,
        Description = self.Config.Description,
        MaxPlayers = self.Config.MaxPlayers,
        PlayerCount = #game.Players:GetPlayers(),
        RobloxGameId = tostring(game.PlaceId),
        SocietixId = self.SocietixId,
        IsPrivate = self.Config.IsPrivate,
        MapName = self.Config.MapName,
        GameMode = self.Config.GameMode,
        Version = "1.0.0",
        LastSeen = tick()
    }
    
    Network:RegisterServer(serverData)
end

function Server:UnregisterServer()
    Network:UnregisterServer(self.ServerId)
end

function Server:StartModules()
    for name, module in pairs(self.Modules) do
        if module.Start then
            local success, result = pcall(module.Start, module)
            if success then
                print("[SocietixM] Started module:", name)
            else
                warn("[SocietixM] Failed to start module:", name, result)
            end
        end
    end
end

function Server:StopModules()
    for name, module in pairs(self.Modules) do
        if module.Stop then
            local success, result = pcall(module.Stop, module)
            if success then
                print("[SocietixM] Stopped module:", name)
            else
                warn("[SocietixM] Failed to stop module:", name, result)
            end
        end
    end
end

function Server:CreateServerUI()
    -- Create GUI for server management
    local screenGui = Instance.new("ScreenGui")
    screenGui.Name = "SocietixMServerUI"
    screenGui.Parent = game.StarterGui
    
    -- Server info display
    local frame = Instance.new("Frame")
    frame.Name = "ServerInfoFrame"
    frame.Size = UDim2.new(0, 300, 0, 200)
    frame.Position = UDim2.new(0, 10, 0, 10)
    frame.BackgroundColor3 = Color3.new(0, 0, 0)
    frame.BackgroundTransparency = 0.3
    frame.BorderSizePixel = 0
    frame.Parent = screenGui
    
    -- Add rounded corners
    local corner = Instance.new("UICorner")
    corner.CornerRadius = UDim.new(0, 8)
    corner.Parent = frame
    
    -- Server name label
    local nameLabel = Instance.new("TextLabel")
    nameLabel.Name = "ServerNameLabel"
    nameLabel.Size = UDim2.new(1, -20, 0, 30)
    nameLabel.Position = UDim2.new(0, 10, 0, 10)
    nameLabel.BackgroundTransparency = 1
    nameLabel.Text = self.Config.Name
    nameLabel.TextColor3 = Color3.new(1, 1, 1)
    nameLabel.TextScaled = true
    nameLabel.Font = Enum.Font.GothamBold
    nameLabel.Parent = frame
    
    -- Player count label
    local playerLabel = Instance.new("TextLabel")
    playerLabel.Name = "PlayerCountLabel"
    playerLabel.Size = UDim2.new(1, -20, 0, 20)
    playerLabel.Position = UDim2.new(0, 10, 0, 50)
    playerLabel.BackgroundTransparency = 1
    playerLabel.Text = "Players: " .. #game.Players:GetPlayers() .. "/" .. self.Config.MaxPlayers
    playerLabel.TextColor3 = Color3.new(0.8, 0.8, 0.8)
    playerLabel.TextScaled = true
    playerLabel.Font = Enum.Font.Gotham
    playerLabel.Parent = frame
    
    -- Server ID label
    local idLabel = Instance.new("TextLabel")
    idLabel.Name = "ServerIdLabel"
    idLabel.Size = UDim2.new(1, -20, 0, 20)
    idLabel.Position = UDim2.new(0, 10, 0, 80)
    idLabel.BackgroundTransparency = 1
    idLabel.Text = "Server ID: " .. self.ServerId
    idLabel.TextColor3 = Color3.new(0.6, 0.6, 0.6)
    idLabel.TextScaled = true
    idLabel.Font = Enum.Font.Gotham
    idLabel.Parent = frame
    
    -- Societix ID label
    local societixLabel = Instance.new("TextLabel")
    societixLabel.Name = "SocietixIdLabel"
    societixLabel.Size = UDim2.new(1, -20, 0, 20)
    societixLabel.Position = UDim2.new(0, 10, 0, 110)
    societixLabel.BackgroundTransparency = 1
    societixLabel.Text = "Societix ID: " .. self.SocietixId
    societixLabel.TextColor3 = Color3.new(0.6, 0.6, 0.6)
    societixLabel.TextScaled = true
    societixLabel.Font = Enum.Font.Gotham
    societixLabel.Parent = frame
    
    -- Status label
    local statusLabel = Instance.new("TextLabel")
    statusLabel.Name = "StatusLabel"
    statusLabel.Size = UDim2.new(1, -20, 0, 20)
    statusLabel.Position = UDim2.new(0, 10, 0, 140)
    statusLabel.BackgroundTransparency = 1
    statusLabel.Text = "Status: " .. (self.IsRunning and "Running" or "Stopped")
    statusLabel.TextColor3 = self.IsRunning and Color3.new(0, 1, 0) or Color3.new(1, 0, 0)
    statusLabel.TextScaled = true
    statusLabel.Font = Enum.Font.Gotham
    statusLabel.Parent = frame
    
    -- Update player count periodically
    spawn(function()
        while self.IsRunning do
            wait(1)
            if playerLabel and playerLabel.Parent then
                playerLabel.Text = "Players: " .. #game.Players:GetPlayers() .. "/" .. self.Config.MaxPlayers
            end
        end
    end)
end

function Server:GenerateServerId()
    local chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    local id = ""
    
    for i = 1, 8 do
        local rand = math.random(1, #chars)
        id = id .. string.sub(chars, rand, rand)
    end
    
    return id
end

function Server:GenerateSocietixId()
    local timestamp = tostring(tick())
    local placeId = tostring(game.PlaceId)
    local input = placeId .. "_" .. timestamp .. "_societix"

    local hash = 0
    for i = 1, #input do
        hash = hash + string.byte(input, i)
    end
    
    return "SX" .. tostring(hash % 1000000)
end

function Server:Cleanup()
    -- Clean up any resources
    self.Players = {}
    self.Modules = {}
end

function Server:GetConfig()
    return self.Config
end

function Server:SetConfig(key, value)
    if self.Config[key] ~= nil then
        self.Config[key] = value
        return true
    end
    return false
end

function Server:GetPlayerCount()
    return #game.Players:GetPlayers()
end

function Server:GetMaxPlayers()
    return self.Config.MaxPlayers
end

function Server:IsFull()
    return self:GetPlayerCount() >= self:GetMaxPlayers()
end

return Server
