/*
Proto contract for the File services.

Version     Date            Author      Comment
V1.0.0      20-05-2026      MiAl        Initial version
*/

syntax = "proto3";

import "Interfaces/google/api/annotations.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "Interfaces/Application/Protos/V1/bergstein.digi.moduleinfo.proto";
import "Interfaces/PrintManager/Protos/V1/bergstein.digi.printmanager.paging.proto";
import "Interfaces/PrintManager/Protos/V1/bergstein.digi.printmanager.audit.proto";
import "Interfaces/PrintManager/Protos/V1/bergstein.digi.printmanager.proto_options.proto";

package file;

option csharp_namespace = "Bergstein.Digi.Shared.Interfaces.PrintManager.File.Protos.V2";

// Service for reading metadata for files and folders.
service MetadataService {
  rpc GetMetadata (GetMetadataRequest) returns (GetMetadataReply) {
    option (google.api.http) = {
      get: "/file_module/v2/metadata"
    };
  }
}

message GetMetadataRequest {
  string uri = 1;
}

message GetMetadataReply {
  Metadata metadata = 1;
}

// Service for listing direct child file and folder URIs.
service ExploreService {
  rpc List (ExploreRequest) returns (ExploreReply) {
    option (google.api.http) = {
      get: "/file_module/v2/explore"
    };
  }
}

message ExploreRequest {
  string uri = 1;
  google.protobuf.UInt32Value page_size = 2;
  google.protobuf.UInt32Value page_number = 3;
  bool include_total_size = 4;
}

message ExploreReply {
  repeated string uris = 1;
  int32 total_size = 2;
}

// Service for file operations.
service FileService {
  rpc RenameFile (RenameFileRequest) returns (RenameFileReply) {
    option (google.api.http) = {
      post: "/file_module/v2/files/rename"
      body: "*"
    };
  }

  rpc MoveFile (MoveFileRequest) returns (MoveFileReply) {
    option (google.api.http) = {
      post: "/file_module/v2/files/move"
      body: "*"
    };
  }

  rpc UploadFile (UploadFileRequest) returns (UploadFileReply) {
    option (google.api.http) = {
      post: "/file_module/v2/files/upload"
      body: "*"
    };
  }

  rpc UploadFileStream (stream UploadFileStreamRequest) returns (UploadFileReply);

  rpc DownloadFile (DownloadFileRequest) returns (DownloadFileReply) {
    option (google.api.http) = {
      post: "/file_module/v2/files/download"
      body: "*"
    };
  }

  rpc DownloadFileStream (DownloadFileStreamRequest) returns (stream DownloadFileStreamReply);

  rpc DeleteFile (DeleteFileRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      post: "/file_module/v2/files/delete"
      body: "*"
    };
  }
}

message RenameFileRequest {
  string uri = 1;
  string new_name = 2;
}

message RenameFileReply {
  Metadata metadata = 1;
}

message MoveFileRequest {
  string uri = 1;
  string target_folder_uri = 2;
}

message MoveFileReply {
  Metadata metadata = 1;
}

message UploadFileRequest {
  oneof operation {
    UploadFileBytes upload_bytes = 1;
    InitiateFileUpload initiate = 2;
    UploadFileChunk upload_chunk = 3;
    CompleteFileUpload complete = 4;
    AbortFileUpload abort = 5;
  }
}

message UploadFileBytes {
  string uri = 1;
  string content_type = 2;
  bytes file_data = 3;
}

message InitiateFileUpload {
  string uri = 1;
  string content_type = 2;
  uint64 size = 3;
  string md5 = 4;
  uint64 requested_chunk_size = 5;
}

message UploadFileChunk {
  string upload_id = 1;
  uint64 chunk_number = 2;
  uint64 offset = 3;
  bytes chunk_data = 4;
}

message CompleteFileUpload {
  string upload_id = 1;
}

message AbortFileUpload {
  string upload_id = 1;
}

message UploadFileReply {
  Metadata metadata = 1;
  UploadSession upload_session = 2;
  UploadChunkResult chunk_result = 3;
}

message UploadFileStreamRequest {
  oneof content {
    UploadFileStreamHeader header = 1;
    UploadFileStreamChunk chunk = 2;
  }
}

message UploadFileStreamHeader {
  string uri = 1;
  string content_type = 2;
}

message UploadFileStreamChunk {
  uint64 offset = 1;
  bytes chunk_data = 2;
}

