#include "command_registry.hpp"
#include "directories.hpp"
#include "shared_commands.hpp"
#include "templates.hpp"

#include "utils/assert.hpp"
#include "utils/utils.hpp"
#include "services.hpp"

namespace dropshell
{

    int create_service_handler(const CommandContext &ctx);
    bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, bool silent);
    void create_service_autocomplete(const CommandContext &ctx);

    static std::vector<std::string> create_service_name_list = {"create-service"};

    // Static registration
    struct CreateServiceCommandRegister
    {
        CreateServiceCommandRegister()
        {
            CommandRegistry::instance().register_command({create_service_name_list,
                                                          create_service_handler,
                                                          create_service_autocomplete,
                                                          false, // hidden
                                                          true,  // requires_config
                                                          true,  // requires_install
                                                          3,     // min_args (after command)
                                                          3,     // max_args (after command)
                                                          "create-service SERVER SERVICE TEMPLATE",
                                                          "Create a service on a server.",
                                                          // heredoc
                                                          R"(
            Create a service on a server.
            create-service SERVER SERVICE TEMPLATE    create the given service on the given server.
                )"});
        }
    } create_service_command_register;

    int create_service_handler(const CommandContext &ctx)
    {
        std::string server = safearg(ctx.args, 0);
        std::string service = safearg(ctx.args, 1);
        std::string template_name = safearg(ctx.args, 2);

        return create_service(server, template_name, service, false) ? 0 : 1;
    }

    void create_service_autocomplete(const CommandContext &ctx)
    {
        if (ctx.args.size() < 2)
            shared_commands::std_autocomplete(ctx);
        else
        {
            if (ctx.args.size() == 2)
            {
                std::set<std::string> templates = gTemplateManager().get_template_list();
                for (const auto &template_name : templates)
                    std::cout << template_name << std::endl;
            }
        }
    }

    bool create_service(const std::string &server_name, const std::string &template_name, const std::string &service_name, bool silent)
    {
        if (server_name.empty() || template_name.empty() || service_name.empty())
            return false;

        std::string service_dir = localpath::service(server_name, service_name);

        if (service_dir.empty())
        {
            if (!silent)
            {
                std::cerr << "Error: Couldn't locate server " << server_name << " in any config directory" << std::endl;
                std::cerr << "Please check the server name is correct and try again" << std::endl;
                std::cerr << "You can list all servers with 'dropshell servers'" << std::endl;
                std::cerr << "You can create a new server with 'dropshell create-server " << server_name << "'" << std::endl;
            }
            return false;
        }

        if (std::filesystem::exists(service_dir))
        {
            if (!silent)
            {
                std::cerr << "Error: Service already exists: " << service_name << std::endl;
                std::cerr << "Current service path: " << service_dir << std::endl;
            }
            return false;
        }

        template_info tinfo = gTemplateManager().get_template_info(template_name);
        if (!tinfo.is_set())
        {
            if (!silent)
            {
                std::cerr << "Error: Template '" << template_name << "' not found" << std::endl;
                std::cerr << "Please check the template name is correct and try again" << std::endl;
                std::cerr << "You can list all templates with 'dropshell templates'" << std::endl;
                std::cerr << "You can create a new template with 'dropshell create-template " << template_name << "'" << std::endl;
            }
            return false;
        }

        // check template is all good.
        if (!gTemplateManager().test_template(tinfo.local_template_path()))
        {
            if (!silent)
                std::cerr << "Error: Template '" << template_name << "' is not valid" << std::endl;
            return false;
        }

        // create the service directory
        std::filesystem::create_directory(service_dir);

        // copy the template config files to the service directory
        recursive_copy(tinfo.local_template_path() / "config", service_dir);

        if (!silent)
        {
            std::cout << "Service " << service_name << " created successfully" << std::endl;
            std::cout << std::endl;
            std::cout << "To complete the installation, please:" << std::endl;
            std::cout << "1. edit the service config file:  dropshell edit " << server_name << " " << service_name << std::endl;
            std::cout << "2. install the remote service:    dropshell install " << server_name << " " << service_name << std::endl;
        }
        return true;
    }

} // namespace dropshell