syntax = "proto3";

package crabs.evening_detective_server;

import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "protoc-gen-openapiv2/options/annotations.proto";
import "google/api/httpbody.proto";

option go_package = "pkg/proto";

option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  info: {
    title  : "Документация сервиса \"Вечерний детектив\"";
    version: "v0.1.0";
  };

  security_definitions: {
    security: {
      key  : "BearerAuth";
      value: {
        type       : TYPE_API_KEY;
        in         : IN_HEADER;
        name       : "Authorization";
        description: "Authentication token, prefixed by Bearer: Bearer <token>";
      }
    }
  }
  security: {
    security_requirement: {
      key  : "BearerAuth";
      value: {};
    }
  }
};

service EveningDetectiveServer {
  rpc Ping(PingReq) returns (PingRsp) {
    option (google.api.http) = {
      get: "/api/test/ping"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      summary: "Проверить доступность";
    };
  }

  rpc Echo(EchoReq) returns (EchoRsp) {
    option (google.api.http) = {
      post: "/api/test/echo"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      summary: "Проверить обработку данных";
    };
  }

  rpc Signup(SignupReq) returns (SignupRsp) {
    option (google.api.http) = {
      post: "/api/auth/signup"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      tags   : "Регистрация и вход";
      summary: "Зарегистрироваться";
    };
  }

  rpc RefreshPassword(RefreshPasswordReq) returns (RefreshPasswordRsp) {
    option (google.api.http) = {
      post: "/api/auth/refresh-password"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      tags   : "Регистрация и вход";
      summary: "Обновить пароль";
    };
  }

  rpc Login(LoginReq) returns (LoginRsp) {
    option (google.api.http) = {
      post: "/api/auth/login"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      tags   : "Регистрация и вход";
      summary: "Войти и получить токена доступа";
    };
  }

  rpc Refresh(RefreshReq) returns (RefreshRsp) {
    option (google.api.http) = {
      post: "/api/auth/refresh"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      tags   : "Регистрация и вход";
      summary: "Обновить токена доступа";
    };
  }

  rpc GetUsers(GetUsersReq) returns (GetUsersRsp) {
    option (google.api.http) = {
      get: "/api/users"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Пользователи";
      summary: "Получить всех пользователей";
    };
  }

  rpc GetUserById(GetUserByIdReq) returns (GetUserByIdRsp) {
    option (google.api.http) = {
      get: "/api/users/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Пользователи";
      summary: "Получить пользователя по id";
    };
  }

  rpc GetMe(GetMeReq) returns (GetMeRsp) {
    option (google.api.http) = {
      get: "/api/users/me"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Пользователи";
      summary: "Получить информацию о себе";
    };
  }

  rpc AddUserRole(AddUserRoleReq) returns (AddUserRoleRsp) {
    option (google.api.http) = {
      post: "/api/users/{id}/role/add"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Пользователи";
      summary: "Добавить пользователю роль";
    };
  }

  rpc DeleteUserRole(DeleteUserRoleReq) returns (DeleteUserRoleRsp) {
    option (google.api.http) = {
      post: "/api/users/{id}/role/delete"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Пользователи";
      summary: "Забрать у пользователя роль";
    };
  }

  rpc GetPermissions(GetPermissionsReq) returns (GetPermissionsRsp) {
    option (google.api.http) = {
      get: "/api/ui/permissions"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Доступы";
      summary: "Получить список доступных элементов интерфейса";
    };
  }

  rpc UploadFile(UploadFileReq) returns (UploadFileRsp) {
    option (google.api.http) = {
      post: "/api/files/upload"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Файлы";
      summary: "Загрузить файл";
    };
  }

  rpc DownloadFile(DownloadFileReq) returns (google.api.HttpBody) {
    option (google.api.http) = {
      get: "/api/files/{filename}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Файлы";
      summary: "Получить файл";
    };
  }

  rpc AddScenario(AddScenarioReq) returns (AddScenarioRsp) {
    option (google.api.http) = {
      post: "/api/scenario"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Создать сценарий";
    };
  }

  rpc GetMyScenarios(GetMyScenariosReq) returns (GetMyScenariosRsp) {
    option (google.api.http) = {
      get: "/api/my-scenarios"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Получить свои сценарии";
    };
  }

  rpc GetScenariosCatalog(GetScenariosCatalogReq) returns (GetScenariosCatalogRsp) {
    option (google.api.http) = {
      get: "/api/catalog"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Получить каталог сценариев";
    };
  }

  rpc GetFullScenario(GetScenarioReq) returns (GetScenarioRsp) {
    option (google.api.http) = {
      get: "/api/scenarios/{id}/full"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Получить сценарий со всеми деталями по id";
    };
  }

  rpc GetScenario(GetScenarioReq) returns (GetScenarioRsp) {
    option (google.api.http) = {
      get: "/api/scenarios/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Получить сценарий по id";
    };
  }

  rpc UpdateScenario(UpdateScenarioReq) returns (UpdateScenarioRsp) {
    option (google.api.http) = {
      put : "/api/scenarios/{id}"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Редактировать сценарий";
    };
  }

  rpc PublicScenario(PublicScenarioReq) returns (PublicScenarioRsp) {
    option (google.api.http) = {
      put : "/api/scenarios/{id}/public"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Опубликовать сценарий";
    };
  }

  rpc DraftScenario(DraftScenarioReq) returns (DraftScenarioRsp) {
    option (google.api.http) = {
      put : "/api/scenarios/{id}/draft"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Снять с публикации сценарий";
    };
  }

  rpc DeleteScenario(DeleteScenarioReq) returns (DeleteScenarioRsp) {
    option (google.api.http) = {
      delete: "/api/scenarios/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Сценарии";
      summary: "Удалить сценарий";
    };
  }

  rpc AddScenarioPlace(AddScenarioPlaceReq) returns (AddScenarioPlaceRsp) {
    option (google.api.http) = {
      post: "/api/scenarios/{id}/places"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Точки сценария";
      summary: "Создать точку сценария";
    };
  }

  rpc UpdateScenarioPlace(UpdateScenarioPlaceReq) returns (UpdateScenarioPlaceRsp) {
    option (google.api.http) = {
      put : "/api/scenarios/{id}/places/{code}"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Точки сценария";
      summary: "Обновить точку сценария";
    };
  }

  rpc DeleteScenarioPlace(DeleteScenarioPlaceReq) returns (DeleteScenarioPlaceRsp) {
    option (google.api.http) = {
      delete: "/api/scenarios/{id}/places/{code}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Точки сценария";
      summary: "Удалить точку сценария";
    };
  }

  rpc AddGame(AddGameReq) returns (AddGameRsp) {
    option (google.api.http) = {
      post: "/api/games"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Создать игру";
    };
  }

  rpc GetGames(GetGamesReq) returns (GetGamesRsp) {
    option (google.api.http) = {
      get: "/api/games"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Получить игры";
    };
  }

  rpc GetGame(GetGameReq) returns (GetGameRsp) {
    option (google.api.http) = {
      get: "/api/games/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Получить игру";
    };
  }

  rpc UpdateGame(UpdateGameReq) returns (UpdateGameRsp) {
    option (google.api.http) = {
      put : "/api/games/{id}"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Обновить игру";
    };
  }

  rpc StartGame(StartGameReq) returns (StartGameRsp) {
    option (google.api.http) = {
      put : "/api/games/{id}/start"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Начать игру";
    };
  }

  rpc PauseGame(PauseGameReq) returns (PauseGameRsp) {
    option (google.api.http) = {
      put : "/api/games/{id}/pause"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Остановить игру";
    };
  }

  rpc FinishGame(FinishGameReq) returns (FinishGameRsp) {
    option (google.api.http) = {
      put : "/api/games/{id}/finish"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Закончить игру";
    };
  }

  rpc ResetGame(ResetGameReq) returns (ResetGameRsp) {
    option (google.api.http) = {
      put : "/api/games/{id}/reset"
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Сбросить игру";
    };
  }

  rpc DeleteGame(DeleteGameReq) returns (DeleteGameRsp) {
    option (google.api.http) = {
      delete: "/api/games/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Игры";
      summary: "Удалить игру";
    };
  }

  rpc AddTeam(AddTeamReq) returns (AddTeamRsp) {
    option (google.api.http) = {
      post: "/api/teams",
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Команда";
      summary: "Создать команду";
    };
  }

  rpc UpdateTeam(UpdateTeamReq) returns (UpdateTeamRsp) {
    option (google.api.http) = {
      put : "/api/teams/{id}",
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Команда";
      summary: "Обновить команду";
    };
  }

  rpc DeleteTeam(DeleteTeamReq) returns (DeleteTeamRsp) {
    option (google.api.http) = {
      delete: "/api/teams/{id}"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Команда";
      summary: "Удалить команду";
    };
  }

  rpc GiveTeamApplications(GiveTeamApplicationsReq) returns (GiveTeamApplicationsRsp) {
    option (google.api.http) = {
      post: "/api/teams/{id}/applications",
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Команда";
      summary: "Выдать улику";
    };
  }

  rpc GetTeamStory(GetTeamStoryReq) returns (GetTeamStoryRsp) {
    option (google.api.http) = {
      get: "/api/teams/{id}/story"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      tags   : "Ходы";
      summary: "Получить ходы";
    };
  }

  rpc AddTeamAction(AddTeamActionReq) returns (AddTeamActionRsp) {
    option (google.api.http) = {
      post: "/api/teams/{id}/actions",
      body: "*"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      security: {
        security_requirement: {}
      }
      tags   : "Ходы";
      summary: "Сделать ход";
    };
  }

  rpc DeleteLastTeamAction(DeleteLastTeamActionReq) returns (DeleteLastTeamActionRsp) {
    option (google.api.http) = {
      delete: "/api/teams/{id}/last-actions"
    };
    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      tags   : "Ходы";
      summary: "Удалить последний ход";
    };
  }
}

