generator client {
  provider = "prisma-client-js"
}

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

enum PriorityLevel {
  LOW
  MEDIUM
  HIGH
}

enum UserRole {
  USER
  ADMIN
}

enum ContentPageType {
  FAQ
  MANUAL
}

enum OverallScoreMethod {
  EQUAL_ALL_MODULES
  EQUAL_ANSWERED_MODULES
  WEIGHTED_ANSWERED_MODULES
}

enum OrganizationDocumentType {
  ACTA_CONSTITUTIVA
}

enum StrategicDiagnosticEvidenceSection {
  TECHNICAL
  EXPERIENCE
  ORGANIZATION
  PUBLIC_PROCUREMENT
}

enum WorkshopProgressStatus {
  NOT_STARTED
  WATCHED
  EVIDENCE_SUBMITTED
  APPROVED
  REJECTED
  SKIPPED
}

enum WorkshopEvidenceValidationStatus {
  PENDING
  APPROVED
  REJECTED
  ERROR
}

enum LicitationSource {
  MUNICIPAL_OPEN_PORTAL
  PNT
  MUNICIPAL_BACKUP
}

enum LicitationProcedureType {
  LICITACION_PUBLICA
  INVITACION_RESTRINGIDA
  ADJUDICACION_DIRECTA
  UNKNOWN
}

enum LicitationCategory {
  GOODS
  SERVICES
  WORKS
  MIXED
  UNKNOWN
}

enum SyncRunStatus {
  SUCCESS
  PARTIAL
  FAILED
}

enum MunicipalOpenPortalType {
  GENERIC
  SAN_PEDRO_ASPX
}

model User {
  id                              String                                @id @default(cuid())
  email                           String                                @unique
  passwordHash                    String
  name                            String?
  role                            UserRole                              @default(USER)
  emailVerifiedAt                 DateTime?
  createdAt                       DateTime                              @default(now())
  updatedAt                       DateTime                              @updatedAt
  organization                    Organization?
  companyProfile                  CompanyProfile?
  organizationDocs                OrganizationDocument[]
  strategicDiagnosticEvidenceDocs StrategicDiagnosticEvidenceDocument[]
  workshopProgresses              DevelopmentWorkshopProgress[]
  workshopEvidenceDocs            DevelopmentWorkshopEvidence[]
  verificationTokens              EmailVerificationToken[]
  responses                       Response[]
  results                         AssessmentResult[]
}

model Organization {
  id                              String                                @id @default(cuid())
  userId                          String                                @unique
  name                            String
  tradeName                       String?
  rfc                             String?
  legalRepresentative             String?
  incorporationDate               String?
  deedNumber                      String?
  notaryName                      String?
  stateOfIncorporation            String?
  companyType                     String?
  fiscalAddress                   String?
  businessPurpose                 String?
  industry                        String?
  operatingState                  String?
  municipality                    String?
  companySize                     String?
  yearsOfOperation                String?
  annualRevenueRange              String?
  hasGovernmentContracts          Boolean?
  country                         String?
  primaryObjective                String?
  actaExtractedData               Json?
  actaLookupDictionary            Json?
  actaUploadedAt                  DateTime?
  onboardingCompletedAt           DateTime?
  strategicDiagnosticData         Json?
  strategicDiagnosticScores       Json?
  strategicDiagnosticCompletedAt  DateTime?
  companyProfile                  CompanyProfile?
  createdAt                       DateTime                              @default(now())
  updatedAt                       DateTime                              @updatedAt
  user                            User                                  @relation(fields: [userId], references: [id], onDelete: Cascade)
  documents                       OrganizationDocument[]
  strategicDiagnosticEvidenceDocs StrategicDiagnosticEvidenceDocument[]
}

model OrganizationDocument {
  id                   String                   @id @default(cuid())
  organizationId       String
  userId               String
  type                 OrganizationDocumentType
  fileName             String
  storedFileName       String
  filePath             String
  mimeType             String
  sizeBytes            Int
  checksumSha256       String?
  extractedData        Json?
  extractedTextSnippet String?
  createdAt            DateTime                 @default(now())
  updatedAt            DateTime                 @updatedAt
  organization         Organization             @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  user                 User                     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([organizationId, type])
  @@unique([userId, type])
  @@index([type])
}

model StrategicDiagnosticEvidenceDocument {
  id             String                             @id @default(cuid())
  organizationId String
  userId         String
  section        StrategicDiagnosticEvidenceSection
  category       String
  fileName       String
  storedFileName String
  filePath       String
  mimeType       String
  sizeBytes      Int
  checksumSha256 String?
  createdAt      DateTime                           @default(now())
  updatedAt      DateTime                           @updatedAt
  organization   Organization                       @relation(fields: [organizationId], references: [id], onDelete: Cascade)
  user           User                               @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([organizationId, section])
  @@index([userId, section])
  @@index([createdAt])
}

