syntax = "proto3";

package web3auth;

option go_package = "github.com/echofi-ai/schema/v2/types/web3auth";

import "web3auth/wallet.proto";
import "web3auth/auth_proof.proto";

// Web3AuthService defines the gRPC service for Web3 wallet-based authentication
// These methods strictly follow the web3-integrate-flow.md document
service Web3AuthService {
  // ========== WEB3-FIRST FLOW ==========

  // GetChallenge generates a challenge for wallet authentication
  // This challenge must be signed to prove wallet ownership
  rpc GetChallenge(GetChallengeRequest) returns (GetChallengeResponse) {}

  // AuthWithSignature authenticates or creates a user using wallet address and signature
  // Follows Web3-first flow: Connect Wallet -> Account Check -> Create/Auth -> Proof Storage -> Session Token
  rpc AuthWithSignature(AuthWithSignatureRequest) returns (AuthWithSignatureResponse) {}

  // AuthWithProof performs fast authentication using existing client-side proof
  // Follows Web3-first flow: Check LocalStorage Proof -> Validate -> Session Token
  rpc AuthWithProof(AuthWithProofRequest) returns (AuthWithProofResponse) {}

  // ========== WEB2-FIRST FLOW ==========

  // LinkWalletToWeb2Account links a wallet to an existing Web2 account (email/OAuth)
  // Follows Web2-first flow: Authorization Header -> Wallet Link Validation -> Connect Wallet
  rpc LinkWalletToWeb2Account(LinkWalletToWeb2AccountRequest) returns (LinkWalletToWeb2AccountResponse) {}

  // ========== ACCOUNT LINKING VALIDATION ==========

  // CheckWalletLinkingStatus checks if a wallet can be linked (not already connected elsewhere)
  // Used in Web2-first flow validation step
  rpc CheckWalletLinkingStatus(CheckWalletLinkingStatusRequest) returns (CheckWalletLinkingStatusResponse) {}

  // CheckEmailLinkingStatus checks if an email can be linked (not already connected elsewhere)
  // Used in Web3-first flow validation step
  rpc CheckEmailLinkingStatus(CheckEmailLinkingStatusRequest) returns (CheckEmailLinkingStatusResponse) {}

  // LinkEmailToWeb3Account links an email account to an existing Web3 account
  // Follows Web3-first flow: Authorization Header -> Email Link Validation -> Connect Email
  rpc LinkEmailToWeb3Account(LinkEmailToWeb3AccountRequest) returns (LinkEmailToWeb3AccountResponse) {}

  // GetAccountStatus returns the current account linking status
  // Requires authentication
  rpc GetAccountStatus(GetAccountStatusRequest) returns (GetAccountStatusResponse) {}
}

// GetChallenge requests and responses
message GetChallengeRequest {
  // Wallet address to generate challenge for
  string wallet_address = 1;
}

message GetChallengeResponse {
  // Challenge string that must be signed
  string challenge = 1;

  // Challenge expiration timestamp (Unix timestamp)
  int64 expires_at = 2;

  // Proof lifetime in seconds (configurable by server)
  int64 proof_lifetime_seconds = 3;
}

// AuthWithSignature requests and responses (with signature verification)
message AuthWithSignatureRequest {
  // Wallet address to authenticate or register
  string wallet_address = 1;

  // Challenge that was signed
  string challenge = 2;

  // Signature of the challenge (hex-encoded)
  string signature = 3;
}

message AuthWithSignatureResponse {
  // User information (existing or newly created)
  Web3User user = 1;

  // Session token for authentication
  string session_token = 2;

  // Session expiration timestamp (Unix timestamp)
  int64 session_expires_at = 3;

  // Whether this was a new user creation
  bool is_new_user = 4;

  // Client-side auth proof (store locally for future quick auth)
  AuthProof auth_proof = 5;

  // Success message
  string message = 6;
}

// AuthWithProof requests (using stored client-side proof)
message AuthWithProofRequest {
  // Wallet address to authenticate
  string wallet_address = 1;

  // Client-side auth proof
  AuthProof auth_proof = 2;
}