message PingReq {}

message PingRsp {}

message EchoReq {
  string text = 1;
}

message EchoRsp {
  string text = 1;
}

message SignupReq {
  string username = 1;
  string email    = 2;
}

message SignupRsp {
  string error = 1;
}

message RefreshPasswordReq {
  string email = 1;
}

message RefreshPasswordRsp {
  string error = 1;
}

message LoginReq {
  string email    = 1;
  string password = 2;
}

message LoginRsp {
  string error        = 1;
  string accessToken  = 2;
  string refreshToken = 3;
}

message RefreshReq {
  string refreshToken = 1;
}

message RefreshRsp {
  string error        = 1;
  string accessToken  = 2;
  string refreshToken = 3;
}

message GetUsersReq {}

message GetUsersRsp {
  string        error = 1;
  repeated User users = 2;
}

message User {
  int32                     id         = 1;
  string                    username   = 2;
  string                    email      = 3;
  repeated string           roles      = 4;
  bool                      is_active  = 5;
  google.protobuf.Timestamp created_at = 6;
}

message GetUserByIdReq {
  int32 id = 1;
}

message GetUserByIdRsp {
  string error = 1;
  User   user  = 2;
}

message GetMeReq {}

message GetMeRsp {
  string error = 1;
  User   user  = 2;
}

