using Sunfish.Config;

namespace Sunfish.Cli;

/// <summary>sunfish-cli share add|set|del|list: shares del fichero de configuracion.</summary>
internal static class ShareCommands
{
    public static int Run(string[] args)
    {
        string? configPath = null;
        var rest = new List<string>();
        for (int i = 0; i < args.Length; i++)
        {
            if (args[i] is "-c" or "--config" && i + 1 < args.Length)
                configPath = args[++i];
            else if (args[i] == "--lang" && i + 1 < args.Length)
                Strings.Force(args[++i]);
            else
                rest.Add(args[i]);
        }
        if (rest.Count == 0)
            return Usage();

        string path = ConfigLocator.Find(configPath) ?? ConfigLocator.PortablePath;
        var config = File.Exists(path) ? SunfishConfig.Load(path) : new SunfishConfig { FilePath = path };
        string verb = rest[0];

        if (verb == "list")
        {
            if (config.Shares.Count == 0)
                Console.WriteLine(Strings.AppNoShares);
            foreach (var s in config.Shares)
            {
                string flags = string.Join(' ', new[]
                {
                    s.Enabled ? "" : "(off)", s.Listing ? "listing" : "", s.Upload ? "upload" : "", s.Overwrite ? "overwrite" : "",
                    s.Rename ? "rename" : "", s.Delete ? "delete" : "", s.Zip ? "zip" : "",
                    s.Users.Count > 0 ? "users=" + string.Join(',', s.Users) : "",
                }.Where(f => f.Length > 0));
                Console.WriteLine($"{s.Name}  {s.Location}  {s.Path}  {flags}");
            }
            return 0;
        }
        if (rest.Count < 2)
            return Usage();

        string name = rest[1];
        var share = config.Shares.FirstOrDefault(s => s.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
        switch (verb)
        {
            case "add":
            {
                if (rest.Count < 3)
                    return Usage();
                if (!ShareSettings.IsValidName(name))
                    return Fail(Strings.ErrorBadName(name));
                if (share is not null)
                    return Fail(Strings.ErrorNameInUse(name));
                string folder = Path.GetFullPath(rest[2]);
                if (!Directory.Exists(folder))
                    return Fail(Strings.ErrorNotAFolder(folder));
                share = new ShareConfig { Name = name, Path = folder, Location = ShareSettings.SuggestLocation(config, name) };
                if (ApplySettings(share, rest.Skip(3)) is { } error)
                    return Fail(error);
                if (config.Shares.Any(s => s.Enabled && s.Location.Equals(share.Location, StringComparison.OrdinalIgnoreCase)))
                    return Fail(Strings.ErrorNameInUse(share.Location));
                config.Shares.Add(share);
                break;
            }
            case "set":
            {
                if (share is null)
                    return Fail(Texts.ShareMissing(name));
                if (ApplySettings(share, rest.Skip(2)) is { } error)
                    return Fail(error);
                break;
            }
            case "del":
                if (share is null)
                    return Fail(Texts.ShareMissing(name));
                config.Shares.Remove(share);
                break;
            default:
                return Usage();
        }
        config.Save(path);
        Console.WriteLine(Texts.ShareSaved(name, path));
        return 0;
    }

    /// <summary>Opciones "Clave=valor" (las del INI) o "--location /x".</summary>
    private static string? ApplySettings(ShareConfig share, IEnumerable<string> settings)
    {
        var list = settings.ToList();
        for (int i = 0; i < list.Count; i++)
        {
            string item = list[i];
            if (item == "--location" && i + 1 < list.Count)
            {
                if (ShareSettings.TrySet(share, "Location", list[++i]) is { } bad)
                    return bad;
                continue;
            }
            int eq = item.IndexOf('=');
            if (eq <= 0)
                return Strings.UnknownShareKey(item);
            if (ShareSettings.TrySet(share, item[..eq], item[(eq + 1)..]) is { } error)
                return error;
        }
        return null;
    }

    private static int Usage()
    {
        Console.Error.WriteLine(Texts.ShareUsage);
        return 1;
    }

    private static int Fail(string message)
    {
        Console.Error.WriteLine(message);
        return 1;
    }
}
