syntax = "proto3";

package cinch.v1;

option go_package = "github.com/cinchcli/cinch-core/go/cinch/v1;cinchv1";

// ClipsService handles clipboard clip operations.
service ClipsService {
  // PushClip saves a text clip and broadcasts it to connected devices.
  // Mirrors POST /clips — auth required.
  rpc PushClip(PushClipRequest) returns (PushClipResponse);

  // ListClips returns clips for the caller, filtered by `since` (RFC 3339, exclusive),
  // by `source_filter` / `exclude_source`, by content-type filters, or by `clip_ids`,
  // and bounded by `limit` (default 50, max 200). When only `since` is set results
  // are oldest-first for delta replay; otherwise newest-first.
  // Mirrors GET /clips — auth required.
  rpc ListClips(ListClipsRequest) returns (ListClipsResponse);

  // GetLatestClip returns the most recent clip from a specific source.
  // Mirrors GET /clips/latest?source=<hostname> — auth required.
  rpc GetLatestClip(GetLatestClipRequest) returns (GetLatestClipResponse);

  // DeleteClip removes a clip owned by the caller.
  // Mirrors DELETE /clips/{id} — auth required.
  rpc DeleteClip(DeleteClipRequest) returns (DeleteClipResponse);
}

// ─── Clip ────────────────────────────────────────────────────
//
// `content_type` carries one of: "text", "url", "code", "image" — kept as a
// string for legacy REST wire compatibility (JSON enums marshal as numbers
// under encoding/json which would break clients sending lowercase strings).
//
// `created_at` is RFC3339 (e.g. "2026-04-30T12:00:00Z") — string for the
// same reason: google.protobuf.Timestamp marshals as `{seconds, nanos}`
// under encoding/json, which is incompatible with the legacy wire.

message Clip {
  string clip_id = 1;
  string user_id = 2;
  string content = 3;
  string content_type = 4;
  string source = 5;
  string label = 6;
  int64 byte_size = 7;
  optional string media_path = 8;
  string created_at = 9;
  // field 10 (ttl) removed — do not reuse
  bool encrypted = 11;
  bool is_pinned = 12;
  optional string pin_note = 13;
}

// ─── PushClip ────────────────────────────────────────────────

message PushClipRequest {
  string content = 1;
  string content_type = 2;
  string label = 3;
  string source = 4;
  // field 5 (ttl) removed — do not reuse
  int64 byte_size = 6;
  bool encrypted = 7;
  optional string target_device_id = 8;
  optional string media_path = 9;
}

message PushClipResponse {
  string clip_id = 1;
  int64 byte_size = 2;
}

// ─── ListClips ───────────────────────────────────────────────

message ListClipsRequest {
  string since = 1; // RFC 3339 timestamp; empty = no filter (returns most recent)
  int32 limit = 2; // 0 = default (50), max 200
  string source_filter = 3; // resolved source key; empty = no filter
  string exclude_source = 4; // resolved source key to exclude; empty = no exclusion
  bool exclude_image = 5; // when true, drop image clips
  bool exclude_text = 6; // when true, drop text clips
  repeated string clip_ids = 7; // when non-empty, return only these clips (max 200)
}

message ListClipsResponse {
  repeated Clip clips = 1;
}

// ─── GetLatestClip ───────────────────────────────────────────

message GetLatestClipRequest {
  string source = 1;
  string exclude_source = 2; // when set, return latest clip whose source != exclude_source
}

message GetLatestClipResponse {
  Clip clip = 1;
}

// ─── DeleteClip ──────────────────────────────────────────────

message DeleteClipRequest {
  string clip_id = 1;
}

message DeleteClipResponse {
  bool ok = 1;
}
