// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.cloud.dataqna.v1alpha;

import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/cloud/dataqna/v1alpha/annotated_string.proto";
import "google/protobuf/any.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";

option csharp_namespace = "Google.Cloud.DataQnA.V1Alpha";
option go_package = "cloud.google.com/go/dataqna/apiv1alpha/dataqnapb;dataqnapb";
option java_multiple_files = true;
option java_outer_classname = "QuestionProto";
option java_package = "com.google.cloud.dataqna.v1alpha";
option php_namespace = "Google\\Cloud\\DataQnA\\V1alpha";
option ruby_package = "Google::Cloud::DataQnA::V1alpha";

// The question resource represents a natural language query, its settings,
// understanding generated by the system, and answer retrieval status.
// A question cannot be modified.
message Question {
  option (google.api.resource) = {
    type: "dataqna.googleapis.com/Question"
    pattern: "projects/{project}/locations/{location}/questions/{question}"
  };

  // Output only. Immutable. The unique identifier for the Question. The ID is server-generated.
  // Example: `projects/foo/locations/bar/questions/123`
  string name = 1 [
    (google.api.field_behavior) = OUTPUT_ONLY,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Required. Immutable. Scopes to be used for the question. A scope defines the relevant data set
  // scope. It can be a reference to a specific data source or a collection of
  // data sources. Currently, support is limited to a single BigQuery table.
  // There must be exactly one `scopes` element.
  //
  // Example:
  // `//bigquery.googleapis.com/projects/test-project/datasets/foo/tables/bar`
  repeated string scopes = 2 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // Required. Immutable. The query in natural language.
  string query = 3 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.field_behavior) = IMMUTABLE
  ];

  // A list of annotations to use instead of the default annotation of a data
  // source (set in the data source reference resource). There must not be
  // more than one annotation with the same data source reference.
  repeated string data_source_annotations = 4;

  // An error field explaining why interpretation failed. This is only populated
  // if the interpretation failed.
  //
  // Note: This is different from getting a status error on the request itself.
  // This is not a client or server error and the Question resource is still
  // persisted, but the service could not interpret the question. Clients should
  // present the error to the user so the user can rephrase the question.
  InterpretError interpret_error = 5;

  // A list of interpretations for this question.
  repeated Interpretation interpretations = 6;

  // Time when the question was created.
  google.protobuf.Timestamp create_time = 7;

  // Output only. The e-mail address of the user that created this question.
  string user_email = 8 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Input only. Immutable. Flags to request additional information for debugging purposes.
  DebugFlags debug_flags = 9 [
    (google.api.field_behavior) = IMMUTABLE,
    (google.api.field_behavior) = INPUT_ONLY
  ];

  // Top level debug information.
  // This will be stored as the type DebugInformation.
  // Using Any so clients don't need to pull in anything
  // inside the debug message.
  google.protobuf.Any debug_info = 10;
}

// Details on the failure to interpret the question.
message InterpretError {
  // Details on interpretation failure.
  message InterpretErrorDetails {
    // Populated if parts of the query are unsupported.
    InterpretUnsupportedDetails unsupported_details = 1;

    // Populated if the query is incomplete.
    InterpretIncompleteQueryDetails incomplete_query_details = 2;

    // Populated if the query was too ambiguous.
    InterpretAmbiguityDetails ambiguity_details = 3;
  }

  // Details about unsupported parts in a query.
  message InterpretUnsupportedDetails {
    // Unsupported operators. For example: median.
    repeated string operators = 1;

    // Unsupported intents.
    repeated string intent = 2;
  }

  // Details about an incomplete query.
  message InterpretIncompleteQueryDetails {
    // List of missing interpret entities.
    repeated InterpretEntity entities = 1;
  }

  // Details about a query that was too ambiguous. Currently, the message
  // has no fields and its presence signals that there was ambiguity.
  message InterpretAmbiguityDetails {

  }

  // The interpret error code provides an error category why the interpretation
  // failed.
  enum InterpretErrorCode {
    // No interpret error code was specified.
    INTERPRET_ERROR_CODE_UNSPECIFIED = 0;

    // The query is not valid.
    INVALID_QUERY = 1;

    // The interpreter failed to understand the question. For example, because
    // it was too ambiguous.
    FAILED_TO_UNDERSTAND = 2;

    // The interpreter could understand the question, but was not able to arrive
    // at an answer. For example, because a requested operation is not
    // supported.
    FAILED_TO_ANSWER = 3;
  }

  // Error message explaining why this question could not be interpreted.
  string message = 1;

  // The code for the error category why the interpretation failed.
  InterpretErrorCode code = 2;

  // Details on interpretation failure.
  InterpretErrorDetails details = 3;
}

