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

#include "components/persistent_cache/sqlite/backend_storage_delegate.h"

#include <memory>
#include <utility>

#include "base/files/file_path.h"
#include "base/numerics/clamped_math.h"
#include "base/types/expected_macros.h"
#include "components/persistent_cache/pending_backend.h"
#include "components/persistent_cache/sqlite/sqlite_backend_impl.h"
#include "components/persistent_cache/sqlite/vfs_util.h"
#include "components/sqlite_vfs/client.h"
#include "components/sqlite_vfs/file_set_error.h"
#include "components/sqlite_vfs/pending_file_set.h"
#include "components/sqlite_vfs/sqlite_database_vfs_file_set.h"
#include "components/sqlite_vfs/vfs_utils.h"

namespace persistent_cache::sqlite {

namespace {

TransactionError FileSetErrorToTransactionError(
    sqlite_vfs::FileSetError error) {
  switch (error) {
    case sqlite_vfs::FileSetError::kTransient:
      return TransactionError::kTransient;

    case sqlite_vfs::FileSetError::kPermanent:
      return TransactionError::kConnectionError;

    case sqlite_vfs::FileSetError::kPermanentRequireDeletion:
      return TransactionError::kPermanent;
  }
}

}  // namespace

base::expected<PendingBackend, TransactionError>
BackendStorageDelegate::MakePendingBackend(Client client,
                                           const base::FilePath& directory,
                                           const base::FilePath& base_name,
                                           bool single_connection,
                                           bool journal_mode_wal) {
  ASSIGN_OR_RETURN(auto pending_file_set,
                   sqlite_vfs::MakePendingFileSet(
                       VfsClientFromClient(client), directory, base_name,
                       single_connection, journal_mode_wal),
                   &FileSetErrorToTransactionError);
  return PendingBackend(std::move(pending_file_set));
}

base::expected<std::unique_ptr<Backend>, TransactionError>
BackendStorageDelegate::MakeBackend(Client client,
                                    const base::FilePath& directory,
                                    const base::FilePath& base_name,
                                    bool single_connection,
                                    bool journal_mode_wal) {
  ASSIGN_OR_RETURN(auto pending_backend,
                   MakePendingBackend(client, directory, base_name,
                                      single_connection, journal_mode_wal));
  return SqliteBackendImpl::Bind(std::move(pending_backend), client);
}

std::optional<PendingBackend> BackendStorageDelegate::ShareReadOnlyConnection(
    const base::FilePath& directory,
    const base::FilePath& base_name,
    const Backend& backend) {
  ASSIGN_OR_RETURN(
      auto pending_file_set,
      sqlite_vfs::ShareConnection(
          directory, base_name,
          static_cast<const SqliteBackendImpl&>(backend).file_set(),
          /*read_write=*/false),
      [](sqlite_vfs::FileSetError) { return std::nullopt; });
  return PendingBackend(std::move(pending_file_set));
}

std::optional<PendingBackend> BackendStorageDelegate::ShareReadWriteConnection(
    const base::FilePath& directory,
    const base::FilePath& base_name,
    const Backend& backend) {
  ASSIGN_OR_RETURN(
      auto pending_file_set,
      sqlite_vfs::ShareConnection(
          directory, base_name,
          static_cast<const SqliteBackendImpl&>(backend).file_set(),
          /*read_write=*/true),
      [](sqlite_vfs::FileSetError) { return std::nullopt; });
  return PendingBackend(std::move(pending_file_set));
}

base::FilePath BackendStorageDelegate::GetBaseName(const base::FilePath& file) {
  return sqlite_vfs::GetBaseName(file);
}

int64_t BackendStorageDelegate::DeleteFiles(Client client,
                                            const base::FilePath& directory,
                                            const base::FilePath& base_name) {
  return sqlite_vfs::DeleteFiles(VfsClientFromClient(client), directory,
                                 base_name);
}

}  // namespace persistent_cache::sqlite
