// Redirect Intelligence v2 - Database Schema
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
  output   = "../../../node_modules/.prisma/client"
}

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

model User {
  id            String   @id @default(cuid())
  email         String   @unique
  name          String
  passwordHash  String   @map("password_hash")
  createdAt     DateTime @default(now()) @map("created_at")
  lastLoginAt   DateTime? @map("last_login_at")
  
  memberships   OrgMembership[]
  auditLogs     AuditLog[]
  bulkJobs      BulkJob[]
  
  @@map("users")
}

model Organization {
  id        String   @id @default(cuid())
  name      String
  plan      String   @default("free")
  createdAt DateTime @default(now()) @map("created_at")
  
  memberships OrgMembership[]
  projects    Project[]
  apiKeys     ApiKey[]
  auditLogs   AuditLog[]
  bulkJobs    BulkJob[]
  
  @@map("organizations")
}

model OrgMembership {
  id     String @id @default(cuid())
  orgId  String @map("org_id")
  userId String @map("user_id")
  role   Role
  
  organization Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  user         User         @relation(fields: [userId], references: [id], onDelete: Cascade)
  
  @@unique([orgId, userId])
  @@map("org_memberships")
}

model Project {
  id           String   @id @default(cuid())
  orgId        String   @map("org_id")
  name         String
  settingsJson Json     @map("settings_json") @default("{}")
  createdAt    DateTime @default(now()) @map("created_at")
  
  organization Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  checks       Check[]
  bulkJobs     BulkJob[]
  
  @@map("projects")
}

model Check {
  id          String      @id @default(cuid())
  projectId   String      @map("project_id")
  inputUrl    String      @map("input_url")
  method      String      @default("GET")
  headersJson Json        @map("headers_json") @default("{}")
  userAgent   String?     @map("user_agent")
  startedAt   DateTime    @map("started_at")
  finishedAt  DateTime?   @map("finished_at")
  status      CheckStatus
  finalUrl    String?     @map("final_url")
  totalTimeMs Int?        @map("total_time_ms")
  reportId    String?     @map("report_id")
  
  project          Project            @relation(fields: [projectId], references: [id], onDelete: Cascade)
  hops             Hop[]
  sslInspections   SslInspection[]
  seoFlags         SeoFlags?
  securityFlags    SecurityFlags?
  reports          Report[]
  
  @@index([projectId, startedAt(sort: Desc)])
  @@map("checks")
}

model Hop {
  id           String       @id @default(cuid())
  checkId      String       @map("check_id")
  hopIndex     Int          @map("hop_index")
  url          String
  scheme       String?
  statusCode   Int?         @map("status_code")
  redirectType RedirectType @map("redirect_type")
  latencyMs    Int?         @map("latency_ms")
  contentType  String?      @map("content_type")
  reason       String?
  responseHeadersJson Json  @map("response_headers_json") @default("{}")
  
  check Check @relation(fields: [checkId], references: [id], onDelete: Cascade)
  
  @@index([checkId, hopIndex])
  @@map("hops")
}

model SslInspection {
  id            String    @id @default(cuid())
  checkId       String    @map("check_id")
  host          String
  validFrom     DateTime? @map("valid_from")
  validTo       DateTime? @map("valid_to")
  daysToExpiry  Int?      @map("days_to_expiry")
  issuer        String?
  protocol      String?
  warningsJson  Json      @map("warnings_json") @default("[]")
  
  check Check @relation(fields: [checkId], references: [id], onDelete: Cascade)
  
  @@map("ssl_inspections")
}

model SeoFlags {
  id                String  @id @default(cuid())
  checkId           String  @unique @map("check_id")
  robotsTxtStatus   String? @map("robots_txt_status")
  robotsTxtRulesJson Json   @map("robots_txt_rules_json") @default("{}")
  metaRobots        String? @map("meta_robots")
  canonicalUrl      String? @map("canonical_url")
  sitemapPresent    Boolean @default(false) @map("sitemap_present")
  noindex           Boolean @default(false)
  nofollow          Boolean @default(false)
  
  check Check @relation(fields: [checkId], references: [id], onDelete: Cascade)
  
  @@map("seo_flags")
}

model SecurityFlags {
  id              String       @id @default(cuid())
  checkId         String       @unique @map("check_id")
  safeBrowsingStatus String?   @map("safe_browsing_status")
  mixedContent    MixedContent @map("mixed_content") @default(NONE)
  httpsToHttp     Boolean      @map("https_to_http") @default(false)
  
  check Check @relation(fields: [checkId], references: [id], onDelete: Cascade)
  
  @@map("security_flags")
}

model Report {
  id           String   @id @default(cuid())
  checkId      String   @map("check_id")
  markdownPath String?  @map("markdown_path")
  pdfPath      String?  @map("pdf_path")
  createdAt    DateTime @default(now()) @map("created_at")
  
  check Check @relation(fields: [checkId], references: [id], onDelete: Cascade)
  
  @@map("reports")
}

model BulkJob {
  id           String    @id @default(cuid())
  projectId    String    @map("project_id")
  uploadPath   String    @map("upload_path")
  status       JobStatus
  progressJson Json      @map("progress_json") @default("{}")
  createdAt    DateTime  @default(now()) @map("created_at")
  completedAt  DateTime? @map("completed_at")
  
  project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
  
  @@map("bulk_jobs")
}

model ApiKey {
  id             String   @id @default(cuid())
  orgId          String   @map("org_id")
  name           String
  tokenHash      String   @unique @map("token_hash")
  permsJson      Json     @map("perms_json") @default("{}")
  rateLimitQuota Int      @map("rate_limit_quota") @default(1000)
  createdAt      DateTime @default(now()) @map("created_at")
  
  organization Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  
  @@index([tokenHash])
  @@map("api_keys")
}

model AuditLog {
  id           String   @id @default(cuid())
  orgId        String   @map("org_id")
  actorUserId  String?  @map("actor_user_id")
  action       String
  entity       String
  entityId     String   @map("entity_id")
  metaJson     Json     @map("meta_json") @default("{}")
  createdAt    DateTime @default(now()) @map("created_at")
  
  organization Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
  actor        User?        @relation(fields: [actorUserId], references: [id], onDelete: SetNull)
  
  @@map("audit_logs")
}

model BulkJob {
  id             String    @id
  userId         String
  organizationId String?
  projectId      String?
  status         String    // 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled'
  totalUrls      Int
  processedUrls  Int       @default(0)
  successfulUrls Int       @default(0)
  failedUrls     Int       @default(0)
  configJson     Json      // Job configuration (options)
  urlsJson       Json      // Array of URLs to process
  resultsJson    Json?     // Array of results
  createdAt      DateTime  @default(now())
  startedAt      DateTime?
  finishedAt     DateTime?
  
  user         User          @relation(fields: [userId], references: [id], onDelete: Cascade)
  organization Organization? @relation(fields: [organizationId], references: [id], onDelete: SetNull)
  project      Project?      @relation(fields: [projectId], references: [id], onDelete: SetNull)
  
  @@index([userId, createdAt])
  @@index([status, createdAt])
  @@map("bulk_jobs")
}

enum Role {
  OWNER
  ADMIN
  MEMBER
}

enum CheckStatus {
  OK
  ERROR
  TIMEOUT
  LOOP
}

enum RedirectType {
  HTTP_301
  HTTP_302
  HTTP_307
  HTTP_308
  META_REFRESH
  JS
  FINAL
  OTHER
}

enum MixedContent {
  NONE
  PRESENT
  FINAL_TO_HTTP
}

enum JobStatus {
  QUEUED
  RUNNING
  DONE
  ERROR
}
