#pragma once

#include <git2.h>
#include <chrono>
#include <map>
#include <set>
#include <string>
#include <vector>

enum class RefKind { local, remote, tag };

struct RefBadge {
    std::string name;
    RefKind kind = RefKind::local;
    bool current = false;
    bool worktree = false;
    bool upstream = false;
};

enum class FileChangeKind { added, modified, deleted, renamed, other };

struct ChangedFile {
    std::string path;
    FileChangeKind kind = FileChangeKind::other;
};

struct WorkingFile {
    std::string path;
    FileChangeKind kind = FileChangeKind::other;
    bool staged = false;
};

struct BranchDivergence {
    size_t ahead = 0;
    size_t behind = 0;
};

enum class ToolbarHistoryActionKind { none, checkout, commit };

struct ToolbarHistoryAction {
    ToolbarHistoryActionKind kind = ToolbarHistoryActionKind::none;
    bool available = false;
    std::string tooltip;
    std::string source;
    std::string target;
    std::string summary;
};

struct CommitInfo {
    git_oid oid{};
    std::string short_id;
    std::string summary;
    std::string description;
    std::string author;
    std::string email;
    std::string date;
    int parents = 0;
    int lane = 0;
    int graph_color = 0;
    std::vector<git_oid> parent_ids;
    std::vector<RefBadge> refs;
    std::vector<ChangedFile> changed_files;
    std::vector<ChangedFile> all_files;
    bool changes_loaded = false;
    bool all_files_loaded = false;
};

struct RepositoryView {
    git_repository* repo = nullptr;
    git_revwalk* commit_walk = nullptr;
    bool history_exhausted = false;
    bool credentials_checked = false;
    std::string path;
    std::string name = "New Tab";
    std::string branch = "detached";
    std::vector<std::string> local_branches;
    std::vector<std::string> remote_branches;
    std::map<std::string, BranchDivergence> local_branch_divergence;
    std::map<std::string, BranchDivergence> remote_branch_divergence;
    std::vector<std::string> remotes;
    std::vector<std::string> worktrees;
    std::set<std::string> worktree_branches;
    std::vector<std::string> submodules;
    std::map<std::string, unsigned int> submodule_statuses;
    std::vector<CommitInfo> commits;
    std::vector<WorkingFile> working_files;
    int selected_commit = 0;
    int scroll_to_commit = -1;
    std::chrono::steady_clock::time_point last_background_refresh{};
    bool pending_background_refresh = false;
    ToolbarHistoryAction undo_action;
    ToolbarHistoryAction redo_action;

    RepositoryView() = default;
    ~RepositoryView() { close(); }
    RepositoryView(const RepositoryView&) = delete;
    RepositoryView& operator=(const RepositoryView&) = delete;

    void close() {
        if (commit_walk) git_revwalk_free(commit_walk);
        commit_walk = nullptr;
        if (repo) git_repository_free(repo);
        repo = nullptr;
        credentials_checked = false;
    }
};