message DownloadFileRequest {
  oneof operation {
    DownloadFileBytes download_bytes = 1;
    InitiateFileDownload initiate = 2;
    DownloadFileChunk download_chunk = 3;
  }
}

message DownloadFileBytes {
  string uri = 1;
}

message InitiateFileDownload {
  string uri = 1;
  uint64 requested_chunk_size = 2;
}

message DownloadFileChunk {
  string download_id = 1;
  uint64 chunk_number = 2;
}

message DownloadFileReply {
  Metadata metadata = 1;
  bytes file_data = 2;
  DownloadSession download_session = 3;
  DownloadChunkResult chunk_result = 4;
}

message DownloadFileStreamRequest {
  string uri = 1;
}

message DownloadFileStreamReply {
  oneof content {
    DownloadFileStreamHeader header = 1;
    DownloadFileStreamChunk chunk = 2;
  }
}

message DownloadFileStreamHeader {
  Metadata metadata = 1;
  uint64 chunk_size = 2;
}

message DownloadFileStreamChunk {
  uint64 offset = 1;
  bytes chunk_data = 2;
}

message DeleteFileRequest {
  string uri = 1;
}

// Service for folder operations.
service FolderService {
  rpc CreateFolder (CreateFolderRequest) returns (CreateFolderReply) {
    option (google.api.http) = {
      post: "/file_module/v2/folders/create"
      body: "*"
    };
  }

  rpc DownloadFolder (DownloadFolderRequest) returns (DownloadFolderReply) {
    option (google.api.http) = {
      post: "/file_module/v2/folders/download"
      body: "*"
    };
  }

  rpc RenameFolder (RenameFolderRequest) returns (RenameFolderReply) {
    option (google.api.http) = {
      post: "/file_module/v2/folders/rename"
      body: "*"
    };
  }

  rpc MoveFolder (MoveFolderRequest) returns (MoveFolderReply) {
    option (google.api.http) = {
      post: "/file_module/v2/folders/move"
      body: "*"
    };
  }

  rpc DeleteFolder (DeleteFolderRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      post: "/file_module/v2/folders/delete"
      body: "*"
    };
  }
}

message CreateFolderRequest {
  string uri = 1;
  bool inherits_permissions = 2;
  StorageObject storage_object = 3;
}

message CreateFolderReply {
  Metadata metadata = 1;
}

message DownloadFolderRequest {
  string uri = 1;
}

message DownloadFolderReply {
  Metadata metadata = 1;
  bytes archive_data = 2;
  string content_type = 3;
  string file_name = 4;
}

message RenameFolderRequest {
  string uri = 1;
  string new_name = 2;
}

message RenameFolderReply {
  Metadata metadata = 1;
}

message MoveFolderRequest {
  string uri = 1;
  string target_parent_uri = 2;
}

message MoveFolderReply {
  Metadata metadata = 1;
}

message DeleteFolderRequest {
  string uri = 1;
  bool recursive = 2;
}

// Service for thumbnails derived from file content.
service ThumbnailService {
  rpc GetThumbnail (GetThumbnailRequest) returns (GetThumbnailReply) {
    option (google.api.http) = {
      get: "/file_module/v2/thumbnails"
    };
  }
}

message GetThumbnailRequest {
  string uri = 1;
  ThumbnailSize size = 2;
}

message GetThumbnailReply {
  bytes thumbnail_data = 1;
  string content_type = 2;
  ThumbnailSize size = 3;
  uint32 width = 4;
  uint32 height = 5;
  string source_etag = 6;
}

// Service for storage object management.
service StorageObjectService {
  rpc ListStorageObject (ListStorageObjectsRequest) returns (ListStorageObjectsReply) {
    option (google.api.http) = {
      get: "/file_module/v2/storage-objects"
    };
  }

  rpc GetStorageObject (GetStorageObjectRequest) returns (GetStorageObjectReply) {
    option (google.api.http) = {
      get: "/file_module/v2/storage-object"
    };
  }

  rpc CreateStorageObject (CreateStorageObjectRequest) returns (CreateStorageObjectReply) {
    option (google.api.http) = {
      post: "/file_module/v2/storage-object"
      body: "*"
    };
  }

  rpc UpdateStorageObject (UpdateStorageObjectRequest) returns (UpdateStorageObjectReply) {
    option (google.api.http) = {
      post: "/file_module/v2/storage-objects/update"
      body: "*"
    };
  }

  rpc DeleteStorageObject (DeleteStorageObjectRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      post: "/file_module/v2/storage-objects/delete"
      body: "*"
    };
  }
}

