using Microsoft.EntityFrameworkCore;
using Server.DB.Documents;
using Wonderking.Game.Data.Character;
using Wonderking.Packets.Incoming;
using Wonderking.Packets.Outgoing;
using Wonderking.Packets.Outgoing.Data;

namespace Server.PacketHandlers;

using DB;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using NetCoreServer;

public class ChannelSelectionHandler : IPacketHandler<ChannelSelectionPacket>
{
    private readonly IConfiguration _configuration;
    private readonly ILogger<ChannelSelectionHandler> _logger;
    private readonly WonderkingContext _wonderkingContext;

    public ChannelSelectionHandler(IConfiguration configuration, ILogger<ChannelSelectionHandler> logger,
        WonderkingContext wonderkingContext)
    {
        this._configuration = configuration;
        this._logger = logger;
        this._wonderkingContext = wonderkingContext;
    }

    public ChannelSelectionHandler()
    {
    }

    public Task HandleAsync(ChannelSelectionPacket packet, TcpSession session)
    {
        var authSession = (AuthSession)session;
        ChannelSelectionResponsePacket responsePacket;
        CharacterSelectionSetGuildNamePacket guildNameResponsePacket;

        var hasCharacters = this._wonderkingContext.Accounts.Include(account => account.Characters)
            .FirstOrDefault(a => a.Id == authSession.AccountId)?.Characters.Count > 0;
        var testingChars = false;
        if (hasCharacters && !testingChars)
        {
            responsePacket = new ChannelSelectionResponsePacket
            {
                ChannelIsFullFlag = 0,
                Endpoint = "127.0.0.1",
                Port = 12345,
                Characters = this._wonderkingContext.Characters.Where(c => c.AccountId == authSession.AccountId)
                    .Select(c =>
                        new CharacterData
                        {
                            Name = c.Name,
                            Job = c.JobData,
                            Gender = c.Gender,
                            Level = c.Level,
                            Experience = 0,
                            Stats = c.BaseStats,
                            Health = c.Health,
                            Mana = c.Mana,
                            EquippedItems =
                                c.InventoryItems.Where(item => item.ItemType == ItemType.WornEquipment)
                                    .Select(item => item.ItemId)
                                    .ToArray(),
                            EquippedCashItems = c.InventoryItems
                                .Where(item => item.ItemType == ItemType.WornCashEquipment)
                                .Select(item => item.ItemId)
                                .ToArray(),
                        })
                    .ToArray(),
            };

            guildNameResponsePacket = new CharacterSelectionSetGuildNamePacket
            {
                GuildNames = this._wonderkingContext.Characters.Where(c => c.AccountId == authSession.AccountId)
                    .Select(character => character.Guild.Name).ToArray()
            };
        }
        else
        {
            responsePacket = testingChars
                ? CreateTestChannelSelectionResponsePacket()
                : new ChannelSelectionResponsePacket
                {
                    ChannelIsFullFlag = 0,
                    Endpoint = "127.0.0.1",
                    Port = 12345,
                    Characters = Array.Empty<CharacterData>()
                };
            guildNameResponsePacket = new CharacterSelectionSetGuildNamePacket
            {
                GuildNames = new[] { "ABCDEFGHIJKLMNOP", "QRSTUVWXYZ123456", "A Guild Name For" }
            };
        }

        authSession.Send(responsePacket);
        if (guildNameResponsePacket.GuildNames.Length > 0)
        {
            authSession.Send(guildNameResponsePacket);
        }

        return Task.CompletedTask;
    }

    private static ChannelSelectionResponsePacket CreateTestChannelSelectionResponsePacket()
    {
        return new ChannelSelectionResponsePacket
        {
            ChannelIsFullFlag = 0,
            Endpoint = "127.0.0.1",
            Port = 12345,
            Characters = new[]
            {
                new CharacterData
                {
                    Name = "1",
                    Job = new JobData { FirstJob = 1, SecondJob = 0, ThirdJob = 0, FourthJob = 0 },
                    Gender = Gender.Female,
                    Level = ushort.MaxValue - 1,
                    Experience = 255,
                    Stats = new BaseStats
                    {
                        Strength = 5,
                        Dexterity = 5,
                        Intelligence = 5,
                        Vitality = 5,
                        Luck = 5,
                        Wisdom = 5
                    },
                    Health = int.MaxValue - 1,
                    Mana = int.MaxValue - 1,
                    EquippedItems = Enumerable.Repeat((ushort)25, 20).ToArray(),
                    EquippedCashItems = Enumerable.Repeat((ushort)70, 20).ToArray()
                },
                new CharacterData
                {
                    Name = "2",
                    Job = new JobData { FirstJob = 1, SecondJob = 0, ThirdJob = 0, FourthJob = 0 },
                    Gender = Gender.Female,
                    Level = ushort.MaxValue - 1,
                    Experience = 255,
                    Stats = new BaseStats
                    {
                        Strength = 5,
                        Dexterity = 5,
                        Intelligence = 5,
                        Vitality = 5,
                        Luck = 5,
                        Wisdom = 5
                    },
                    Health = int.MaxValue - 1,
                    Mana = int.MaxValue - 1,
                    EquippedItems = Enumerable.Repeat((ushort)35, 20).ToArray(),
                    EquippedCashItems = Enumerable.Repeat((ushort)55, 20).ToArray()
                },
                new CharacterData
                {
                    Name = "3",
                    Job = new JobData { FirstJob = 1, SecondJob = 0, ThirdJob = 0, FourthJob = 0 },
                    Gender = Gender.Female,
                    Level = ushort.MaxValue - 1,
                    Experience = 255,
                    Stats = new BaseStats
                    {
                        Strength = 5,
                        Dexterity = 5,
                        Intelligence = 5,
                        Vitality = 5,
                        Luck = 5,
                        Wisdom = 5
                    },
                    Health = int.MaxValue - 1,
                    Mana = int.MaxValue - 1,
                    EquippedItems = Enumerable.Repeat((ushort)45, 20).ToArray(),
                    EquippedCashItems = Enumerable.Repeat((ushort)65, 20).ToArray()
                }
            },
        };
    }
}