// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_page_handler.h"

#include <stddef.h>

#include <set>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption.mojom.h"
#include "chrome/browser/new_tab_page/modules/v2/tab_resumption/tab_resumption_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/session_sync_service_factory.h"
#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "components/history/core/browser/history_types.h"
#include "components/history/core/browser/mojom/history_types.mojom.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/search/ntp_features.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync_device_info/device_info.h"
#include "components/sync_sessions/open_tabs_ui_delegate.h"
#include "components/sync_sessions/session_sync_service.h"
#include "content/public/browser/web_ui.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/time_format.h"
#include "url/gurl.h"

using history::BrowsingHistoryService;
using history::HistoryService;

const size_t kCategoryBlockListCount = 18;
constexpr std::array<std::string_view, kCategoryBlockListCount>
    kCategoryBlockList{"/g/11b76fyj2r", "/m/09lkz",  "/m/012mj",  "/m/01rbb",
                       "/m/02px0wr",    "/m/028hh",  "/m/034qg",  "/m/034dj",
                       "/m/0jxxt",      "/m/015fwp", "/m/04shl0", "/m/01h6rj",
                       "/m/05qt0",      "/m/06gqm",  "/m/09l0j_", "/m/01pxgq",
                       "/m/0chbx",      "/m/02c66t"};

namespace {
// Name of preference to track list of dismissed tabs.
const char kDismissedTabsPrefName[] = "NewTabPage.TabResumption.DismissedTabs";

std::u16string FormatRelativeTime(const base::Time& time) {
  // Return a time like "1 hour ago", "2 days ago", etc.
  base::Time now = base::Time::Now();
  // TimeFormat does not support negative TimeDelta values, so then we use 0.
  return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED,
                                ui::TimeFormat::LENGTH_SHORT,
                                now < time ? base::TimeDelta() : now - time);
}

// Helper method to create mojom tab objects from SessionTab objects.
history::mojom::TabPtr SessionTabToMojom(
    const ::sessions::SessionTab& tab,
    const syncer::DeviceInfo::FormFactor device_type,
    const std::string& session_name) {
  if (tab.navigations.empty()) {
    return nullptr;
  }

  int selected_index = std::min(tab.current_navigation_index,
                                static_cast<int>(tab.navigations.size() - 1));
  const ::sessions::SerializedNavigationEntry& current_navigation =
      tab.navigations.at(selected_index);
  GURL tab_url = current_navigation.virtual_url();
  if (!tab_url.is_valid() || tab_url.spec() == chrome::kChromeUINewTabURL) {
    return nullptr;
  }

  auto tab_mojom = history::mojom::Tab::New();
  tab_mojom->device_type =
      history::mojom::DeviceType(static_cast<int>(device_type));
  base::Value::Dict dictionary;
  NewTabUI::SetUrlTitleAndDirection(&dictionary, current_navigation.title(),
                                    tab_url);
  tab_mojom->session_name = session_name;
  tab_mojom->url = GURL(*dictionary.FindString("url"));
  tab_mojom->title = *dictionary.FindString("title");

  auto relative_time = base::Time::Now() - tab.timestamp;
  tab_mojom->relative_time = relative_time;
  if (relative_time.InSeconds() < 60) {
    tab_mojom->relative_time_text = l10n_util::GetStringUTF8(
        IDS_NTP_MODULES_TAB_RESUMPTION_RECENTLY_OPENED);
  } else {
    tab_mojom->relative_time_text =
        base::UTF16ToUTF8(FormatRelativeTime(tab.timestamp));
  }

  return tab_mojom;
}

// Helper method to append mojom tab objects from SessionWindow objects.
void SessionWindowToMojom(std::vector<history::mojom::TabPtr>& tabs_mojom,
                          const ::sessions::SessionWindow& window,
                          const syncer::DeviceInfo::FormFactor device_type,
                          const std::string& session_name) {
  if (window.tabs.empty()) {
    return;
  }

  for (const std::unique_ptr<sessions::SessionTab>& tab : window.tabs) {
    history::mojom::TabPtr tab_mojom =
        SessionTabToMojom(*tab.get(), device_type, session_name);
    if (tab_mojom) {
      tabs_mojom.push_back(std::move(tab_mojom));
    }
  }
}