message AuthWithProofResponse {
  // User information
  Web3User user = 1;

  // Session token for authentication
  string session_token = 2;

  // Session expiration timestamp (Unix timestamp)
  int64 session_expires_at = 3;

  // Success message
  string message = 4;
}

// Client-side authentication proof (stored locally by user)
message AuthProof {
  // Wallet address this proof is for
  string wallet_address = 1;

  // Original challenge that was signed
  string challenge = 2;

  // User's signature of the challenge
  string signature = 3;

  // When this proof was issued (Unix timestamp)
  int64 issued_at = 4;

  // When this proof expires (Unix timestamp)
  int64 expires_at = 5;

  // User ID associated with this proof
  string user_id = 6;
}

// ConnectWalletToUser requests and responses (requires authentication)
message ConnectWalletToUserRequest {
  // Wallet address to connect
  string wallet_address = 1;
}

message ConnectWalletToUserResponse {
  // Updated user information with wallet
  Web3User user = 1;

  // Success message
  string message = 2;
}

// LinkWalletToAccount requests and responses (flexible authentication)
message LinkWalletToAccountRequest {
  // Wallet address to link
  string wallet_address = 1;

  // Authentication options (one of these must be provided)
  oneof auth_method {
    // Option 1: Use existing session token
    string session_token = 2;

    // Option 2: Use email and password for authentication
    EmailPasswordAuth email_password = 3;
  }
}

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

message LinkWalletToAccountResponse {
  // Updated user information with wallet
  Web3User user = 1;

  // New session token (always provided for convenience)
  string session_token = 2;

  // Session expiration timestamp (Unix timestamp)
  int64 expires_at = 3;

  // Success message
  string message = 4;
}

// GetAccountStatus requests and responses
message GetAccountStatusRequest {
  // No additional fields needed - user is identified from authentication context
}

message GetAccountStatusResponse {
  // Current user information
  Web3User user = 1;

  // Account status information
  bool has_email = 2;
  bool has_wallet = 3;
  bool is_linked_account = 4;

  // Available actions
  bool can_connect_wallet = 5;
  bool can_disconnect_wallet = 6;
  bool can_link_email = 7;
  bool can_unlink_email = 8;
}

// ========== NEW FLOW-SPECIFIC MESSAGES ==========

// LinkWalletToWeb2Account requests and responses (Web2-first flow)
message LinkWalletToWeb2AccountRequest {
  // Wallet address to link
  string wallet_address = 1;
  // Note: Authentication is now handled via Authorization header
}

message LinkWalletToWeb2AccountResponse {
  // Updated user information with wallet
  Web3User user = 1;

  // Success message
  string message = 2;

  // Whether this completed the account linking
  bool linking_complete = 3;
}

// CheckWalletLinkingStatus requests and responses
message CheckWalletLinkingStatusRequest {
  // Wallet address to check
  string wallet_address = 1;
}

message CheckWalletLinkingStatusResponse {
  // Whether the wallet can be linked
  bool can_link = 1;

  // Error message if cannot link
  string error_message = 2;

  // Whether wallet is already linked to another account
  bool already_linked = 3;

  // If already linked, the linked user ID (for debugging)
  string linked_user_id = 4;
}

// CheckEmailLinkingStatus requests and responses
message CheckEmailLinkingStatusRequest {
  // Email address to check
  string email = 1;
}

message CheckEmailLinkingStatusResponse {
  // Whether the email can be linked
  bool can_link = 1;

  // Error message if cannot link
  string error_message = 2;

  // Whether email is already registered/linked
  bool already_linked = 3;

  // If already linked, whether it's linked to Google OAuth
  bool linked_to_google = 4;
}

// LinkEmailToWeb3Account requests and responses (Web3-first flow)
message LinkEmailToWeb3AccountRequest {
  // Email to link
  string email = 1;

  // Password for the email account
  string password = 2;
  // Note: Authentication is now handled via Authorization header
}

message LinkEmailToWeb3AccountResponse {
  // Updated user information with email
  Web3User user = 1;

  // Success message
  string message = 2;

  // Whether this completed the account linking
  bool linking_complete = 3;
}
