#include "panels.h"
#include "data.h"

#include <imgui.h>
#include <imgui_internal.h>
#include <map>
#include <mutex>
#include <string>
#include <utility>
#include <vector>

#include "core/icons_tabler.h"

namespace kanban {

static const char* k_columns[] = {"ideas", "pendiente", "in-progress", "completado"};
static const char* k_column_icons[] = {TI_BULB, TI_CLIPBOARD, TI_TOOLS, TI_CIRCLE_CHECK};
static const int   k_n_columns = sizeof(k_columns) / sizeof(k_columns[0]);

// Map flow status (free-form) → one of the 4 board columns.
static int flow_column_index(const std::string& s) {
    if (s == "draft" || s == "ideas")             return 0;
    if (s == "active" || s == "in-progress")      return 2;
    if (s == "done" || s == "completed" || s == "completado") return 3;
    // pending, paused, "" → pendiente
    return 1;
}

static ImU32 priority_color(const std::string& p) {
    if (p == "critica") return IM_COL32(255, 80, 80, 255);
    if (p == "alta")    return IM_COL32(255, 165, 0, 255);
    if (p == "media")   return IM_COL32(120, 170, 255, 255);
    if (p == "baja")    return IM_COL32(140, 140, 140, 255);
    return IM_COL32(180, 180, 180, 255);
}

static ImU32 status_tint(const std::string& s) {
    if (s == "bloqueado") return IM_COL32(120,  60,  60, 200);
    if (s == "completado") return IM_COL32( 60, 110,  60, 100);
    if (s == "in-progress") return IM_COL32( 70,  90, 140, 100);
    if (s == "ideas")     return IM_COL32(110,  90, 140, 100);
    return IM_COL32(60, 60, 70, 100);
}

static void draw_card(const Issue& iss) {
    ImGui::PushID(iss.id.c_str());

    const float card_h = 110.0f;
    ImVec2 size(0.0f, card_h);
    ImU32 bg = status_tint(iss.status);
    ImGui::PushStyleColor(ImGuiCol_ChildBg, bg);
    ImGui::BeginChild("card", size, true, ImGuiWindowFlags_NoScrollbar);

    // Top row: id  ·  priority dot  ·  agent icon (right-aligned)  ·  block badge if blocked
    ImGui::TextColored(ImColor(200, 200, 200, 255), "%s", iss.id.c_str());
    ImGui::SameLine();
    {
        ImVec2 cur = ImGui::GetCursorScreenPos();
        ImU32 c = priority_color(iss.priority);
        ImDrawList* dl = ImGui::GetWindowDrawList();
        float r = 5.0f;
        dl->AddCircleFilled(ImVec2(cur.x + r, cur.y + r + 2), r, c);
        ImGui::Dummy(ImVec2(2 * r + 4, 2 * r));
        ImGui::SameLine();
        ImGui::TextColored(ImColor(180, 180, 180, 255), "%s", iss.priority.c_str());
    }

    // Right-aligned indicators (agent active + blocked).
    {
        std::string indicators;
        bool active = is_agent_active(iss.id);
        if (active)              indicators += TI_ROBOT;
        if (iss.status == "bloqueado") { if (!indicators.empty()) indicators += " "; indicators += TI_LOCK; }
        if (!indicators.empty()) {
            ImVec2 ts = ImGui::CalcTextSize(indicators.c_str());
            float avail = ImGui::GetContentRegionAvail().x;
            ImGui::SameLine(0, avail - ts.x - 4);
            if (active) {
                ImGui::TextColored(ImColor(120, 220, 120, 255), "%s", indicators.c_str());
            } else {
                ImGui::TextColored(ImColor(220, 120, 120, 255), "%s", indicators.c_str());
            }
        }
    }

    // Title (2-3 lines)
    std::string t = iss.title;
    if (t.size() > 140) t = t.substr(0, 137) + "...";
    ImGui::TextWrapped("%s", t.c_str());

    // Bottom: first domain chip
    if (!iss.domain.empty()) {
        ImGui::TextColored(ImColor(140, 200, 255, 255), "%s %s", TI_TAG, iss.domain[0].c_str());
    }

    ImGui::EndChild();
    ImGui::PopStyleColor();

    // Click → load detail
    if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
        refresh_issue_detail(iss.id);
    }