message ListStorageObjectsRequest {
  shared.PagingRequest paging = 1;
  bool descending = 2;
  StorageObject order = 3;
  StorageObject filter = 4;
}

message ListStorageObjectsReply {
  repeated StorageObject storage_objects = 1;
  shared.PagingReply paging = 2;
}

message GetStorageObjectRequest {
  // The matching Id of the StorageObject to get.
  string id = 1 [(proto_options.field_attributes) = IS_GUID];
}

message GetStorageObjectReply {
  StorageObject storage_object = 1;
}

message CreateStorageObjectRequest {
  StorageObject storage_object = 2;
}

message CreateStorageObjectReply {
  StorageObject storage_object = 1;
}

message UpdateStorageObjectRequest {
  string id = 1;
  StorageObject storage_object = 2;
}

message UpdateStorageObjectReply {
  StorageObject storage_object = 1;
}

message DeleteStorageObjectRequest {
  string id = 1;
}

// Service for file and folder permissions.
service StoragePermissionService {
  rpc ListPermissions (ListPermissionsRequest) returns (ListPermissionsReply) {
    option (google.api.http) = {
      get: "/file_module/v2/permissions"
    };
  }

  rpc CreatePermission (CreatePermissionRequest) returns (PermissionReply) {
    option (google.api.http) = {
      post: "/file_module/v2/permissions"
      body: "*"
    };
  }

  rpc UpdatePermission (UpdatePermissionRequest) returns (PermissionReply) {
    option (google.api.http) = {
      post: "/file_module/v2/permissions/update"
      body: "*"
    };
  }

  rpc DeletePermission (DeletePermissionRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      post: "/file_module/v2/permissions/delete"
      body: "*"
    };
  }
}

message ListPermissionsRequest {
  string uri = 1;
}

message ListPermissionsReply {
  repeated Permission permissions = 1;
}

message CreatePermissionRequest {
  string uri = 1;
  Permission permission = 2;
}

message UpdatePermissionRequest {
  string uri = 1;
  Permission permission = 2;
}

message DeletePermissionRequest {
  string uri = 1;
  string permission_id = 2;
}

message PermissionReply {
  Permission permission = 1;
}

// Metadata for a file or folder node.
message Metadata {
  // Audit info for this entity.
  shared.Audit audit = 1;
  // The id used to reference this entity in the system.
  string id = 2 [
    (proto_options.field_attributes) = IS_GUID,
    (proto_options.field_attributes) = IS_PRIMARY_KEY
  ];
  // Name of the file or folder (not including the path).
  string name = 3;
  // Full URI of the file or folder (including the path).
  string uri = 4;
  // The type of the node (file or folder).
  NodeType node_type = 5;
  // Permissions associated with this node.
  repeated Permission permissions = 6;
  // For files, the size in bytes. For folders, the total size of all descendant files in bytes. 0 means there was no calculation result for the size.
  uint64 size = 7;
  // For files, the content type (MIME type). Empty for folders.
  string content_type = 8;
  // The MD5 hash of the file content. Empty for folders or when the hash is not available. 
  string md5 = 9;
  // The ETag of the file or folder.
  string etag = 10;
  // Optional reference to the storage object where the content of this file or folder is stored.
  string storage_object_id = 11 [
    (proto_options.field_attributes) = IS_GUID
  ];
  // The storage object where the content of this file or folder is stored.
  StorageObject storage_object = 12;
}

message Permission {
  shared.Audit audit = 1;
  string id = 2 [
    (proto_options.field_attributes) = IS_GUID,
    (proto_options.field_attributes) = IS_PRIMARY_KEY
  ];
  string uri = 3;
  PermissionSubjectType permission_subject_type = 4;
  string subject_id = 5;
  bool can_read = 6;
  bool can_write = 7;
  bool can_manage_permissions = 8;
  bool inherit_to_children = 9;
}

message UploadSession {
  string upload_id = 1;
  string uri = 2;
  string content_type = 3;
  uint64 chunk_size = 4;
  uint64 total_chunks = 5;
  google.protobuf.Timestamp expires_utc = 6;
}

message UploadChunkResult {
  string upload_id = 1;
  uint64 chunk_number = 2;
  bool accepted = 3;
}

