datasource db {
  provider  = "postgresql"
  url       = env("DATABASE_URL")
  directUrl = env("DIRECT_URL")
}

generator client {
  provider        = "prisma-client-js"
  binaryTargets   = ["native", "debian-openssl-1.1.x"]
  previewFeatures = ["tracing"]
}

model Activity {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  text      String
  // Used to link the task or activity to external apps
  sourceURL String?

  integrationAccount   IntegrationAccount? @relation(fields: [integrationAccountId], references: [id])
  integrationAccountId String?

  rejectionReason String?

  workspace   Workspace @relation(fields: [workspaceId], references: [id])
  workspaceId String

  WebhookDeliveryLog WebhookDeliveryLog[]

  ConversationHistory ConversationHistory[]
  IngestionQueue      IngestionQueue[]
}

model AuthorizationCode {
  id String @id @default(cuid())

  code String @unique

  personalAccessToken   PersonalAccessToken? @relation(fields: [personalAccessTokenId], references: [id], onDelete: Cascade, onUpdate: Cascade)
  personalAccessTokenId String?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model Conversation {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  unread Boolean @default(false)

  title  String?
  user   User    @relation(fields: [userId], references: [id])
  userId String

  workspace   Workspace? @relation(fields: [workspaceId], references: [id])
  workspaceId String?

  status String @default("pending") // Can be "pending", "running", "completed", "failed", "need_attention"

  ConversationHistory ConversationHistory[]
  RecallLog           RecallLog[]
}

model ConversationExecutionStep {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  thought String
  message String

  actionId     String?
  actionOutput String?
  actionInput  String?
  actionStatus String?

  metadata Json? @default("{}")

  conversationHistory   ConversationHistory @relation(fields: [conversationHistoryId], references: [id])
  conversationHistoryId String
}

model ConversationHistory {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  message  String
  userType UserType

  activity   Activity? @relation(fields: [activityId], references: [id])
  activityId String?

  context Json?

  thoughts Json?
  user     User?   @relation(fields: [userId], references: [id])
  userId   String?

  conversation              Conversation                @relation(fields: [conversationId], references: [id])
  conversationId            String
  ConversationExecutionStep ConversationExecutionStep[]
}

model IngestionQueue {
  id String @id @default(cuid())

  // Relations
  space   Space?  @relation(fields: [spaceId], references: [id])
  spaceId String?

  // Queue metadata
  data     Json // The actual data to be processed
  output   Json? // The processed output data
  status   IngestionStatus
  priority Int             @default(0)

  type String?

  workspaceId String
  workspace   Workspace @relation(fields: [workspaceId], references: [id])

  activity   Activity? @relation(fields: [activityId], references: [id])
  activityId String?

  // Error handling
  error      String?
  retryCount Int     @default(0)

  // Timestamps
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
  processedAt DateTime?
}

model IngestionRule {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  name     String? // Optional human-readable rule name
  text     String // Free-flowing text rule description (mandatory)
  source   String // Source/integration this rule applies to (mandatory)
  isActive Boolean @default(true) // Enable/disable rule (mandatory)

  workspace   Workspace @relation(fields: [workspaceId], references: [id])
  workspaceId String

  user   User   @relation(fields: [userId], references: [id])
  userId String
}

model IntegrationAccount {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  integrationConfiguration Json
  accountId                String?
  settings                 Json?
  isActive                 Boolean @default(true)

  integratedBy            User                    @relation(references: [id], fields: [integratedById])
  integratedById          String
  integrationDefinition   IntegrationDefinitionV2 @relation(references: [id], fields: [integrationDefinitionId])
  integrationDefinitionId String
  workspace               Workspace               @relation(references: [id], fields: [workspaceId])
  workspaceId             String
  Activity                Activity[]
  oauthIntegrationGrants  OAuthIntegrationGrant[]

  @@unique([accountId, integrationDefinitionId, workspaceId])
}

model IntegrationDefinitionV2 {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  name        String  @unique
  slug        String
  description String
  icon        String
  config      Json?
  spec        Json    @default("{}")
  version     String?
  url         String?

  workspace   Workspace? @relation(references: [id], fields: [workspaceId])
  workspaceId String?

  IntegrationAccount IntegrationAccount[]
}

model InvitationCode {
  id   String @id @default(cuid())
  code String @unique

  users User[]

  createdAt DateTime @default(now())
}

model MCPSession {
  id           String   @id @default(cuid())
  source       String
  integrations String[]

  workspace   Workspace? @relation(references: [id], fields: [workspaceId])
  workspaceId String?

  createdAt DateTime  @default(now())
  deleted   DateTime?
}

model OAuthAuthorizationCode {
  id String @id @default(cuid())

  code String @unique

  // OAuth2 specific fields
  clientId            String
  userId              String
  redirectUri         String
  scope               String?
  state               String?
  codeChallenge       String?
  codeChallengeMethod String?
  expiresAt           DateTime
  used                Boolean  @default(false)

  // Relations
  client      OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
  user        User        @relation(fields: [userId], references: [id], onDelete: Cascade)
  workspace   Workspace   @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  workspaceId String

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model OAuthAccessToken {
  id String @id @default(cuid())

  token     String   @unique
  clientId  String
  userId    String
  scope     String?
  expiresAt DateTime
  revoked   Boolean  @default(false)

  // Relations
  client      OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
  user        User        @relation(fields: [userId], references: [id], onDelete: Cascade)
  workspace   Workspace   @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  workspaceId String

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model OAuthClient {
  id String @id @default(cuid())

  clientId     String  @unique
  clientSecret String
  name         String
  description  String?

  // Redirect URIs (comma-separated for simplicity)
  redirectUris String

  // Allowed scopes (comma-separated)
  allowedScopes String @default("read")

  // Grant types allowed
  grantTypes String @default("authorization_code")

  // PKCE support
  requirePkce Boolean @default(false)

  clientType String @default("regular")

  // Client metadata
  logoUrl     String?
  homepageUrl String?

  // Integration hub webhook support
  webhookUrl    String?
  webhookSecret String?

  // GitHub-style features
  isActive Boolean @default(true)

  // Workspace relationship (like GitHub orgs)
  workspace   Workspace? @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  workspaceId String?

  // Created by user (for audit trail)
  createdBy   User?   @relation(fields: [createdById], references: [id])
  createdById String?

  // Relations
  oauthAuthorizationCodes OAuthAuthorizationCode[]
  accessTokens            OAuthAccessToken[]
  refreshTokens           OAuthRefreshToken[]
  integrationGrants       OAuthIntegrationGrant[]
  oAuthClientInstallation OAuthClientInstallation[]

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model OAuthClientInstallation {
  id String @id @default(cuid())

  // The OAuth client being installed
  oauthClient   OAuthClient @relation(fields: [oauthClientId], references: [id], onDelete: Cascade)
  oauthClientId String

  // The workspace where it's installed
  workspace   Workspace @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  workspaceId String

  // Installation metadata
  installedBy   User      @relation(fields: [installedById], references: [id])
  installedById String
  installedAt   DateTime  @default(now())
  uninstalledAt DateTime?

  // Installation status
  isActive Boolean @default(true)

  // Installation-specific settings
  settings Json?

  grantedScopes String?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@unique([oauthClientId, workspaceId])
}

model OAuthRefreshToken {
  id String @id @default(cuid())

  token     String   @unique
  clientId  String
  userId    String
  scope     String?
  expiresAt DateTime
  revoked   Boolean  @default(false)

  // Relations
  client      OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
  user        User        @relation(fields: [userId], references: [id], onDelete: Cascade)
  workspace   Workspace   @relation(fields: [workspaceId], references: [id], onDelete: Cascade)
  workspaceId String

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

model OAuthIntegrationGrant {
  id String @id @default(cuid())

  // OAuth client that has access
  client   OAuthClient @relation(fields: [clientId], references: [id], onDelete: Cascade)
  clientId String

  // User who granted access
  user   User   @relation(fields: [userId], references: [id], onDelete: Cascade)
  userId String

  // Integration account that was granted
  integrationAccount   IntegrationAccount @relation(fields: [integrationAccountId], references: [id], onDelete: Cascade)
  integrationAccountId String

  // When access was granted/revoked
  grantedAt DateTime  @default(now())
  revokedAt DateTime?
  isActive  Boolean   @default(true)

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  @@unique([clientId, userId, integrationAccountId])
}

model PersonalAccessToken {
  id String @id @default(cuid())

  /// If generated by the CLI this will be "cli", otherwise user-provided
  name String

  /// This is the token encrypted using the ENCRYPTION_KEY
  encryptedToken Json

  /// This is shown in the UI, with ********
  obfuscatedToken String

  /// This is used to find the token in the database
  hashedToken String @unique

  user   User   @relation(fields: [userId], references: [id])
  userId String

  revokedAt      DateTime?
  lastAccessedAt DateTime?

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  authorizationCodes AuthorizationCode[]
}

model RecallLog {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  // Access details
  accessType String // "search", "recall", "direct_access"
  query      String? // Search query (null for direct access)

  // Target information
  targetType String? // "episode", "statement", "entity", "mixed_results"
  targetId   String? // UUID of specific target (null for search with multiple results)

  // Search/access parameters
  searchMethod  String? // "semantic", "keyword", "hybrid", "contextual", "graph_traversal"
  minSimilarity Float? // Minimum similarity threshold used
  maxResults    Int? // Maximum results requested

  // Results and interaction
  resultCount     Int    @default(0) // Number of results returned
  similarityScore Float? // Similarity score (for single result access)

  // Context and source
  context   String? // Additional context
  source    String? // Source of the access (e.g., "chat", "api", "integration")
  sessionId String? // Session identifier

  // Performance metrics
  responseTimeMs Int? // Response time in milliseconds

  // Relations
  user   User   @relation(fields: [userId], references: [id])
  userId String

  workspace   Workspace? @relation(fields: [workspaceId], references: [id])
  workspaceId String?

  conversation   Conversation? @relation(fields: [conversationId], references: [id])
  conversationId String?

  // Metadata for additional tracking data
  metadata Json? @default("{}")
}

model Space {
  id             String   @id @default(cuid())
  name           String
  description    String?
  autoMode       Boolean  @default(false)
  summary        String?
  themes         String[]
  statementCount Int?

  status String?

  icon String?

  lastPatternTrigger          DateTime?
  statementCountAtLastTrigger Int?

  // Relations
  workspace   Workspace @relation(fields: [workspaceId], references: [id])
  workspaceId String

  createdAt      DateTime         @default(now())
  updatedAt      DateTime         @updatedAt
  IngestionQueue IngestionQueue[]
  SpacePattern   SpacePattern[]
}

model SpacePattern {
  id        String    @id @default(cuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  name          String
  source        String
  type          String
  summary       String
  editedSummary String?
  evidence      String[]
  confidence    Float
  userConfirmed String   @default("pending")

  // Relations
  space   Space  @relation(fields: [spaceId], references: [id], onDelete: Cascade)
  spaceId String

  @@index([spaceId, source])
}

model User {
  id    String @id @default(cuid())
  email String @unique

  authenticationMethod      AuthenticationMethod
  authenticationProfile     Json?
  authenticationExtraParams Json?
  authIdentifier            String?              @unique

  displayName String?
  name        String?
  avatarUrl   String?

  memoryFilter String? // Adding memory filter instructions

  admin Boolean @default(false)

  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  marketingEmails       Boolean @default(true)
  confirmedBasicDetails Boolean @default(false)
  onboardingComplete    Boolean @default(false)

  referralSource String?

  metadata Json @default("{}")

  personalAccessTokens PersonalAccessToken[]
  InvitationCode       InvitationCode?        @relation(fields: [invitationCodeId], references: [id])
  invitationCodeId     String?
  Workspace            Workspace?
  IntegrationAccount   IntegrationAccount[]
  WebhookConfiguration WebhookConfiguration[]
  Conversation         Conversation[]
  ConversationHistory  ConversationHistory[]
  IngestionRule        IngestionRule[]

  // OAuth2 relations
  oauthAuthorizationCodes OAuthAuthorizationCode[]
  oauthAccessTokens       OAuthAccessToken[]
  oauthRefreshTokens      OAuthRefreshToken[]
  oauthClientsCreated     OAuthClient[]
  oauthIntegrationGrants  OAuthIntegrationGrant[]
  oAuthClientInstallation OAuthClientInstallation[]
  UserUsage               UserUsage?
  RecallLog               RecallLog[]
}

model UserUsage {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  availableCredits Int @default(0)
  usedCredits      Int @default(0)

  user   User   @relation(fields: [userId], references: [id])
  userId String @unique
}

model WebhookConfiguration {
  id          String     @id @default(cuid())
  url         String
  secret      String?
  isActive    Boolean    @default(true)
  eventTypes  String[] // List of event types this webhook is interested in, e.g. ["activity.created"]
  user        User?      @relation(fields: [userId], references: [id])
  userId      String?
  workspace   Workspace? @relation(fields: [workspaceId], references: [id])
  workspaceId String?
  createdAt   DateTime   @default(now())
  updatedAt   DateTime   @updatedAt

  WebhookDeliveryLog WebhookDeliveryLog[]
}

model WebhookDeliveryLog {
  id                     String               @id @default(cuid())
  webhookConfiguration   WebhookConfiguration @relation(fields: [webhookConfigurationId], references: [id])
  webhookConfigurationId String

  activity   Activity? @relation(fields: [activityId], references: [id])
  activityId String?

  status             WebhookDeliveryStatus
  responseStatusCode Int?
  responseBody       String?
  error              String?
  deliveredAt        DateTime              @default(now())

  createdAt DateTime @default(now())
}

model Workspace {
  id        String    @id @default(uuid())
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
  deleted   DateTime?

  name String
  slug String  @unique
  icon String?

  integrations String[]

  userId                  String?                   @unique
  user                    User?                     @relation(fields: [userId], references: [id])
  IngestionQueue          IngestionQueue[]
  IntegrationAccount      IntegrationAccount[]
  IntegrationDefinitionV2 IntegrationDefinitionV2[]
  Activity                Activity[]
  WebhookConfiguration    WebhookConfiguration[]
  Conversation            Conversation[]
  IngestionRule           IngestionRule[]
  OAuthClient             OAuthClient[]
  OAuthClientInstallation OAuthClientInstallation[]
  OAuthAuthorizationCode  OAuthAuthorizationCode[]
  OAuthAccessToken        OAuthAccessToken[]
  OAuthRefreshToken       OAuthRefreshToken[]
  RecallLog               RecallLog[]
  Space                   Space[]
  MCPSession              MCPSession[]
}

enum AuthenticationMethod {
  GOOGLE
  MAGIC_LINK
}

enum IngestionStatus {
  PENDING
  PROCESSING
  COMPLETED
  FAILED
  CANCELLED
}

enum UserType {
  Agent
  User
  System
}

enum WebhookDeliveryStatus {
  SUCCESS
  FAILED
}
