/*
 * src/commands/info/directory.cpp
 * include/commands/info/directory.h
 *
 * The logic for getting and printing info about a directory
 *
 * Copyright (C) 2026 Giuliano De Amicis. All rights reserved.
 * This software is licensed under the GPL-3.0-or-later.
 * See LICENSE file for details.
 */

#include "commands/info/directory.h"

#include <filesystem>
#include <ftxui/dom/elements.hpp>
#include <ftxui/screen/screen.hpp>
#include <iostream>
#include <map>
#include <string>
#include <unordered_set>
#include <vector>

#include "config.h"
#include "fs/Directory.h"
#include "fs/get_directories_entries.h"
#include "fs/operations.h"
#include "ftxui/dom/node.hpp"
#include "git/GitRepo.h"
#include "theme.h"
#include "utility/join.h"
#include "utility/most_common.h"
#include "utility/regex.h"

namespace fima {

namespace info {

void
dir(const std::filesystem::directory_entry& path,
    const bool& verbose,
    const fima::git::GitRepo& repo)
{
    using namespace ftxui;

    fima::fs::Directory dir(path);

    dir.metadata.set_size();
    dir.set_stats(repo);
    dir.set_number_of_files(repo);

    auto draw_window_entry = [&](const std::string& title, const Element& value) {
        return hbox(text(title) | bold | color(fima::theme::theme.primary.get_color_for_tui()),
                    value | color(fima::theme::theme.secondary.get_color_for_tui()));
    };

    Element document{};

    if (verbose) {
        std::vector<std::filesystem::directory_entry> files{ fima::fs::get_files_for_cloc(
          path, repo, true, true, fima::config::DEFAULT_DIRS_TO_IGNORE) };

        std::unordered_set<std::string> extensions_set{};
        std::vector<std::string> extensions_vec{};

        std::map<size_t, std::filesystem::path> size_path_map{};

        for (const std::filesystem::directory_entry& item : files) {
            std::filesystem::path path = item.path();
            std::string extension      = path.extension().string();

            size_t size = fima::fs::operations::get_item_size(path);

            size_path_map[size] = path;

            if (extension != "") {
                extensions_set.insert(extension);
                extensions_vec.push_back(extension);
            }
        }

        std::string extensions{ fima::utility::join(extensions_set, ", ") };

        std::string most_common_extension{ fima::utility::most_common(extensions_vec.begin(),
                                                                      extensions_vec.end()) };

        auto biggest_file_size_tmp{ std::prev(size_path_map.end())->first };

        std::string biggest_file_path{ std::filesystem::relative(
          std::prev(size_path_map.end())->second) };
        std::string biggest_file_size{ fima::fs::operations::make_size_readable(
          biggest_file_size_tmp) };

        document = vbox(
          // header
          border(
            hbox(text("DINFO: ") | bold | color(fima::theme::theme.primary.get_color_for_tui()),
                 text(dir.metadata.get_path().string()) |
                   color(fima::theme::theme.secondary.get_color_for_tui()),
                 text((dir.metadata.get_path().string().ends_with("/") ? "" : "/")) |
                   color(fima::theme::theme.secondary.get_color_for_tui()),
                 text((dir.metadata.get_is_hidden() ? " (hidden)" : "")) | flex,
                 text(" " + dir.metadata.get_icon() + " "))) |
            color(fima::theme::theme.border.get_color_for_tui()),

          hbox(
            window(text(" INFO ") | bold,
                   vbox(draw_window_entry("Size: ", text(dir.metadata.get_size_with_extension())),
                        draw_window_entry("Permissions: ", dir.metadata.get_permissions_tui()),
                        draw_window_entry("Number of files: ",
                                          text(std::to_string(dir.get_number_of_files()))),
                        draw_window_entry("Last modification date: ",
                                          text(dir.metadata.get_last_modification_date())))) |
              color(fima::theme::theme.border.get_color_for_tui()) | flex,

            window(
              text(" LOC ") | bold,
              vbox(draw_window_entry("Code: ", text(std::to_string(dir.stats.get_code()))),
                   draw_window_entry("Comments: ", text(std::to_string(dir.stats.get_comments()))),
                   draw_window_entry("Blank lines: ",
                                     text(std::to_string(dir.stats.get_blank_lines()))),
                   draw_window_entry("Total: ", text(std::to_string(dir.stats.get_total()))))) |
              color(fima::theme::theme.border.get_color_for_tui())),
          window(text(" VERBOSE ") | bold,
                 vbox(draw_window_entry("Extensions: ", text(extensions)),
                      draw_window_entry("Most common extension: ", text(most_common_extension)),
                      draw_window_entry(
                        "Biggest file: ",
                        hbox(text(biggest_file_path), text(" (" + biggest_file_size + ")"))))) |
            color(fima::theme::theme.border.get_color_for_tui()));
    } else {
        document = vbox(
          // header
          border(
            hbox(text("DINFO: ") | bold | color(fima::theme::theme.primary.get_color_for_tui()),
                 text(dir.metadata.get_path().string()) |
                   color(fima::theme::theme.secondary.get_color_for_tui()),
                 text((dir.metadata.get_path().string().ends_with("/") ? "" : "/")) |
                   color(fima::theme::theme.secondary.get_color_for_tui()),
                 text((dir.metadata.get_is_hidden() ? " (hidden)" : "")) | flex,
                 text("  " + dir.metadata.get_icon() + " "))) |
            color(fima::theme::theme.border.get_color_for_tui()),

          hbox(
            window(text(" INFO ") | bold,
                   vbox(draw_window_entry("Size: ", text(dir.metadata.get_size_with_extension())),
                        draw_window_entry("Permissions: ", dir.metadata.get_permissions_tui()),
                        draw_window_entry("Number of files: ",
                                          text(std::to_string(dir.get_number_of_files()))),
                        draw_window_entry("Last modification date: ",
                                          text(dir.metadata.get_last_modification_date())))) |
              color(fima::theme::theme.border.get_color_for_tui()) | flex,

            window(
              text(" LOC ") | bold,
              vbox(draw_window_entry("Code: ", text(std::to_string(dir.stats.get_code()))),
                   draw_window_entry("Comments: ", text(std::to_string(dir.stats.get_comments()))),
                   draw_window_entry("Blank lines: ",
                                     text(std::to_string(dir.stats.get_blank_lines()))),
                   draw_window_entry("Total: ", text(std::to_string(dir.stats.get_total()))))) |
              color(fima::theme::theme.border.get_color_for_tui())));
    }

    auto screen = Screen::Create(Dimension::Fit(document));
    Render(screen, document);
    screen.Print();

    std::cout << '\n';
}

} // namespace info

} // namespace fima