// Helper method to create a list of mojom tab objects from Session objects.
std::vector<history::mojom::TabPtr> SessionToMojom(
    const sync_sessions::SyncedSession* session) {
  std::vector<history::mojom::TabPtr> tabs_mojom;
  const syncer::DeviceInfo::FormFactor device_type =
      session->GetDeviceFormFactor();
  const std::string& session_name = session->GetSessionName();

  // Order tabs by visual order within window.
  for (const auto& window_pair : session->windows) {
    SessionWindowToMojom(tabs_mojom, window_pair.second->wrapped_window,
                         device_type, session_name);
  }
  return tabs_mojom;
}
}  // namespace

TabResumptionPageHandler::TabResumptionPageHandler(
    mojo::PendingReceiver<ntp::tab_resumption::mojom::PageHandler>
        pending_page_handler,
    content::WebContents* web_contents)
    : profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
      web_contents_(web_contents),
      page_handler_(this, std::move(pending_page_handler)),
      visibility_threshold_(
          static_cast<float>(base::GetFieldTrialParamByFeatureAsDouble(
              ntp_features::kNtpTabResumptionModule,
              ntp_features::kNtpTabResumptionModuleVisibilityThresholdDataParam,
              /*Default value for visibility threshold*/ 0.5))),
      categories_blocklist_(GetTabResumptionCategories(
          ntp_features::kNtpTabResumptionModuleCategoriesBlocklistParam,
          {kCategoryBlockList.begin(), kCategoryBlockListCount})),
      time_limit_(base::GetFieldTrialParamByFeatureAsInt(
          ntp_features::kNtpTabResumptionModuleTimeLimit,
          ntp_features::kNtpTabResumptionModuleTimeLimitParam,
          /*Default value for time limit*/ 24)) {
  DCHECK(profile_);
  DCHECK(web_contents_);
}

TabResumptionPageHandler::~TabResumptionPageHandler() = default;

void TabResumptionPageHandler::OnQueryURLsComplete(
    std::vector<history::mojom::TabPtr> tabs,
    GetTabsCallback callback,
    std::vector<history::QueryURLResult> results) {
  history::VisitVector visit_rows;
  for (auto result : results) {
    for (auto visit : result.visits) {
      visit_rows.push_back(visit);
    }
  }
  auto* history_service = HistoryServiceFactory::GetForProfile(
      profile_, ServiceAccessType::EXPLICIT_ACCESS);
  history_service->ToAnnotatedVisits(
      visit_rows,
      /*compute_redirect_chain_start_properties=*/false,
      base::BindOnce(&TabResumptionPageHandler::OnAnnotatedVisits,
                     weak_ptr_factory_.GetWeakPtr(), std::move(tabs),
                     std::move(callback)),
      &task_tracker_);
}

void TabResumptionPageHandler::OnAnnotatedVisits(
    std::vector<history::mojom::TabPtr> tabs,
    GetTabsCallback callback,
    const std::vector<history::AnnotatedVisit> annotated_visits) {
  std::vector<history::mojom::TabPtr> scored_tabs;
  std::set<int> scored_tab_indices;
  for (const auto& annotated_visit : annotated_visits) {
    float visibility_score =
        annotated_visit.content_annotations.model_annotations.visibility_score;
    /* If score is -1, it has not been evaluated for visibility */
    if (visibility_score < visibility_threshold_ && visibility_score >= 0) {
      continue;
    }
    if (IsVisitInCategories(annotated_visit, categories_blocklist_)) {
      continue;
    }
    for (size_t i = 0; i < tabs.size(); i++) {
      if (annotated_visit.url_row.url() == tabs[i]->url &&
          scored_tab_indices.find(i) == scored_tab_indices.end()) {
        scored_tab_indices.insert(i);
        break;
      }
    }
  }

  bool new_url_found = false;
  for (auto index : scored_tab_indices) {
    if (IsNewURL(tabs[index]->url)) {
      new_url_found = true;
    }
    scored_tabs.push_back(std::move(tabs[index]));
  }

  // Bail if module is still dismissed.
  if (profile_->GetPrefs()->GetList(kDismissedTabsPrefName).size() > 0 &&
      !new_url_found) {
    std::move(callback).Run(std::vector<history::mojom::TabPtr>());
    return;
  }

  std::sort(scored_tabs.begin(), scored_tabs.end(), CompareTabsByTime);

  std::move(callback).Run(std::move(scored_tabs));
}