    // Drag source
    if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
        ImGui::SetDragDropPayload("KANBAN_ISSUE", iss.id.c_str(), iss.id.size() + 1);
        ImGui::Text("%s %s", iss.id.c_str(), t.c_str());
        ImGui::EndDragDropSource();
    }

    // Right-click context menu
    if (ImGui::BeginPopupContextItem("card_ctx")) {
        if (iss.status == "bloqueado") {
            if (ImGui::MenuItem(TI_LOCK_OPEN " Unblock (→ pendiente)")) {
                patch_issue_status(iss.id, "pendiente");
            }
        } else {
            if (ImGui::MenuItem(TI_LOCK " Block this issue")) {
                patch_issue_status(iss.id, "bloqueado");
            }
        }
        ImGui::Separator();
        if (ImGui::MenuItem(TI_PLAYER_PLAY " Launch agent (fix-issue)", nullptr, false, !is_agent_active(iss.id))) {
            launch_agent(iss.id);
        }
        if (is_agent_active(iss.id)) {
            ImGui::TextDisabled(TI_ROBOT " agent already running");
        }
        ImGui::Separator();
        if (ImGui::MenuItem("Move → ideas"))       patch_issue_status(iss.id, "ideas");
        if (ImGui::MenuItem("Move → pendiente"))   patch_issue_status(iss.id, "pendiente");
        if (ImGui::MenuItem("Move → in-progress")) patch_issue_status(iss.id, "in-progress");
        if (ImGui::MenuItem("Move → completado")) patch_issue_status(iss.id, "completado");
        ImGui::EndPopup();
    }

    ImGui::PopID();
}

static void draw_flow_card(const Flow& fl, int child_issue_count) {
    ImGui::PushID(("flow_" + fl.id).c_str());

    const float card_h = 88.0f;
    ImVec2 size(0.0f, card_h);
    ImU32 bg = IM_COL32(80, 60, 110, 100);
    ImGui::PushStyleColor(ImGuiCol_ChildBg, bg);
    ImGui::BeginChild("flow_card", size, true, ImGuiWindowFlags_NoScrollbar);

    ImGui::TextColored(ImColor(190, 170, 230, 255), "%s flow %s", TI_GIT_BRANCH, fl.id.c_str());
    {
        ImVec2 ts = ImGui::CalcTextSize("999 issues");
        float avail = ImGui::GetContentRegionAvail().x;
        ImGui::SameLine(0, avail - ts.x - 4);
        ImGui::TextDisabled("%d issues", child_issue_count);
    }

    std::string t = fl.title;
    if (t.size() > 140) t = t.substr(0, 137) + "...";
    ImGui::TextWrapped("%s", t.c_str());

    if (!fl.tags.empty()) {
        ImGui::TextColored(ImColor(140, 200, 255, 255), "%s %s", TI_TAG, fl.tags[0].c_str());
    }

    ImGui::EndChild();
    ImGui::PopStyleColor();

    // Click → set selected_issue_id to first child issue (best UX guess).
    if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
        std::lock_guard<std::mutex> g(state().mu);
        for (const auto& iss : state().issues) {
            if (iss.flow == fl.id) {
                state().selected_issue_id = iss.id;
                state().selected_issue_detail = iss;
                break;
            }
        }
    }
    if (ImGui::BeginPopupContextItem("flow_ctx")) {
        ImGui::TextDisabled("flow %s — %d issues", fl.id.c_str(), child_issue_count);
        ImGui::Separator();
        ImGui::TextDisabled("(no actions; edit %s manually)", fl.file_path.c_str());
        ImGui::EndPopup();
    }

    ImGui::PopID();
}