model DiagnosticModule {
  id              String             @id @default(cuid())
  key             String             @unique
  name            String
  description     String?
  sortOrder       Int                @default(0)
  createdAt       DateTime           @default(now())
  updatedAt       DateTime           @updatedAt
  questions       Question[]
  results         AssessmentResult[]
  recommendations Recommendation[]
  workshops       DevelopmentWorkshop[]
}

model DevelopmentWorkshop {
  id                String                        @id @default(cuid())
  key               String                        @unique
  moduleId          String
  title             String
  summary           String
  videoUrl          String
  durationMinutes   Int                           @default(0)
  evidenceRequired  String
  learningObjectives Json?
  sortOrder         Int                           @default(0)
  isActive          Boolean                       @default(true)
  createdAt         DateTime                      @default(now())
  updatedAt         DateTime                      @updatedAt
  module            DiagnosticModule              @relation(fields: [moduleId], references: [id], onDelete: Cascade)
  progresses        DevelopmentWorkshopProgress[]
  evidences         DevelopmentWorkshopEvidence[]

  @@index([moduleId, sortOrder])
  @@index([isActive, sortOrder])
}

model DevelopmentWorkshopProgress {
  id          String               @id @default(cuid())
  workshopId  String
  userId      String
  status      WorkshopProgressStatus @default(NOT_STARTED)
  watchedAt   DateTime?
  skippedAt   DateTime?
  completedAt DateTime?
  createdAt   DateTime             @default(now())
  updatedAt   DateTime             @updatedAt
  workshop    DevelopmentWorkshop  @relation(fields: [workshopId], references: [id], onDelete: Cascade)
  user        User                 @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([workshopId, userId])
  @@index([userId, status])
  @@index([workshopId, status])
}

model DevelopmentWorkshopEvidence {
  id                   String                           @id @default(cuid())
  workshopId           String
  userId               String
  validationStatus     WorkshopEvidenceValidationStatus @default(PENDING)
  validationReason     String?
  validationConfidence Float?
  validatedAt          DateTime?
  fileName             String
  storedFileName       String
  filePath             String
  mimeType             String
  sizeBytes            Int
  checksumSha256       String?
  createdAt            DateTime                         @default(now())
  updatedAt            DateTime                         @updatedAt
  workshop             DevelopmentWorkshop              @relation(fields: [workshopId], references: [id], onDelete: Cascade)
  user                 User                             @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId, workshopId, createdAt])
  @@index([workshopId, validationStatus])
}

model Question {
  id            String           @id @default(cuid())
  key           String           @unique
  moduleId      String
  prompt        String
  helpText      String?
  sortOrder     Int              @default(0)
  createdAt     DateTime         @default(now())
  updatedAt     DateTime         @updatedAt
  module        DiagnosticModule @relation(fields: [moduleId], references: [id], onDelete: Cascade)
  answerOptions AnswerOption[]
  responses     Response[]

  @@index([moduleId, sortOrder])
}

model AnswerOption {
  id         String     @id @default(cuid())
  key        String     @unique
  questionId String
  label      String
  weight     Int
  sortOrder  Int        @default(0)
  createdAt  DateTime   @default(now())
  updatedAt  DateTime   @updatedAt
  question   Question   @relation(fields: [questionId], references: [id], onDelete: Cascade)
  responses  Response[]

  @@index([questionId, sortOrder])
}

model Response {
  id             String       @id @default(cuid())
  userId         String
  questionId     String
  answerOptionId String
  evidence       Json?
  createdAt      DateTime     @default(now())
  updatedAt      DateTime     @updatedAt
  user           User         @relation(fields: [userId], references: [id], onDelete: Cascade)
  question       Question     @relation(fields: [questionId], references: [id], onDelete: Cascade)
  answerOption   AnswerOption @relation(fields: [answerOptionId], references: [id], onDelete: Cascade)

  @@unique([userId, questionId])
  @@index([userId])
}

model AssessmentResult {
  id           String            @id @default(cuid())
  userId       String
  moduleId     String?
  overallScore Float?
  moduleScore  Float?
  metadata     Json?
  calculatedAt DateTime          @default(now())
  createdAt    DateTime          @default(now())
  updatedAt    DateTime          @updatedAt
  user         User              @relation(fields: [userId], references: [id], onDelete: Cascade)
  module       DiagnosticModule? @relation(fields: [moduleId], references: [id], onDelete: SetNull)

  @@index([userId, calculatedAt])
  @@index([moduleId])
}

