using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using GTANetworkAPI;
using Newtonsoft.Json;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Extensions;
using ReallifeGamemode.Server.Finance;
using ReallifeGamemode.Server.Managers;
using ReallifeGamemode.Server.Services;
using ReallifeGamemode.Server.Types;
using ReallifeGamemode.Server.Util;
using ReallifeGamemode.Services;

namespace ReallifeGamemode.Server.Commands
{
  internal class UserCommands : Script
  {
    [Command("rent", "~m~rent stop")]
    public void CmdUserStopRent(Player player, String option = "") {
      if (!player.IsLoggedIn()) return;

      if (option != "stop")
      {
        player.SendChatMessage("Mit \"/rent stop\" kannst du die Miete kündigen");
        return;
      }

      if (!player.HasData("hasRentcar"))
      {
        ChatService.ErrorMessage(player, "Du hast zurzeit kein Fahrzeug gemietet");
        return;
      }

      Rentcar.cancelRent(player);
    }

    [Command("eventport", "~m~eventport")]
    public void CmdUserEventport(Player player, String option = "")
    {
      if (!player.IsLoggedIn()) return;

      if (option == "on")
      {
        if (!player.GetUser()?.IsAdmin(AdminLevel.ADMIN) ?? true)
        {
          return;
        }
        PositionManager.eventportPosition = player.Position;
        PositionManager.eventportActive = true;
        player.SendChatMessage("~y~Du hast hier erfolgreich einen Eventport gesetzt.");
        return;
      }

      if (option == "off")
      {
        if (!player.GetUser()?.IsAdmin(AdminLevel.ADMIN) ?? true)
        {
          return;
        }
        PositionManager.eventportActive = false;
        player.SendChatMessage("~y~Du hast den Eventport deaktiviert.");
        return;
      }

      if (!PositionManager.eventportActive || PositionManager.eventportPosition == null)
      {
        player.SendChatMessage("~y~Im Moment ist kein Eventport aktiv.");
        return;
      }

      using (var dbContext = new DatabaseContext())
      {
        User user = player.GetUser(dbContext);
        if (user.Wanteds > 0 || user.JailTime > 0 || player.HasData("inGangWar") || !player.IsAlive())
        {
          ChatService.ErrorMessage(player, "Momentan kannst du keinen Eventport nutzen");
          return;
        }
      }

      Random rnd = new Random();
      int randomX = rnd.Next(-3, 3);
      int randomY = rnd.Next(-3, 3);

      Vector3 teleportPosition = new Vector3(PositionManager.eventportPosition.X + randomX, PositionManager.eventportPosition.Y + randomY, PositionManager.eventportPosition.Z);

      player.SafeTeleport(teleportPosition);
      player.SendNotification("Du hast dich zum Event teleportiert");
    }

    [Command("sms", "~m~Benutzung: ~s~/sms [Spieler] [Nachricht]", GreedyArg = true)]
    public void CmdUserSMS(Player player, string name, string msg)
    {
      if (!player.IsLoggedIn()) return;

      Player target = PlayerService.GetPlayerByNameOrId(name);
      if (target == null || !target.IsLoggedIn())
      {
        ChatService.PlayerNotFound(player);
        return;
      }

      if (target == player)
      {
        ChatService.ErrorMessage(player, "Du kannst dir keine SMS schreiben");
        return;
      }

      msg = Regex.Replace(msg, "(~[a-zA-Z]~)|(!{(.*)})", "");

      ChatService.SendMessage(player, $"~y~SMS ~w~an ~y~{target.Name}~w~: {msg}");
      ChatService.SendMessage(target, $"~y~SMS ~w~von ~y~{player.Name}~w~: { msg }");
    }

    [Command("look", "~m~look")]
    public void CmdUserLook(Player player)
    {
      if (!player.IsLoggedIn()) return;

      Vehicle veh = NAPI.Pools.GetAllVehicles()
        .Where(v => v.Position.DistanceTo(player.Position) <= 5)
        .OrderBy(v => v.Position.DistanceTo(player.Position))
        .FirstOrDefault();

      if (veh == null)
      {
        return;
      }

      var lastDriverDic = new Dictionary<string, DateTime>();

      if(VehicleManager.lastDriversInVehicle.ContainsKey(veh))
      {
        lastDriverDic = VehicleManager.lastDriversInVehicle[veh];
      }
      else
      {
        player.SendNotification("~r~Mit diesem Fahrzeug ist noch niemand gefahren");
        return;
      }

      var list = lastDriverDic.Select(v => new
      {
        Name = v.Key,
        Time = v.Value
      }).OrderByDescending(v => v.Time).ToList();

      player.TriggerEvent("lookLastDrivers", JsonConvert.SerializeObject(list));
    }

