syntax = "proto3";

package devvit.dev_portal.installation;

import "devvit/dev_portal/app/info/app_info.proto";
import "devvit/dev_portal/app_version/info/app_version_info.proto";
import "devvit/reddit/thing_type.proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";

option go_package = "github.snooguts.net/reddit/reddit-devplatform-monorepo/go-common/generated/protos/types/devvit/devportal/installation";

// region Enums

enum UpgradeStrategy {
  MANUAL = 0;
  AUTOMATIC = 1;
}

// Permissions that a moderator can grant to the app developer for an installation
// This enum maps 1-to-1 to its Prisma equivalent in prisma/schema.prisma,
// so they must be kept in sync
enum DeveloperPermissions {
  // No permissions granted
  NONE = 0;
  // Developer can stream the installation's logs and see the installation page
  // in portal, but cannot edit the installation's settings
  READ_INSTALL_LOGS = 1;
}

// endregion

message OptionalUpgradeStrategy {
  UpgradeStrategy value = 1;
}

// region Request parameters

// Used to install an app
message InstallationCreationRequest {
  // What app version are you installing?
  string app_version_id = 1;
  // Who should this app run as? If not present, will be run by the user installing the app.
  google.protobuf.StringValue run_as = 3;

  // What type of install is this?
  app_version.info.InstallationType type = 4;
  // The subreddit or user to install on. For subreddits, this is either the
  // subreddit name (**with** "r/" prefix) or its t5 ID. Eg, `r/beta` or
  // `t5_15e`. For users, this is the username (**with** "u/" prefix) or the t2 ID.
  string location = 5;

  // What is the installation's upgrade strategy?
  UpgradeStrategy upgrade_strategy = 6;
  // If applicable, what is the configuration for that upgrade strategy?
  google.protobuf.Struct upgrade_strategy_config = 7;

  // installed_by is determined by the auth of the logged in user, does not need to be given

  // developer_permission defaults to NONE on creation, does not need to be given
}

// Used to update an existing installation's information.
// If a field is optional, omitting it will leave its value unchanged.
message InstallationUpdateRequest {
  // What is the ID of the installation you want to change?
  string id = 1;
  // Who should this app run as? If not present, will be run by the user installing the app.
  google.protobuf.StringValue run_as = 3;

  // installed_by, install type, location, and version are not editable

  // What is the installation's upgrade strategy?
  OptionalUpgradeStrategy upgrade_strategy = 4;
  // If applicable, what is the configuration for that upgrade strategy?
  google.protobuf.Struct upgrade_strategy_config = 5;
  /** Disable this installation of the app? */
  google.protobuf.BoolValue is_enabled = 6;
  // What permissions does the developer have for this installation?
  optional DeveloperPermissions developer_permissions = 7;
}

// Used to upgrade an existing installation to a newer version.
message InstallationUpgradeRequest {
  // What is the ID of the installation you want to change?
  string id = 1;
  // What version of the app are you upgrading to? (NOTE: This must be a version of
  // the same app, and must be a later version than the one currently installed.)
  // If not given, we will upgrade you to the latest non-prerelease version of the app.
  google.protobuf.StringValue app_version_id = 2;
}

message InstallationUpgradeManyRequest {
  // What are the IDs of the installations you want to change?
  repeated string ids = 1;
  // What version of the app are you upgrading them all to? (NOTE: This must be a version
  // of the same app, and must be a later version than the one currently installed.)
  string app_version_id = 2;
}

message GetByAppNameAndInstallLocationRequest {
  // What is the slug of the app you're looking for?
  string slug = 1;
  // What type of install are you looking for?
  app_version.info.InstallationType type = 2;
  // What is the install location?
  string location = 3;
}

// Used to get all installs in a given location
message GetAllWithInstallLocationRequest {
  // What type of install are you looking for?
  app_version.info.InstallationType type = 1;
  // What is the install location?
  string location = 2;
}