static void draw_column(const char* status_key, const char* icon,
                        std::vector<const Issue*>& issues,
                        std::vector<std::pair<const Flow*, int>>& flows) {
    ImGui::TableNextColumn();
    ImGui::PushFont(nullptr);
    size_t total = issues.size() + flows.size();
    ImGui::TextColored(ImColor(220, 220, 220, 255), "%s %s  (%zu)", icon, status_key, total);
    ImGui::PopFont();
    ImGui::Separator();

    ImVec2 region = ImGui::GetContentRegionAvail();
    ImGui::BeginChild((std::string("col_") + status_key).c_str(), region, false);

    // Issues first (heavier visual), then flows (lighter).
    for (const auto* iss : issues) {
        draw_card(*iss);
    }
    for (const auto& [fl, cnt] : flows) {
        draw_flow_card(*fl, cnt);
    }

    ImGui::InvisibleButton("col_drop", ImVec2(-1, 24));
    if (ImGui::BeginDragDropTarget()) {
        if (const ImGuiPayload* p = ImGui::AcceptDragDropPayload("KANBAN_ISSUE")) {
            std::string id((const char*)p->Data, p->DataSize - 1);
            patch_issue_status(id, status_key);
        }
        ImGui::EndDragDropTarget();
    }
    ImGui::EndChild();

    if (ImGui::BeginDragDropTarget()) {
        if (const ImGuiPayload* p = ImGui::AcceptDragDropPayload("KANBAN_ISSUE")) {
            std::string id((const char*)p->Data, p->DataSize - 1);
            patch_issue_status(id, status_key);
        }
        ImGui::EndDragDropTarget();
    }
}

void draw_board() {
    if (!ImGui::Begin(TI_LAYOUT_KANBAN " Board")) {
        ImGui::End();
        return;
    }

    std::vector<Issue> issue_snap;
    std::vector<Flow>  flow_snap;
    bool agent_up = false;
    int  agent_running_count = 0;
    std::string last_launch;
    bool show_issues_flag = true;
    bool show_flows_flag  = true;
    {
        std::lock_guard<std::mutex> g(state().mu);
        issue_snap          = state().issues;
        flow_snap           = state().flows;
        agent_up            = state().agent_runner_up;
        agent_running_count = (int)state().agent_active.size();
        last_launch         = state().last_launch_msg;
        show_issues_flag    = state().filters.show_issues;
        show_flows_flag     = state().filters.show_flows;
    }

    // Bucket issues per column.
    std::vector<std::vector<const Issue*>> issue_buckets(k_n_columns);
    int filtered_out = 0;
    if (show_issues_flag) {
        for (const auto& iss : issue_snap) {
            if (!passes_filters(iss)) {
                filtered_out++;
                continue;
            }
            std::string s = iss.status;
            if (s == "bloqueado") s = "pendiente";
            for (int c = 0; c < k_n_columns; ++c) {
                if (s == k_columns[c]) {
                    issue_buckets[c].push_back(&iss);
                    break;
                }
            }
        }
    }

    // Count children per flow (issues that reference flow_id).
    std::map<std::string, int> flow_child_count;
    for (const auto& iss : issue_snap) {
        if (!iss.flow.empty()) flow_child_count[iss.flow]++;
    }

    // Bucket flows per column using flow_column_index.
    std::vector<std::vector<std::pair<const Flow*, int>>> flow_buckets(k_n_columns);
    if (show_flows_flag) {
        for (const auto& fl : flow_snap) {
            int col = flow_column_index(fl.status);
            int cnt = flow_child_count.count(fl.id) ? flow_child_count[fl.id] : 0;
            flow_buckets[col].push_back({&fl, cnt});
        }
    }

    // Header line
    size_t total_visible = 0;
    for (int c = 0; c < k_n_columns; ++c) total_visible += issue_buckets[c].size() + flow_buckets[c].size();
    ImGui::Text("%zu issues + %zu flows — %d filtered out — visible %zu",
                issue_snap.size(), flow_snap.size(), filtered_out, total_visible);
    ImGui::SameLine();
    ImGui::TextDisabled(" | ");
    ImGui::SameLine();
    if (agent_up) {
        ImGui::TextColored(ImColor(120, 220, 120, 255), TI_ROBOT " agent_runner_api OK — %d active", agent_running_count);
    } else {
        ImGui::TextColored(ImColor(220, 140, 140, 255), TI_ROBOT " agent_runner_api offline");
    }
    if (!last_launch.empty()) {
        ImGui::SameLine();
        ImGui::TextDisabled(" | %s", last_launch.c_str());
    }
    ImGui::Separator();

    if (ImGui::BeginTable("board_table", k_n_columns,
                         ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchSame)) {
        ImGui::TableNextRow();
        for (int c = 0; c < k_n_columns; ++c) {
            draw_column(k_columns[c], k_column_icons[c], issue_buckets[c], flow_buckets[c]);
        }
        ImGui::EndTable();
    }

    ImGui::End();
}

}  // namespace kanban