message AddUserRoleReq {
  int32  id   = 1;
  string role = 2;
}

message AddUserRoleRsp {
  string error = 1;
}

message DeleteUserRoleReq {
  int32  id   = 1;
  string role = 2;
}

message DeleteUserRoleRsp {
  string error = 1;
}

message GetPermissionsReq {}

message GetPermissionsRsp {
  string          error       = 1;
  repeated string permissions = 2;
}

message UploadFileReq {
  string filename = 1;
  bytes  data     = 2;
}

message UploadFileRsp {
  string error    = 1;
  string filename = 2;
}

message DownloadFileReq {
  string filename = 1;
}

message AddScenarioReq {
  string name = 1;
}

message AddScenarioRsp {
  string error = 1;
  int32  id    = 2;
}

message GetMyScenariosReq {}

message GetMyScenariosRsp {
  string            error     = 1;
  repeated Scenario scenarios = 2;
}

message GetScenariosCatalogReq {}

message GetScenariosCatalogRsp {
  string            error     = 1;
  repeated Scenario scenarios = 2;
}

message GetScenarioReq {
  int32 id = 1;
}

message GetScenarioRsp {
  string   error    = 1;
  Scenario scenario = 2;
}

message Scenario {
  int32                     id           = 1;
  string                    name         = 2;
  optional string           description  = 3;
  optional string           image        = 4;
  Story                     story        = 5;
  string                    status       = 6;
  User                      author       = 7;
  google.protobuf.Timestamp updated_at   = 8;
  google.protobuf.Timestamp created_at   = 9;
  google.protobuf.Timestamp published_at = 10;
}

message Story {
  repeated Place places = 1;
}

