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

#include "components/offline_pages/core/prefetch/tasks/metrics_finalization_task.h"

#include <algorithm>
#include <memory>
#include <vector>

#include "base/bind.h"
#include "base/callback.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "components/offline_pages/core/offline_clock.h"
#include "components/offline_pages/core/offline_store_utils.h"
#include "components/offline_pages/core/prefetch/prefetch_types.h"
#include "components/offline_pages/core/prefetch/store/prefetch_store.h"
#include "sql/database.h"
#include "sql/statement.h"
#include "sql/transaction.h"

namespace offline_pages {
namespace {

// In-memory representation of URL metadata fetched from SQLite storage.
struct PrefetchItemStats {
  PrefetchItemStats(int64_t offline_id,
                    int generate_bundle_attempts,
                    int get_operation_attempts,
                    int download_initiation_attempts,
                    int64_t archive_body_length,
                    base::Time creation_time,
                    PrefetchItemErrorCode error_code,
                    int64_t file_size)
      : offline_id(offline_id),
        generate_bundle_attempts(generate_bundle_attempts),
        get_operation_attempts(get_operation_attempts),
        download_initiation_attempts(download_initiation_attempts),
        archive_body_length(archive_body_length),
        creation_time(creation_time),
        error_code(error_code),
        file_size(file_size) {}

  int64_t offline_id;
  int generate_bundle_attempts;
  int get_operation_attempts;
  int download_initiation_attempts;
  int64_t archive_body_length;
  base::Time creation_time;
  PrefetchItemErrorCode error_code;
  int64_t file_size;
};

std::vector<PrefetchItemStats> FetchUrlsSync(sql::Database* db) {
  static const char kSql[] = R"(
  SELECT offline_id, generate_bundle_attempts, get_operation_attempts,
    download_initiation_attempts, archive_body_length, creation_time,
    error_code, file_size
  FROM prefetch_items
  WHERE state = ?
)";
  sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
  statement.BindInt(0, static_cast<int>(PrefetchItemState::FINISHED));

  std::vector<PrefetchItemStats> urls;
  while (statement.Step()) {
    urls.emplace_back(statement.ColumnInt64(0),  // offline_id
                      statement.ColumnInt(1),    // generate_bundle_attempts
                      statement.ColumnInt(2),    // get_operation_attempts
                      statement.ColumnInt(3),    // download_initiation_attempts
                      statement.ColumnInt64(4),  // archive_body_length
                      store_utils::FromDatabaseTime(
                          statement.ColumnInt64(5)),  // creation_time
                      static_cast<PrefetchItemErrorCode>(
                          statement.ColumnInt(6)),  // error_code
                      statement.ColumnInt64(7)      // file_size
                      );
  }