// Information about the backend status (such as BigQuery) of the execution.
message ExecutionInfo {
  // Enum of possible job execution statuses.
  enum JobExecutionState {
    // No job execution was specified.
    JOB_EXECUTION_STATE_UNSPECIFIED = 0;

    // No job execution was requested, yet.
    NOT_EXECUTED = 1;

    // The job is running.
    RUNNING = 2;

    // The job completed successfully.
    SUCCEEDED = 3;

    // The job completed unsuccessfully.
    FAILED = 4;
  }

  // Status returned by the backend when the job was created.
  google.rpc.Status job_creation_status = 1;

  // Status of the job execution.
  JobExecutionState job_execution_state = 2;

  // Time when the execution was triggered.
  google.protobuf.Timestamp create_time = 3;

  // BigQuery job information.
  // Future versions will have different backends. Hence, clients must make sure
  // they can handle it when this field is not populated.
  BigQueryJob bigquery_job = 4;
}

// BigQuery job information. This can be used to query the BigQuery API and
// retrieve the current job's status (using
// [jobs.get](https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/get)).
message BigQueryJob {
  // The job ID.
  string job_id = 1;

  // The project ID of the job.
  string project_id = 2;

  // The location where the job is running.
  string location = 3;
}

// An interpretation of a natural language query.
message Interpretation {
  // List of data sources used in the current understanding.
  repeated string data_sources = 1;

  // The level of confidence that one of the interpretations is correct. This is
  // a value in the range [0, 1] where a value of 0.5 or below is to be
  // considered a low confidence.
  double confidence = 2;

  // A list of unused phrases. Clients should display a Did You Mean (DYM)
  //  dialog if this is non-empty, even if this is the only interpretation.
  repeated string unused_phrases = 3;

  // Human readable representation of the query.
  HumanReadable human_readable = 4;

  // Information about the interpretation structure that helps to understand and
  // visualize the response.
  InterpretationStructure interpretation_structure = 5;

  // Representation of the data query to be sent to the backend.
  DataQuery data_query = 6;

  // Information about the backend response. This is populated only if execution
  // of an interpretation was requested.
  ExecutionInfo execution_info = 7;
}

// Representation of the data query for the backend.
// This is provided for informational purposes only. Clients should not use
// it to send it to the backend directly, but rather use the `execute` RPC
// to trigger the execution. Using the `execute` RPC is needed in order to
// track the state of a question and report on it correctly to the data
// administrators.
message DataQuery {
  // The generated SQL query to be sent to the backend.
  string sql = 1;
}

// Human readable interpretation.
message HumanReadable {
  // Generated query explaining the interpretation.
  AnnotatedString generated_interpretation = 1;

  // Annotations on the original query.
  AnnotatedString original_question = 2;
}