message Place {
  string               code         = 1;
  string               name         = 2;
  string               text         = 3;
  string               image        = 4;
  bool                 hidden       = 5;
  repeated Application applications = 6;
  repeated Door        doors        = 7;
  repeated Key         keys         = 8;
}

message Application {
  string name  = 1;
  string image = 2;
}

message Door {
  string       code = 1;
  string       name = 2;
  repeated Key keys = 3;
}

message Key {
  string name = 1;
}

message UpdateScenarioReq {
  int32  id          = 1;
  string name        = 2;
  string description = 3;
  string image       = 4;
}

message UpdateScenarioRsp {
  string error = 1;
}

message PublicScenarioReq {
  int32 id = 1;
}

message PublicScenarioRsp {
  string error = 1;
}

message DraftScenarioReq {
  int32 id = 1;
}

message DraftScenarioRsp {
  string error = 1;
}

message DeleteScenarioReq {
  int32 id = 1;
}

message DeleteScenarioRsp {
  string error = 1;
}

message AddScenarioPlaceReq {
  int32 id    = 1;
  Place place = 2;
}

message AddScenarioPlaceRsp {
  string error = 1;
}

message UpdateScenarioPlaceReq {
  int32  id    = 1;
  string code  = 2;
  Place  place = 3;
}

message UpdateScenarioPlaceRsp {
  string error = 1;
}

message DeleteScenarioPlaceReq {
  int32  id   = 1;
  string code = 2;
}

message DeleteScenarioPlaceRsp {
  string error = 1;
}

message AddGameReq {
  string                    name        = 1;
  string                    description = 2;
  google.protobuf.Timestamp start_at    = 3;
  int32                     scenario_id = 4;
}

message AddGameRsp {
  string error = 1;
  int32  id    = 2;
}

message GetGamesReq {}

message GetGamesRsp {
  string        error = 1;
  repeated Game games = 2;
}

message Game {
  int32                              id          = 1;
  string                             name        = 2;
  string                             description = 3;
  google.protobuf.Timestamp          start_at    = 4;
  string                             status      = 5;
  Scenario                           scenario    = 6;
  repeated Team                      teams       = 7;
  optional google.protobuf.Timestamp started_at  = 8;
  optional google.protobuf.Timestamp ended_at    = 9;
}

message Team {
  int32                id            = 1;
  string               name          = 2;
  string               status        = 3;
  string               password      = 4;
  int32                actions_count = 5;
  repeated Application applications  = 6;
}

message GetGameReq {
  int32 id = 1;
}

message GetGameRsp {
  string error = 1;
  Game   game  = 2;
}

message UpdateGameReq {
  int32                     id          = 1;
  string                    name        = 2;
  string                    description = 3;
  google.protobuf.Timestamp start_at    = 4;
  int32                     scenario_id = 5;
}

message UpdateGameRsp {
  string error = 1;
}

message StartGameReq {
  int32 id = 1;
}

message StartGameRsp {
  string error = 1;
}

message PauseGameReq {
  int32 id = 1;
}

message PauseGameRsp {
  string error = 1;
}

message FinishGameReq {
  int32 id = 1;
}

message FinishGameRsp {
  string error = 1;
}

message ResetGameReq {
  int32 id = 1;
}

message ResetGameRsp {
  string error = 1;
}

message DeleteGameReq {
  int32 id = 1;
}

message DeleteGameRsp {
  string error = 1;
}

message AddTeamReq {
  int32  game_id = 1;
  string name    = 2;
}

message AddTeamRsp {
  string error    = 1;
  int32  id       = 2;
  string password = 3;
}

message UpdateTeamReq {
  int32  id   = 1;
  string name = 2;
}

message UpdateTeamRsp {
  string error = 1;
}

message DeleteTeamReq {
  int64 id = 1;
}

message DeleteTeamRsp {
  string error = 1;
}

message GiveTeamApplicationsReq {
  int64  id   = 1;
  string name = 2;
}

message GiveTeamApplicationsRsp {
  string error = 1;
}

message GetTeamStoryReq {
  int64  id       = 1;
  string password = 2;
}

message GetTeamStoryRsp {
  string error = 1;
  Story  story = 2;
  Game   game  = 3;
}

message AddTeamActionReq {
  int64  id       = 1;
  string password = 2;
  string code     = 3;
}

message AddTeamActionRsp {
  string error = 1;
}

message DeleteLastTeamActionReq {
  int64 id = 1;
}

message DeleteLastTeamActionRsp {
  string error = 1;
}