model Recommendation {
  id          String            @id @default(cuid())
  key         String            @unique
  moduleId    String?
  title       String
  description String
  priority    PriorityLevel     @default(MEDIUM)
  isTemplate  Boolean           @default(true)
  createdAt   DateTime          @default(now())
  updatedAt   DateTime          @updatedAt
  module      DiagnosticModule? @relation(fields: [moduleId], references: [id], onDelete: SetNull)

  @@index([moduleId])
}

model ContentPage {
  id          String          @id @default(cuid())
  type        ContentPageType
  slug        String          @unique
  title       String
  content     String
  sortOrder   Int             @default(0)
  isPublished Boolean         @default(true)
  createdAt   DateTime        @default(now())
  updatedAt   DateTime        @updatedAt

  @@index([type, sortOrder])
}

model ScoringConfig {
  id                 String             @id @default(cuid())
  key                String             @unique
  lowScoreThreshold  Int                @default(70)
  overallScoreMethod OverallScoreMethod @default(EQUAL_ALL_MODULES)
  moduleWeights      Json?
  createdAt          DateTime           @default(now())
  updatedAt          DateTime           @updatedAt
}

model EmailVerificationToken {
  id         String    @id @default(cuid())
  userId     String
  token      String    @unique
  expiresAt  DateTime
  consumedAt DateTime?
  createdAt  DateTime  @default(now())
  user       User      @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId])
  @@index([expiresAt])
}

model Municipality {
  id                   String                  @id @default(cuid())
  stateCode            String
  stateName            String
  municipalityCode     String
  municipalityName     String
  openPortalUrl        String?
  openPortalType       MunicipalOpenPortalType @default(GENERIC)
  openSyncIntervalDays Int                     @default(7)
  lastOpenSyncAt       DateTime?
  pntSubjectId         String?
  pntEntityId          String?
  pntSectorId          String?
  pntEntryUrl          String?
  backupUrl            String?
  scrapingEnabled      Boolean                 @default(true)
  isActive             Boolean                 @default(true)
  createdAt            DateTime                @default(now())
  updatedAt            DateTime                @updatedAt
  licitations          Licitation[]
  syncRuns             SyncRun[]

  @@unique([stateCode, municipalityCode])
  @@index([stateCode, municipalityName])
  @@index([isActive, scrapingEnabled])
}

model Licitation {
  id              String                  @id @default(cuid())
  municipalityId  String
  source          LicitationSource
  sourceRecordId  String
  tenderCode      String?
  procedureType   LicitationProcedureType @default(UNKNOWN)
  title           String
  description     String?
  category        LicitationCategory?     @default(UNKNOWN)
  isOpen          Boolean                 @default(true)
  openingDate     DateTime?
  closingDate     DateTime?
  publishDate     DateTime?
  eventDates      Json?
  amount          Decimal?                @db.Decimal(14, 2)
  currency        String?
  status          String?
  supplierAwarded String?
  documents       Json?
  rawSourceUrl    String?
  rawPayload      Json
  lastSeenAt      DateTime                @default(now())
  createdAt       DateTime                @default(now())
  updatedAt       DateTime                @updatedAt
  municipality    Municipality            @relation(fields: [municipalityId], references: [id], onDelete: Cascade)

  @@unique([municipalityId, source, sourceRecordId])
  @@index([municipalityId, isOpen, closingDate])
  @@index([municipalityId, publishDate])
  @@index([procedureType, category])
  @@index([amount])
  @@index([createdAt])
}

model SyncRun {
  id             String           @id @default(cuid())
  startedAt      DateTime         @default(now())
  finishedAt     DateTime?
  municipalityId String?
  source         LicitationSource
  status         SyncRunStatus    @default(SUCCESS)
  stats          Json?
  error          String?
  municipality   Municipality?    @relation(fields: [municipalityId], references: [id], onDelete: SetNull)

  @@index([municipalityId, startedAt])
  @@index([source, status, startedAt])
}

model CompanyProfile {
  id                  String        @id @default(cuid())
  userId              String        @unique
  organizationId      String?       @unique
  locations           Json?
  categoriesSupported Json?
  keywords            Json?
  minAmount           Decimal?      @db.Decimal(14, 2)
  maxAmount           Decimal?      @db.Decimal(14, 2)
  createdAt           DateTime      @default(now())
  updatedAt           DateTime      @updatedAt
  user                User          @relation(fields: [userId], references: [id], onDelete: Cascade)
  organization        Organization? @relation(fields: [organizationId], references: [id], onDelete: SetNull)
}
