/**
 * Prisma JSON Field Types - Enterprise Grade
 * Strictly typed interfaces for all JSON fields in the database
 * Issues: #34, #130
 */

import type { Prisma } from '@prisma/client';

// ========================================
// Exercise Solution Types
// ========================================

export interface SolutionStep {
  step: number;
  explanation: string;
  latexFormula?: string;
  hint?: string;
}

export interface ExerciseHint {
  order: number;
  content: string;
  pointsPenalty: number;
}

export interface MultipleChoiceOption {
  id: string;
  content: string;
  isCorrect: boolean;
}

export interface ProofRequirement {
  description: string;
  maxPoints: number;
  requiredElements: string[];
}

export interface CalculationStep {
  step: number;
  formula: string;
  explanation: string;
  intermediateResult?: string;
}

// ========================================
// Module Types
// ========================================

export interface ModulePrerequisite {
  moduleId: string;
  requiredLevel: number;
}

export interface ModuleExample {
  id: string;
  title: string;
  description: string;
  latexContent?: string;
  difficulty: 'BASIC' | 'INTERMEDIATE' | 'ADVANCED';
}

export interface ModuleExerciseData {
  exerciseId: string;
  order: number;
  isRequired: boolean;
  weight: number;
}

// ========================================
// Topic Types
// ========================================

export interface TheoryContent {
  sections: {
    title: string;
    content: string;
    latexFormula?: string;
  }[];
  summary: string;
}

export interface Formula {
  name: string;
  latex: string;
  description: string;
  variables: { symbol: string; meaning: string }[];
}

export interface KeyPoint {
  id: string;
  content: string;
  importance: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
  relatedFormula?: string;
}

export interface CommonMistake {
  id: string;
  mistake: string;
  explanation: string;
  correctApproach: string;
  example?: string;
}

// ========================================
// Achievement Types
// ========================================

export interface AchievementMetadata {
  iconUrl?: string;
  animationUrl?: string;
  color?: string;
  unlockMessage?: string;
  bonusMultiplier?: number;
}

export interface UserAchievementMetadata {
  progressDetails?: Record<string, number>;
  unlockedAtSession?: string;
  firstAttemptDate?: string;
}

// ========================================
// Notification Types
// ========================================

export interface NotificationMetadata {
  actionUrl?: string;
  actionText?: string;
  relatedEntityId?: string;
  relatedEntityType?: string;
  customData?: Record<string, unknown>;
}

// ========================================
// PDF Processing Types
// ========================================

export interface ExtractedText {
  page: number;
  content: string;
  confidence: number;
  hasFormulas: boolean;
}

export interface DetectedExercise {
  id: string;
  page: number;
  text: string;
  type: 'MULTIPLE_CHOICE' | 'OPEN_RESPONSE' | 'CALCULATION' | 'PROOF';
  confidence: number;
  detectedFormulas: string[];
}

export interface ExtractedFormula {
  id: string;
  latex: string;
  page: number;
  confidence: number;
  context: string;
}

export interface PdfMetadata {
  title?: string;
  author?: string;
  subject?: string;
  keywords?: string[];
  creator?: string;
  producer?: string;
  creationDate?: string;
  modificationDate?: string;
}

// ========================================
// System Config Types
// ========================================

export interface ConfigChangeHistory {
  changes: {
    timestamp: string;
    changedBy: string;
    oldValue: string;
    newValue: string;
    reason?: string;
  }[];
}

// ========================================
// Prisma Helper Types
// ========================================

export type ExerciseWithTypedJson = Prisma.ExerciseGetPayload<{
  select: {
    id: true;
    solutionSteps: true;
    hints: true;
    multipleChoiceOptions: true;
    proofRequirements: true;
    calculationSteps: true;
    formulas: true;
  };
}> & {
  solutionSteps: SolutionStep[] | null;
  hints: ExerciseHint[] | null;
  multipleChoiceOptions: MultipleChoiceOption[] | null;
  proofRequirements: ProofRequirement[] | null;
  calculationSteps: CalculationStep[] | null;
  formulas: Formula[] | null;
};

export type ModuleWithTypedJson = Prisma.modulesGetPayload<{
  select: {
    id: true;
    examples: true;
    exercisesData: true;
  };
}> & {
  examples: ModuleExample[] | null;
  exercisesData: ModuleExerciseData[] | null;
};

export type TopicWithTypedJson = Prisma.topicsGetPayload<{
  select: {
    id: true;
    theoryContent: true;
    formulas: true;
    keyPoints: true;
    commonMistakes: true;
  };
}> & {
  theoryContent: TheoryContent | null;
  formulas: Formula[] | null;
  keyPoints: KeyPoint[] | null;
  commonMistakes: CommonMistake[] | null;
};

export type AchievementWithTypedJson = Prisma.AchievementGetPayload<{
  select: {
    id: true;
    metadata: true;
  };
}> & {
  metadata: AchievementMetadata | null;
};

export type UserAchievementWithTypedJson = Prisma.UserAchievementGetPayload<{
  select: {
    id: true;
    metadata: true;
  };
}> & {
  metadata: UserAchievementMetadata | null;
};

export type NotificationWithTypedJson = Prisma.NotificationGetPayload<{
  select: {
    id: true;
    metadata: true;
  };
}> & {
  metadata: NotificationMetadata | null;
};

export type ProcessedPdfWithTypedJson = Prisma.processed_pdfsGetPayload<{
  select: {
    id: true;
    extractedText: true;
    exercisesDetected: true;
    formulasExtracted: true;
    metadata: true;
  };
}> & {
  extractedText: ExtractedText[] | null;
  exercisesDetected: DetectedExercise[] | null;
  formulasExtracted: ExtractedFormula[] | null;
  metadata: PdfMetadata | null;
};

// SystemConfig JSON type (custom model not in Prisma client types)
export interface SystemConfigWithTypedJson {
  id: string;
  changeHistory: ConfigChangeHistory | null;
  createdAt: Date;
  updatedAt: Date;
}

// ========================================
// Validation Functions
// ========================================

export function validateSolutionSteps(steps: unknown): steps is SolutionStep[] {
  if (!Array.isArray(steps)) return false;
  return steps.every(
    (step) =>
      typeof step === 'object' &&
      step !== null &&
      typeof step.step === 'number' &&
      typeof step.explanation === 'string'
  );
}

export function validateExerciseHints(hints: unknown): hints is ExerciseHint[] {
  if (!Array.isArray(hints)) return false;
  return hints.every(
    (hint) =>
      typeof hint === 'object' &&
      hint !== null &&
      typeof hint.order === 'number' &&
      typeof hint.content === 'string' &&
      typeof hint.pointsPenalty === 'number'
  );
}

export function validateMultipleChoiceOptions(options: unknown): options is MultipleChoiceOption[] {
  if (!Array.isArray(options)) return false;
  return options.every(
    (option) =>
      typeof option === 'object' &&
      option !== null &&
      typeof option.id === 'string' &&
      typeof option.content === 'string' &&
      typeof option.isCorrect === 'boolean'
  );
}

export function validateFormulas(formulas: unknown): formulas is Formula[] {
  if (!Array.isArray(formulas)) return false;
  return formulas.every(
    (formula) =>
      typeof formula === 'object' &&
      formula !== null &&
      typeof formula.name === 'string' &&
      typeof formula.latex === 'string' &&
      typeof formula.description === 'string' &&
      Array.isArray(formula.variables)
  );
}
