#include <algorithm>
#include <cmath>

#include "IconsFontAwesome6.h"
#include "application/gui_application.h"
#include "layout.h"
#include "localization.h"
#include "rd_log.h"

namespace crossdesk {

namespace {
int CountDigits(int number) {
  if (number == 0)
    return 1;
  return (int)std::floor(std::log10(std::abs(number))) + 1;
}

int BitrateDisplay(int bitrate) {
  int num_of_digits = CountDigits(bitrate);
  if (num_of_digits <= 3) {
    ImGui::Text("%d bps", bitrate);
  } else if (num_of_digits > 3 && num_of_digits <= 6) {
    ImGui::Text("%d kbps", bitrate / 1000);
  } else {
    ImGui::Text("%.1f mbps", bitrate / 1000000.0f);
  }
  return 0;
}
} // namespace

int GuiApplication::FileTransferWindow(
    std::shared_ptr<RemoteSession> &props) {
  FileTransferState *state = &transfers_.state_for(props);
  state->file_transfer_window_hovered_ = false;

  // Only show window if there are files in transfer list or currently
  // transferring
  std::vector<RemoteSession::FileTransferInfo> file_list;
  {
    std::lock_guard<std::mutex> lock(state->file_transfer_list_mutex_);
    file_list = state->file_transfer_list_;
  }

  // Sort file list: Sending first, then Completed, then Queued, then Failed
  std::sort(
      file_list.begin(), file_list.end(),
      [](const RemoteSession::FileTransferInfo &a,
         const RemoteSession::FileTransferInfo &b) {
        // Priority: Sending > Completed > Queued > Failed
        auto get_priority =
            [](RemoteSession::FileTransferStatus status) {
              switch (status) {
              case RemoteSession::FileTransferStatus::Sending:
                return 0;
              case RemoteSession::FileTransferStatus::Completed:
                return 1;
              case RemoteSession::FileTransferStatus::Queued:
                return 2;
              case RemoteSession::FileTransferStatus::Failed:
                return 3;
              }
              return 3;
            };
        return get_priority(a.status) < get_priority(b.status);
      });

  // Only show window if file_transfer_window_visible_ is true
  // Window can be closed by user even during transfer
  // It will be reopened automatically when:
  // 1. A file transfer completes (via FileTransferManager)
  // 2. FileTransferManager starts the next queued file.
  if (!state->file_transfer_window_visible_) {
    return 0;
  }

  // Position window at bottom-left of stream window
  // Adjust window size based on number of files
  float file_transfer_window_width = main_window_width_ * 0.6f;
  float file_transfer_window_height =
      main_window_height_ * 0.3f; // Dynamic height
  float pos_x = file_transfer_window_width * 0.05f;
  float pos_y = stream_window_height_ - file_transfer_window_height -
                file_transfer_window_width * 0.05;

  const ImVec2 mouse_pos = ImGui::GetMousePos();
  const bool mouse_in_window_rect =
      mouse_pos.x >= pos_x &&
      mouse_pos.x <= pos_x + file_transfer_window_width &&
      mouse_pos.y >= pos_y &&
      mouse_pos.y <= pos_y + file_transfer_window_height;

  ImGui::SetNextWindowPos(ImVec2(pos_x, pos_y), ImGuiCond_Always);
  ImGui::SetNextWindowSize(
      ImVec2(file_transfer_window_width, file_transfer_window_height),
      ImGuiCond_Always);
  if (mouse_in_window_rect) {
    ImGui::SetNextWindowFocus();
  }

  // Set Chinese font for proper display
  const bool has_chinese_font = stream_windows_system_chinese_font_ != nullptr;
  if (has_chinese_font) {
    ImGui::PushFont(stream_windows_system_chinese_font_);
  }

  ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, window_rounding_ * 0.5f);
  ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 1.0f);
  ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(1.0f, 1.0f, 1.0f, 0.9f));
  ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0.0f, 0.0f, 0.0f, 0.3f));
  ImGui::PushStyleColor(ImGuiCol_TitleBg, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
  ImGui::PushStyleColor(ImGuiCol_TitleBgActive, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));

  ImGui::SetWindowFontScale(0.5f);
  bool window_opened = true;
  const bool show_contents = ImGui::Begin(
      localization::file_transfer_progress[localization_language_index_]
          .c_str(),
      &window_opened,
      ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
          ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings |
          ImGuiWindowFlags_NoScrollbar);
  ImGui::PopStyleColor(4);
  ImGui::PopStyleVar(2);

  state->file_transfer_window_hovered_ =
      mouse_in_window_rect ||
      ImGui::IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows);

  if (!window_opened) {
    state->file_transfer_window_visible_ = false;
  }

  if (show_contents && window_opened) {
    ImGui::SetWindowFontScale(1.0f);
    ImGui::SetWindowFontScale(0.5f);

    // Display file list
    if (file_list.empty()) {
      ImGui::Text("No files in transfer queue");
    } else {
      // Use a scrollable child window for the file list
      ImGui::SetWindowFontScale(0.5f);
      ImGui::BeginChild(
          "FileList", ImVec2(0, file_transfer_window_height * 0.75f),
          ImGuiChildFlags_Borders, ImGuiWindowFlags_HorizontalScrollbar);
      ImGui::SetWindowFontScale(1.0f);
      ImGui::SetWindowFontScale(0.5f);

      for (size_t i = 0; i < file_list.size(); ++i) {
        const auto &info = file_list[i];
        ImGui::PushID(static_cast<int>(i));

        // Status icon and file name
        const char *status_icon = "";
        ImVec4 status_color(0.5f, 0.5f, 0.5f, 1.0f);
        const char *status_text = "";

        switch (info.status) {
        case RemoteSession::FileTransferStatus::Queued:
          status_icon = ICON_FA_CLOCK;
          status_color =
              ImVec4(0.5f, 0.6f, 0.7f, 1.0f); // Common blue-gray for queued
          status_text =
              localization::queued[localization_language_index_].c_str();
          break;
        case RemoteSession::FileTransferStatus::Sending:
          status_icon = ICON_FA_ARROW_UP;
          status_color = ImVec4(0.2f, 0.6f, 1.0f, 1.0f);
          status_text =
              localization::sending[localization_language_index_].c_str();
          break;
        case RemoteSession::FileTransferStatus::Completed:
          status_icon = ICON_FA_CHECK;
          status_color = ImVec4(0.0f, 0.8f, 0.0f, 1.0f);
          status_text =
              localization::completed[localization_language_index_].c_str();
          break;
        case RemoteSession::FileTransferStatus::Failed:
          status_icon = ICON_FA_XMARK;
          status_color = ImVec4(1.0f, 0.2f, 0.2f, 1.0f);
          status_text =
              localization::failed[localization_language_index_].c_str();
          break;
        }

        ImGui::TextColored(status_color, "%s", status_icon);
        ImGui::SameLine();
        ImGui::Text("%s", info.file_name.c_str());
        ImGui::SameLine();
        ImGui::TextColored(status_color, "%s", status_text);

        // Progress bar for sending files
        if (info.status ==
                RemoteSession::FileTransferStatus::Sending &&
            info.file_size > 0) {
          float progress = static_cast<float>(info.sent_bytes) /
                           static_cast<float>(info.file_size);
          progress = (std::max)(0.0f, (std::min)(1.0f, progress));

          float text_height = ImGui::GetTextLineHeight();
          ImGui::ProgressBar(
              progress, ImVec2(file_transfer_window_width * 0.5f, text_height),
              "");
          ImGui::SameLine();

          ImGui::Text("%.1f%%", progress * 100.0f);
          ImGui::SameLine();

          float speed_x_pos = file_transfer_window_width * 0.65f;
          ImGui::SetCursorPosX(speed_x_pos);
          BitrateDisplay(static_cast<int>(info.rate_bps));
        } else if (info.status ==
                   RemoteSession::FileTransferStatus::Completed) {
          // Show completed size
          char size_str[64];
          if (info.file_size < 1024) {
            snprintf(size_str, sizeof(size_str), "%llu B",
                     (unsigned long long)info.file_size);
          } else if (info.file_size < 1024 * 1024) {
            snprintf(size_str, sizeof(size_str), "%.2f KB",
                     info.file_size / 1024.0f);
          } else {
            snprintf(size_str, sizeof(size_str), "%.2f MB",
                     info.file_size / (1024.0f * 1024.0f));
          }
          ImGui::Text("Size: %s", size_str);
        }

        ImGui::PopID();
        ImGui::Spacing();
      }

      ImGui::SetWindowFontScale(1.0f);
      ImGui::SetWindowFontScale(0.5f);
      ImGui::EndChild();
      ImGui::SetWindowFontScale(1.0f);
    }
    ImGui::SetWindowFontScale(1.0f);
    ImGui::SetWindowFontScale(0.5f);
  }

  ImGui::End();
  ImGui::SetWindowFontScale(1.0f);

  if (has_chinese_font) {
    ImGui::PopFont();
  }

  return 0;
}

} // namespace crossdesk