// Used to get all installs made by a given user
message GetAllWithInstallerRequest {
  // Whose installs are you looking for? (Can be a t2_ ID or a username, with or without `u/`)
  string installed_by = 1;
}

message GetAllWithAppRequest {
  string id = 1;
  optional uint32 take = 2;
  optional uint32 skip = 3;
}

message GetInstallationHistoryRequest {
  // What type of install are you looking for?
  app_version.info.InstallationType type = 1;
  // What is the install location?
  string location = 2;
  // What is the slug of the app you're looking for?
  string slug = 3;
  // Beginning of the time window. Leaving null implies searching from the beginning
  google.protobuf.Timestamp from = 4;
  // End of the time window. Leaving null implies searching until the end
  google.protobuf.Timestamp to = 5;
  // How many items to take?
  optional uint32 take = 6;
  // Order in desc order?
  optional bool desc = 7;
}

// endregion

// region Response types

// Contains the details of an installation. For field documentation, refer to the Prisma schema.
message InstallationInfo {
  string id = 1;
  // string installed_by = 2; // Removed; see DX-2225
  UpgradeStrategy upgrade_strategy = 3;
  google.protobuf.Struct upgrade_strategy_config = 4;
  google.protobuf.StringValue run_as = 6;
  app_version.info.InstallationType type = 7;
  InstallationLocationInfo location = 8;
  bool is_enabled = 9;
  DeveloperPermissions developer_permissions = 10;
}

message InstallationLocationInfo {
  // Thing ID; eg, `"t5_2qh0u"` for r/pics.
  string id = 1;
  // Thing name; eg, `"pics"` for r/pics.
  string name = 2;
  // Thing type; eg, `5`, the second character in `t5_2qh0u` for r/pics.
  devvit.reddit.ThingType type = 3;
  google.protobuf.StringValue icon = 4;
  bool is_nsfw = 5;
  // True if subreddit is private and the user isn't a member, or is not visible to viewer for any other reason.
  bool is_unavailable = 6;
}

// Contains details of an installation, as well as what version was installed.
message FullInstallationInfo {
  InstallationInfo installation = 1;
  app_version.info.AppVersionInfo app_version = 2;
  app.info.AppInfo app = 3;
}

// Contains multiple installations.
message MultipleInstallationsResponse {
  repeated InstallationInfo installations = 1;
}

// Contains multiple installations and their app versions.
message GetAllWithAppResponse {
  repeated InstallationWithAppVersion installations = 1;
}

// An app installation with its matching app version info.
message InstallationWithAppVersion {
  InstallationInfo installation = 1;
  app_version.info.AppVersionInfo app_version = 2;
}

message InstallationUpgradeManyResponse {
  message InstallationUpgradeDetails {
    string id = 1;
    bool success = 2;
    optional string error = 3;
  }
  repeated InstallationUpgradeDetails details = 1;
}

// Location details of an install including type of location, id, and name. (subreddit or user)
message InstallationLocationDetails {
  app_version.info.InstallationType type = 1;
  // The thing ID of the valid install location
  string thing_id = 2;
  // The name of the valid install location
  string name = 3;
}

enum InstallationHistoryEventName {
  INSTALLED = 0;
  UNINSTALLED = 1;
  UPGRADED = 2;
  UPDATED = 3;
  BANNED = 4;
  UNBANNED = 5;
}

message InstallationHistoryEvent {
  // Who triggered this event? t2_id of the user
  string user_id = 1;
  // What kind of event what it?
  InstallationHistoryEventName name = 2;
  // What are the details of the event?
  map<string, string> details = 3;
  // When did this event occur?
  google.protobuf.Timestamp created_at = 4;
}

message GetInstallationHistoryResponse {
  // The events that occurred during the window specified by the request query
  repeated InstallationHistoryEvent events = 1;
  // Total number of events associated with the installation
  uint32 total_events = 8;
}

// endregion