// Information about the interpretation structure that helps to understand and
// visualize the response.
message InterpretationStructure {
  // Information about a column.
  message ColumnInfo {
    // The alias of the output column as used by the backend. For example, the
    // field name in the schema provided in the query response in BigQuery.
    string output_alias = 1;

    // Human readable name of the output column.
    string display_name = 2;
  }

  // Enumeration of visualzation types to use for query response data.
  enum VisualizationType {
    // No visualization type was specified.
    VISUALIZATION_TYPE_UNSPECIFIED = 0;

    // Show a table.
    TABLE = 1;

    // Show a [bar
    // chart](https://developers.google.com/chart/interactive/docs/gallery/barchart).
    BAR_CHART = 2;

    // Show a [column
    // chart](https://developers.google.com/chart/interactive/docs/gallery/columnchart).
    COLUMN_CHART = 3;

    // Show a
    // [timeline](https://developers.google.com/chart/interactive/docs/gallery/timeline).
    TIMELINE = 4;

    // Show a [scatter
    // plot](https://developers.google.com/chart/interactive/docs/gallery/scatterchart).
    SCATTER_PLOT = 5;

    // Show a [pie
    // chart](https://developers.google.com/chart/interactive/docs/gallery/piechart).
    PIE_CHART = 6;

    // Show a [line
    // chart](https://developers.google.com/chart/interactive/docs/gallery/linechart).
    LINE_CHART = 7;

    // Show an [area
    // chart](https://developers.google.com/chart/interactive/docs/gallery/areachart).
    AREA_CHART = 8;

    // Show a [combo
    // chart](https://developers.google.com/chart/interactive/docs/gallery/combochart).
    COMBO_CHART = 9;

    // Show a
    // [histogram](https://developers.google.com/chart/interactive/docs/gallery/histogram).
    HISTOGRAM = 10;

    // This denotes queries when the user has not specified the particular type
    // of chart and has mentioned only a generic chart name such as "Chart",
    // "Plot", "Graph", etc. This will differentiate it from specific charting
    // terms such as "Bar chart", "Pie chart", etc.
    GENERIC_CHART = 11;

    // The user tried to specify a chart type, but the interpreter could not
    // understand the type. The client should display a generic chart and may
    // give a hint to the user that the requested type was not understood.
    CHART_NOT_UNDERSTOOD = 12;
  }

  // List of possible visualization types to apply for this interpretation. The
  // order has no relevance.
  repeated VisualizationType visualization_types = 1;

  // Information about the output columns, that is, the columns that will be
  // returned by the backend.
  repeated ColumnInfo column_info = 2;
}

// Configuriation of debug flags.
message DebugFlags {
  // Whether to include the original VAQuery.
  bool include_va_query = 1;

  // Whether to include the original nested VAQuery.
  bool include_nested_va_query = 2;

  // Whether to include the original human interpretation strings generated
  // by Analyza.
  bool include_human_interpretation = 3;

  // Whether to include the Aqua debug response.
  bool include_aqua_debug_response = 4;

  // The time in milliseconds from Unix epoch to be used
  // to process the query. This is useful for testing
  // the queries at different time period.
  // If not set or time_override <= 0, then the current
  // time is used.
  int64 time_override = 5;

  // Set to true if request is initiated by an internal Google user.
  bool is_internal_google_user = 6;

  // Determines whether cache needs to be ignored. If set to
  // true, cache won't be queried and updated.
  bool ignore_cache = 7;

  // Whether to include the request/response pair from the call to the
  // EntityIndex for SearchEntities.
  bool include_search_entities_rpc = 8;

  // Whether to include the request/response pair from the call to the
  // Annotations service for ListColumnAnnotations.
  bool include_list_column_annotations_rpc = 9;

  // Whether to include the entity list passed to Analyza.
  bool include_virtual_analyst_entities = 10;

  // Whether to include the table list.
  bool include_table_list = 11;

  // Whether to include the domain list.
  bool include_domain_list = 12;
}

// Query entities of an interpretation.
enum InterpretEntity {
  // No interpret entity was specified.
  INTERPRET_ENTITY_UNSPECIFIED = 0;

  // A dimenstion entity.
  DIMENSION = 1;

  // A metric entity.
  METRIC = 2;
}