message DownloadSession {
  string download_id = 1;
  string uri = 2;
  uint64 chunk_size = 3;
  uint64 total_chunks = 4;
  google.protobuf.Timestamp expires_utc = 5;
}

message DownloadChunkResult {
  string download_id = 1;
  uint64 chunk_number = 2;
  uint64 offset = 3;
  bytes chunk_data = 4;
  bool is_last_chunk = 5;
}

message StorageObject {
  string id = 1 [
    (proto_options.field_attributes) = IS_GUID,
    (proto_options.field_attributes) = IS_PRIMARY_KEY
  ];
  string name = 2;
  string drive_label = 3;
  StorageSettings settings = 4;
}

message StorageSettings {
  oneof settings {
    DirectorySettings directory = 1;
    FtpSettings ftp = 2;
    google.protobuf.Empty in_memory = 3;
  }
}

message DirectorySettings {
  string base_path = 1;
}

message FtpSettings {
  string address = 1;
  google.protobuf.StringValue user_name = 2;
  google.protobuf.StringValue password = 3;
  google.protobuf.StringValue domain = 4;
}

// Service for creating and revoking temporary signed download links.
service SignedFileUrlService {
  rpc CreateSignedDownloadUrl (CreateSignedDownloadUrlRequest) returns (CreateSignedDownloadUrlReply) {
    option (google.api.http) = {
      post: "/file_module/v2/signed-download-urls"
      body: "*"
    };
  }

  rpc GetSignedDownloadUrlInfo (GetSignedDownloadUrlInfoRequest) returns (GetSignedDownloadUrlInfoReply) {
    option (google.api.http) = {
      get: "/file_module/v2/signed-download-urls/{id}"
    };
  }

  rpc RevokeSignedDownloadUrl (RevokeSignedDownloadUrlRequest) returns (google.protobuf.Empty) {
    option (google.api.http) = {
      delete: "/file_module/v2/signed-download-urls/{id}"
    };
  }
}

message CreateSignedDownloadUrlRequest {
  string uri = 1;
  google.protobuf.UInt32Value ttl_seconds = 2;
  google.protobuf.UInt32Value max_downloads = 3;
  bool inline = 4;
}

message CreateSignedDownloadUrlReply {
  SignedFileUrl signed_url = 1;
  string url = 2;
}

message GetSignedDownloadUrlInfoRequest {
  string id = 1;
}

message GetSignedDownloadUrlInfoReply {
  SignedFileUrl signed_url = 1;
}

message RevokeSignedDownloadUrlRequest {
  string id = 1;
}

message SignedFileUrl {
  string id = 1;
  string uri = 2;
  google.protobuf.Timestamp expires_utc = 3;
  google.protobuf.UInt32Value max_downloads = 4;
  uint32 download_count = 5;
  google.protobuf.Timestamp revoked_utc = 6;
  bool inline = 7;
  shared.Audit audit = 8;
}

// Service for reading info about this module.
service FileModuleInfoService {
  rpc GetModuleInfo (google.protobuf.Empty) returns (module_info.ModuleInfoReply) {
    option (google.api.http) = {
      get: "/file_module/v2/module_info"
    };
  }

  rpc GetFeatureFlags (google.protobuf.Empty) returns (module_info.FeatureFlagsReply) {
    option (google.api.http) = {
      get: "/file_module/v2/feature_flags"
    };
  }

  rpc GetReleaseNotes (google.protobuf.Empty) returns (module_info.ReleaseNotesReply) {
    option (google.api.http) = {
      get: "/file_module/v2/release_notes"
    };
  }

  rpc GetHealthChecks (google.protobuf.Empty) returns (module_info.HealthChecksReply) {
    option (google.api.http) = {
      get: "/file_module/v2/health_checks"
    };
  }
}

enum NodeType {
  NODE_TYPE_UNKNOWN = 0;
  NODE_TYPE_FOLDER = 1;
  NODE_TYPE_FILE = 2;
}

enum PermissionSubjectType {
  PERMISSION_SUBJECT_TYPE_UNKNOWN = 0;
  PERMISSION_SUBJECT_TYPE_USER = 1;
  PERMISSION_SUBJECT_TYPE_ROLE = 2;
}

enum ThumbnailSize {
  THUMBNAIL_SIZE_UNKNOWN = 0;
  THUMBNAIL_SIZE_SMALL = 1;
  THUMBNAIL_SIZE_MEDIUM = 2;
  THUMBNAIL_SIZE_LARGE = 3;
}