void TabResumptionPageHandler::GetTabs(GetTabsCallback callback) {
  const std::string fake_data_param = base::GetFieldTrialParamValueByFeature(
      ntp_features::kNtpTabResumptionModule,
      ntp_features::kNtpTabResumptionModuleDataParam);

  if (!fake_data_param.empty()) {
    std::vector<history::mojom::TabPtr> tabs_mojom;
    const int kSampleSessionsCount = 3;
    for (int i = 0; i < kSampleSessionsCount; i++) {
      auto session_tabs_mojom =
          SessionToMojom(SampleSession("Test Session Name", 3, 1).get());
      for (auto& tab_mojom : session_tabs_mojom) {
        tabs_mojom.push_back(std::move(tab_mojom));
      }
    }
    std::move(callback).Run(std::move(tabs_mojom));
    return;
  }

  auto tabs_mojom = GetForeignTabs();
  std::vector<GURL> urls;
  for (const auto& tab : tabs_mojom) {
    urls.push_back(tab->url);
  }

  if (urls.empty()) {
    std::move(callback).Run({});
    return;
  }

  auto* history_service = HistoryServiceFactory::GetForProfile(
      profile_, ServiceAccessType::EXPLICIT_ACCESS);
  history_service->QueryURLs(
      urls, /*want_visits=*/true,
      base::BindOnce(&TabResumptionPageHandler::OnQueryURLsComplete,
                     weak_ptr_factory_.GetWeakPtr(), std::move(tabs_mojom),
                     std::move(callback)),
      &task_tracker_);
}

// static
void TabResumptionPageHandler::RegisterProfilePrefs(
    PrefRegistrySimple* registry) {
  registry->RegisterListPref(kDismissedTabsPrefName, base::Value::List());
}

// static
sync_sessions::OpenTabsUIDelegate*
TabResumptionPageHandler::GetOpenTabsUIDelegate() {
  sync_sessions::SessionSyncService* service =
      SessionSyncServiceFactory::GetInstance()->GetForProfile(profile_);
  return service ? service->GetOpenTabsUIDelegate() : nullptr;
}

std::vector<history::mojom::TabPtr> TabResumptionPageHandler::GetForeignTabs() {
  sync_sessions::OpenTabsUIDelegate* open_tabs = GetOpenTabsUIDelegate();
  std::vector<raw_ptr<const sync_sessions::SyncedSession, VectorExperimental>>
      sessions;

  std::vector<history::mojom::TabPtr> tabs_mojom;
  if (open_tabs && open_tabs->GetAllForeignSessions(&sessions)) {
    // Note: we don't own the SyncedSessions themselves.
    for (size_t i = 0; i < sessions.size(); ++i) {
      const sync_sessions::SyncedSession* session(sessions[i]);
      auto session_tabs_mojom = SessionToMojom(session);
      for (auto& tab_mojom : session_tabs_mojom) {
        if (tab_mojom && (tab_mojom->relative_time).InHours() < time_limit_ &&
            !tab_mojom->url.is_empty()) {
          tabs_mojom.push_back(std::move(tab_mojom));
        }
      }
    }
  }
  return tabs_mojom;
}

void TabResumptionPageHandler::DismissModule(const std::vector<GURL>& urls) {
  base::Value::List url_list;
  for (const auto& url : urls) {
    url_list.Append(url.spec());
  }
  profile_->GetPrefs()->SetList(kDismissedTabsPrefName, std::move(url_list));
}

void TabResumptionPageHandler::RestoreModule() {
  profile_->GetPrefs()->SetList(kDismissedTabsPrefName, base::Value::List());
}

bool TabResumptionPageHandler::IsNewURL(GURL url) {
  const base::Value::List& cached_urls =
      profile_->GetPrefs()->GetList(kDismissedTabsPrefName);
  auto it = std::find_if(cached_urls.begin(), cached_urls.end(),
                         [url](const base::Value& cached_url) {
                           return cached_url.GetString() == url.spec();
                         });
  if (it == cached_urls.end()) {
    return true;
  }
  return false;
}