    [Command("id", "~m~Benutzung: ~s~/id [Name]")]
    public void CmdUserId(Player player, String targetname)
    {
      Player target = PlayerService.GetPlayerByNameOrId(targetname);

      if (target == null)
      {
        player.SendChatMessage("~c~Spieler ist nicht online.");
      }
      else
      {
        player.SendChatMessage("~c~ID: (" + target.Id + ") " + target.Name);
      }
    }

    [Command("dice", "~m~Benutzung: ~s~/dice")]
    public void CmdUserDice(Player player)
    {
      if (!player.IsLoggedIn()) return;

      Random rnd = new Random();
      int number = rnd.Next(1, 7);

      var peopleInRange = NAPI.Player.GetPlayersInRadiusOfPlayer(7, player);

      foreach (var managedPlayer in peopleInRange)
      {
        if (!managedPlayer.IsLoggedIn()) return;
        ChatService.SendMessage(managedPlayer, "* " + player.Name + " hat eine " + number + " gewürfelt.");
      }
    }

    [Command("car", "~m~Benutzung: ~s~/car")]
    public void CmdUserCar(Player player)
    {
      if (!player.IsLoggedIn()) return;

      Vehicle pVeh = null;

      if (player.IsInVehicle)
      {
        pVeh = player.Vehicle;
      }
      else
      {
        pVeh = NAPI.Pools.GetAllVehicles().Where(v => v.Position.DistanceTo(player.Position) <= 5).OrderBy(v => v.Position.DistanceTo(player.Position)).FirstOrDefault();
      }

      if (pVeh == null)
      {
        return;
      }

      using var dbContext = new DatabaseContext();

      if (pVeh.GetServerVehicle(dbContext) is ServerVehicle veh)
      {
        string dbIdStr = player.GetUser(dbContext).IsAdmin(AdminLevel.ADMIN) ? $" | DB-ID: {veh.Id}" : "";
        ChatService.SendMessage(player, "~m~" + ((VehicleHash)pVeh.Model) + " | " + veh.ToString() + " | Farbe 1: " + pVeh.PrimaryColor + " | Farbe 2: " + pVeh.SecondaryColor + " | ID: " + pVeh.Handle.Value + dbIdStr);
      }
      else
      {
        ChatService.SendMessage(player, "~m~" + ((VehicleHash)pVeh.Model) + " | Farbe 1: " + pVeh.PrimaryColor + " | Farbe 2: " + pVeh.SecondaryColor + " | ID: " + pVeh.Handle.Value);
      }
    }

    [Command("help", "~m~Benutzung: ~s~/help")]
    public void CmdUserHelp(Player player)
    {
      player.SendChatMessage("E - Interagieren (ATM, Türen, Shops, Friseur etc.");
      player.SendChatMessage("M - Interaktionsmenü öffnen und schließen");
      player.SendChatMessage("X - Fahrzeug auf -/ abschließen sowie im Fahrzeuginteraktionsmenü öffnen");
      player.SendChatMessage("N - Fahrzeugmotor Starten");
      player.SendChatMessage("O - Onlineliste öffnen / schließen");
      player.SendChatMessage("I - Inventar öffnen / schließen");
      player.SendChatMessage("F4 - Mikrofon an/aus schalten");
      player.SendChatMessage("/report - Support-Anfrage");
    }

    [Command("hup")]
    public void CmdUserHup(Player player)
    {
      player.CheckToggleSurrender();
    }

    [Command("event", "~m~Benutzung: ~s~/event [Nachricht]", GreedyArg = true)]
    public void CmdFactionNREventchat(Player player, string msg)
    {
      if (player.HasData("eventAllowed") == false)
      {
        ChatService.NotAuthorized(player);
        return;
      }
      ChatService.BroadcastFaction("~b~[Event] " + player.Name + ": " + msg, new List<int>() { 9 });
    }
  }
}
