using SharpChat.SockChat.S2CPackets;

namespace SharpChat.ClientCommands;

public class CreateChannelClientCommand : ClientCommand {
    public bool IsMatch(ClientCommandContext ctx) {
        return ctx.NameEquals("create");
    }

    public async Task Dispatch(ClientCommandContext ctx) {
        long msgId = ctx.Chat.RandomSnowflake.Next();

        if(!ctx.User.Can(UserPermissions.CreateChannel)) {
            await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.COMMAND_NOT_ALLOWED, true, $"/{ctx.Name}"));
            return;
        }

        string firstArg = ctx.Args.First();

        bool createChanHasHierarchy;
        if(ctx.Args.Length < 1 || (createChanHasHierarchy = firstArg.All(char.IsDigit) && ctx.Args.Length < 2)) {
            await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.COMMAND_FORMAT_ERROR));
            return;
        }

        int createChanHierarchy = 0;
        if(createChanHasHierarchy)
            if(!int.TryParse(firstArg, out createChanHierarchy))
                createChanHierarchy = 0;

        if(createChanHierarchy > ctx.User.Rank) {
            await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.INSUFFICIENT_HIERARCHY));
            return;
        }

        string createChanName = string.Join('_', ctx.Args.Skip(createChanHasHierarchy ? 1 : 0));

        if(!Channel.CheckName(createChanName)) {
            await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_NAME_INVALID));
            return;
        }

        if(ctx.Chat.Channels.Any(c => c.NameEquals(createChanName))) {
            await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_ALREADY_EXISTS, true, createChanName));
            return;
        }

        Channel createChan = new(
            createChanName,
            isTemporary: !ctx.User.Can(UserPermissions.SetChannelPermanent),
            rank: createChanHierarchy,
            ownerId: ctx.User.UserId
        );

        ctx.Chat.Channels.Add(createChan);
        foreach(User ccu in ctx.Chat.Users.Where(u => u.Rank >= ctx.Channel.Rank))
            await ctx.Chat.SendTo(ccu, new ChannelCreateS2CPacket(createChan.Name, createChan.HasPassword, createChan.IsTemporary));

        await ctx.Chat.SwitchChannel(ctx.User, createChan, createChan.Password);
        await ctx.Chat.SendTo(ctx.User, new CommandResponseS2CPacket(msgId, LCR.CHANNEL_CREATED, false, createChan.Name));
    }
}