using System;
using System.Linq;
using GTANetworkAPI;
using Newtonsoft.Json;
using ReallifeGamemode.Database;
using ReallifeGamemode.Database.Entities;
using ReallifeGamemode.Database.Models;
using ReallifeGamemode.Server.Extensions;

namespace ReallifeGamemode.Server.Business
{
  public abstract class BusinessBase : BankAccountHolder<BusinessBankAccount>, IBankAccountOwner
  {
    private TextLabel _informationLabel;
    private ColShape _colShape;
    private Blip _blip;
    private Marker _marker;

    public virtual int? BlipSprite { get; } = null;

    public abstract int Id { get; }

    public abstract string Name { get; }

    public abstract Vector3 Position { get; }

    public override BusinessBankAccount BankAccount
    {
      get
      {
        using (var dbContext = new DatabaseContext())
        {
          return dbContext.BusinessBankAccounts.Where(b => b.BusinessId == this.Id).FirstOrDefault();
        }
      }

      set => throw new NotImplementedException();
    }

    public override int? BankAccountId
    {
      get
      {
        using (var dbContext = new DatabaseContext())
        {
          return dbContext.BusinessBankAccounts.Where(b => b.BusinessId == this.Id).Select(b => b.Id).FirstOrDefault();
        }
      }

      set => throw new NotImplementedException();
    }

    public override string BankAccountName => Name;

    public IBankAccount GetBankAccount(DatabaseContext databaseContext = null)
    {
      if (databaseContext == null)
      {
        using (databaseContext = new DatabaseContext())
        {
          return databaseContext.BusinessBankAccounts.FirstOrDefault(u => u.BusinessId == Id);
        }
      }
      else
      {
        return databaseContext.BusinessBankAccounts.FirstOrDefault(u => u.BusinessId == Id);
      }
    }

    public void Setup()
    {
      _informationLabel = NAPI.TextLabel.CreateTextLabel(Name, Position.Add(new Vector3(0, 0, 0.5)), 20.0f, 1.3f, 0, new Color(255, 255, 255));
      _marker = NAPI.Marker.CreateMarker(MarkerType.VerticalCylinder, Position.Subtract(new Vector3(0, 0, 1.5)), new Vector3(), new Vector3(), 1f, new Color(255, 255, 255));

      if (BlipSprite != null)
      {
        _blip = NAPI.Blip.CreateBlip(BlipSprite.Value, Position, 1f, 4, Name, shortRange: true);
      }

      _colShape = NAPI.ColShape.CreateSphereColShape(Position.Subtract(new Vector3(0, 0, 1.5)), 3f);
      _colShape.OnEntityEnterColShape += EntityEnterBusinessColShape;
      _colShape.OnEntityExitColShape += EntityExitBusinessColShape;

      if (GetBankAccount() == null)
      {
        NAPI.Util.ConsoleOutput("Creating Bank Account for Business: " + Name);
        using (var dbContext = new DatabaseContext())
        {
          dbContext.BusinessBankAccounts.Add(new BusinessBankAccount()
          {
            BusinessId = Id,
            Balance = 0
          });
          dbContext.SaveChanges();
        }
      }

      BusinessData data = GetData();

      if (data == null)
      {
        using (var dbContext = new DatabaseContext())
        {
          data = new BusinessData()
          {
            BusinessId = this.Id,
            Price = -1
          };

          dbContext.BusinessData.Add(data);

          dbContext.SaveChanges();
        }
      }
    }

    private void EntityExitBusinessColShape(ColShape colShape, Player client)
    {
      client.TriggerEvent("SERVER:Business_RemoveHelp", true);
    }

    public BusinessData GetData(DatabaseContext dbContext = null)
    {
      if (dbContext == null)
      {
        using (dbContext = new DatabaseContext())
        {
          return dbContext.BusinessData.Where(b => b.BusinessId == this.Id).FirstOrDefault();
        }
      }
      else
      {
        return dbContext.BusinessData.Where(b => b.BusinessId == this.Id).FirstOrDefault();
      }
    }

    private void EntityEnterBusinessColShape(ColShape colShape, Player client)
    {
      if (client.IsInVehicle || !client.IsLoggedIn()) return;

      SendBusinessDataToPlayer(client);
      client.TriggerEvent("SERVER:Business_ShowMenuHelp");
    }

    public void SendBusinessDataToPlayer(Player player)
    {
      User owner = GetOwner();

      int state = -1; // Keine Beziehung

      if (owner == null) // Kein Besitzer
      {
        state = 0;
      }
      else if (owner.Id == player.GetUser()?.Id) // Besitzer
      {
        state = 1;
      }

      var business = new
      {
        this.Name,
        Price = this.GetData().Price.ToMoneyString(),
        Balance = this.GetBankAccount().Balance.ToMoneyString()
      };

      player.TriggerEvent("SERVER:Business_SetData", JsonConvert.SerializeObject(business), state);
    }

    public void Update(int? money = null)
    {
      if (money == null) money = GetBankAccount()?.Balance ?? 0;
      User owner = GetOwner();
      string infoText = Name;
      if (owner == null) infoText += "\n~g~Zum Verkauf\n~s~Preis: ~y~" + this.GetData().Price.ToMoneyString();
      else infoText += $"\nBesitzer: ~g~{owner.Name}\n~s~Kasse: ~y~{money.ToMoneyString()}";
      _informationLabel.Text = infoText;
    }

    public User GetOwner(DatabaseContext dbContext = null)
    {
      if (dbContext == null)
      {
        using (dbContext = new DatabaseContext())
        {
          return dbContext.Users.FirstOrDefault(u => u.BusinessId == Id);
        }
      }
      else
      {
        return dbContext.Users.FirstOrDefault(u => u.BusinessId == Id);
      }
    }

    public abstract void Load();
  }
}