  return urls;
}

bool MarkUrlAsZombie(sql::Database* db,
                     base::Time freshness_time,
                     int64_t offline_id) {
  static const char kSql[] =
      "UPDATE prefetch_items SET state = ?, freshness_time = ? WHERE "
      "offline_id = ?";
  sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
  statement.BindInt(0, static_cast<int>(PrefetchItemState::ZOMBIE));
  statement.BindInt(1, store_utils::ToDatabaseTime(freshness_time));
  statement.BindInt64(2, offline_id);
  return statement.Run();
}

void LogStateCountMetrics(PrefetchItemState state, int count) {
  // The histogram below is an expansion of the UMA_HISTOGRAM_ENUMERATION
  // macro adapted to allow for setting a count.
  // Note: The factory creates and owns the histogram.
  base::HistogramBase* histogram = base::SparseHistogram::FactoryGet(
      "OfflinePages.Prefetching.StateCounts",
      base::HistogramBase::kUmaTargetedHistogramFlag);
  histogram->AddCount(static_cast<int>(state), count);
}

void CountEntriesInEachState(sql::Database* db) {
  static const char kSql[] =
      "SELECT state, COUNT (*) FROM prefetch_items GROUP BY state";
  sql::Statement statement(db->GetCachedStatement(SQL_FROM_HERE, kSql));
  while (statement.Step()) {
    PrefetchItemState state =
        static_cast<PrefetchItemState>(statement.ColumnInt(0));
    int count = statement.ColumnInt(1);
    LogStateCountMetrics(state, count);
  }
}

void ReportMetricsFor(const PrefetchItemStats& url, const base::Time now) {
  // Lifetime reporting.
  static const int kFourWeeksInSeconds =
      base::TimeDelta::FromDays(28).InSeconds();
  const bool successful = url.error_code == PrefetchItemErrorCode::SUCCESS;
  int64_t lifetime_seconds = (now - url.creation_time).InSeconds();
  if (successful) {
    UMA_HISTOGRAM_CUSTOM_COUNTS(
        "OfflinePages.Prefetching.ItemLifetime.Successful", lifetime_seconds, 1,
        kFourWeeksInSeconds, 50);
  } else {
    UMA_HISTOGRAM_CUSTOM_COUNTS("OfflinePages.Prefetching.ItemLifetime.Failed",
                                lifetime_seconds, 1, kFourWeeksInSeconds, 50);
  }

  // Error code reporting.
  base::UmaHistogramSparse("OfflinePages.Prefetching.FinishedItemErrorCode",
                           static_cast<int>(url.error_code));

  // Attempt counts reporting.
  static const int kMaxPossibleRetries = 20;
  UMA_HISTOGRAM_EXACT_LINEAR(
      "OfflinePages.Prefetching.ActionAttempts.GeneratePageBundle",
      url.generate_bundle_attempts, kMaxPossibleRetries);
  UMA_HISTOGRAM_EXACT_LINEAR(
      "OfflinePages.Prefetching.ActionAttempts.GetOperation",
      url.get_operation_attempts, kMaxPossibleRetries);
  UMA_HISTOGRAM_EXACT_LINEAR(
      "OfflinePages.Prefetching.ActionAttempts.DownloadInitiation",
      url.download_initiation_attempts, kMaxPossibleRetries);
}

bool ReportMetricsAndFinalizeSync(sql::Database* db) {
  sql::Transaction transaction(db);
  if (!transaction.Begin())
    return false;

  // Gather metrics about the current number of entries with each state.  Check
  // before zombification so that we will be able to see entries in the finished
  // state, otherwise we will only see zombies, never finished entries.
  CountEntriesInEachState(db);

  const std::vector<PrefetchItemStats> urls = FetchUrlsSync(db);

  base::Time now = OfflineClock()->Now();
  for (const auto& url : urls) {
    MarkUrlAsZombie(db, now, url.offline_id);
  }

  if (transaction.Commit()) {
    for (const auto& url : urls) {
      DVLOG(1) << "Finalized prefetch item with error code "
               << static_cast<int>(url.error_code) << ": (" << url.offline_id
               << ", " << url.generate_bundle_attempts << ", "
               << url.get_operation_attempts << ", "
               << url.download_initiation_attempts << ", "
               << url.archive_body_length << ", " << url.creation_time << ", "
               << url.file_size << ")";
      ReportMetricsFor(url, now);
    }
    return true;
  }

  return false;
}

}  // namespace

MetricsFinalizationTask::MetricsFinalizationTask(PrefetchStore* prefetch_store)
    : prefetch_store_(prefetch_store), weak_factory_(this) {}

MetricsFinalizationTask::~MetricsFinalizationTask() {}

void MetricsFinalizationTask::Run() {
  prefetch_store_->Execute(
      base::BindOnce(&ReportMetricsAndFinalizeSync),
      base::BindOnce(&MetricsFinalizationTask::MetricsFinalized,
                     weak_factory_.GetWeakPtr()),
      false);
}

void MetricsFinalizationTask::MetricsFinalized(bool result) {
  TaskComplete();
}

}  // namespace offline_pages
