using System; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore; namespace D3ROVoice.Api.Data; public class User { [Key] public int Id { get; set; } [Required] [MaxLength(150)] public string Email { get; set; } = string.Empty; [Required] public string PasswordHash { get; set; } = string.Empty; [Required] [MaxLength(50)] public string Role { get; set; } = "User"; // "Admin" or "User" public bool IsActive { get; set; } = true; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? LastLoginAt { get; set; } } public class ServiceModelEndpoint { [Key] public int Id { get; set; } [Required] [MaxLength(100)] public string ModelId { get; set; } = string.Empty; [Required] [MaxLength(150)] public string ModelName { get; set; } = string.Empty; [Required] [MaxLength(50)] public string Provider { get; set; } = "OpenAI"; // OpenAI, Anthropic, Custom [Required] [MaxLength(500)] public string EndpointUrl { get; set; } = string.Empty; [MaxLength(500)] public string ApiKey { get; set; } = string.Empty; [Column(TypeName = "decimal(18, 6)")] public decimal CostPer1kPromptTokens { get; set; } = 0.00015m; [Column(TypeName = "decimal(18, 6)")] public decimal CostPer1kCompletionTokens { get; set; } = 0.00060m; public bool IsActive { get; set; } = true; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } public class ApiUsageLog { [Key] public int Id { get; set; } public int UserId { get; set; } [MaxLength(150)] public string UserEmail { get; set; } = string.Empty; public int ModelEndpointId { get; set; } [MaxLength(100)] public string ModelId { get; set; } = string.Empty; public int PromptTokens { get; set; } public int CompletionTokens { get; set; } public int TotalTokens { get; set; } [Column(TypeName = "decimal(18, 6)")] public decimal CalculatedCost { get; set; } public int RequestDurationMs { get; set; } public int StatusCode { get; set; } = 200; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } public class ServerErrorLog { [Key] public int Id { get; set; } [Required] [MaxLength(100)] public string ErrorType { get; set; } = string.Empty; [Required] public string Message { get; set; } = string.Empty; public string? StackTrace { get; set; } [MaxLength(250)] public string? Endpoint { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } public class SttProviderEndpoint { [Key] public int Id { get; set; } [Required] [MaxLength(150)] public string Name { get; set; } = string.Empty; [Required] [MaxLength(50)] public string ProviderType { get; set; } = "groq"; // groq, openai, deepgram, google, assemblyai, azure, custom, local-sidecar [Required] [MaxLength(500)] public string EndpointUrl { get; set; } = string.Empty; [MaxLength(500)] public string ApiKey { get; set; } = string.Empty; [Required] [MaxLength(100)] public string ModelId { get; set; } = "whisper-large-v3-turbo"; [Required] [MaxLength(50)] public string Method { get; set; } = "multipart"; // multipart, binary-stream, json-base64, custom-rest [MaxLength(20)] public string Language { get; set; } = "ko"; [MaxLength(1000)] public string? Prompt { get; set; } public double Temperature { get; set; } = 0.0; [Column(TypeName = "decimal(18, 6)")] public decimal CostPerMinute { get; set; } = 0.000500m; [Column(TypeName = "decimal(18, 6)")] public decimal CostPerSecond { get; set; } = 0.000008m; public bool IsDefault { get; set; } = false; public bool IsActive { get; set; } = true; public int FallbackPriority { get; set; } = 1; [MaxLength(1000)] public string? ExtraHeadersJson { get; set; } public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } } public class SttUsageLog { [Key] public int Id { get; set; } public int UserId { get; set; } [MaxLength(150)] public string UserEmail { get; set; } = string.Empty; public int EndpointId { get; set; } [MaxLength(50)] public string Provider { get; set; } = string.Empty; [MaxLength(100)] public string ModelId { get; set; } = string.Empty; public double AudioDurationSeconds { get; set; } [Column(TypeName = "decimal(18, 6)")] public decimal CalculatedCost { get; set; } public int LatencyMs { get; set; } public int StatusCode { get; set; } = 200; [MaxLength(1000)] public string TranscriptPreview { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; } public class AppDbContext : DbContext { public AppDbContext(DbContextOptions options) : base(options) { } public DbSet Users => Set(); public DbSet ModelEndpoints => Set(); public DbSet UsageLogs => Set(); public DbSet ErrorLogs => Set(); public DbSet SttProviderEndpoints => Set(); public DbSet SttUsageLogs => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity() .HasIndex(u => u.Email) .IsUnique(); modelBuilder.Entity() .HasIndex(m => m.ModelId) .IsUnique(); modelBuilder.Entity() .HasIndex(s => s.Name); modelBuilder.Entity() .HasIndex(s => s.IsDefault); } }