using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using System.Text; using Serilog; using FinControl.Infrastructure.Persistence; using FinControl.Infrastructure.Repositories; using FinControl.Domain.Repositories; var builder = WebApplication.CreateBuilder(args); // Load .env file if it exists var envPath = Path.Combine(Directory.GetCurrentDirectory(), "..", "..", ".env"); if (File.Exists(envPath)) { var lines = File.ReadAllLines(envPath); foreach (var line in lines) { if (string.IsNullOrWhiteSpace(line) || line.StartsWith("#")) continue; var parts = line.Split('=', 2); if (parts.Length == 2) { Environment.SetEnvironmentVariable(parts[0].Trim(), parts[1].Trim()); } } Log.Information("✅ .env file loaded"); } // Configure Serilog Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Console() .WriteTo.File("logs/app-.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); builder.Host.UseSerilog(); // Add services builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); // CORS builder.Services.AddCors(options => { options.AddDefaultPolicy(builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); // Auth (simplified) // Database var useMySQL = builder.Configuration.GetValue("UseMySQL", true); var usePostgres = builder.Configuration.GetValue("UsePostgres", false); // Build connection string from .env or appsettings string? connectionString = null; // Try to get from .env environment variables var envHost = Environment.GetEnvironmentVariable("DB_HOST"); var envPort = Environment.GetEnvironmentVariable("DB_PORT") ?? "3306"; var envDatabase = Environment.GetEnvironmentVariable("DB_DATABASE"); var envUsername = Environment.GetEnvironmentVariable("DB_USERNAME"); var envPassword = Environment.GetEnvironmentVariable("DB_PASSWORD"); if (!string.IsNullOrEmpty(envHost)) { connectionString = $"server={envHost};port={envPort};database={envDatabase};uid={envUsername};pwd={envPassword};charset=utf8mb4;Pooling=true;Maximum Pool Size=100;"; Log.Information("🔗 Connection string loaded from .env file"); } else { connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); Log.Information("🔗 Connection string loaded from appsettings.json"); } builder.Services.AddDbContext(options => { if (!string.IsNullOrEmpty(connectionString)) { options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); Log.Information("📊 MySQL Database configured: {Host}/{Database}", envHost ?? "appsettings", envDatabase ?? "eune6179_financeiro"); } else { throw new InvalidOperationException("No database connection string found in .env or appsettings.json"); } }); // Repositories builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); var app = builder.Build(); // Seed data using (var scope = app.Services.CreateScope()) { var context = scope.ServiceProvider.GetRequiredService(); SeedData(context); } // Configure pipeline if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseCors(); app.UseHttpsRedirection(); app.MapControllers(); app.Run(); static void SeedData(FinControlContext context) { // Seed initial data if (!context.Users.Any()) { var userId = Guid.NewGuid(); var user = new FinControl.Domain.Entities.User { Id = userId, Name = "João Silva", Email = "joao@example.com", PasswordHash = BCrypt.Net.BCrypt.HashPassword("senha123"), CreatedAt = DateTime.UtcNow }; context.Users.Add(user); // Add sample categories var salaryCategory = new FinControl.Domain.Entities.Category { Id = Guid.NewGuid(), UserId = userId, Name = "Salário", Type = FinControl.Domain.Enums.CategoryType.Income }; var foodCategory = new FinControl.Domain.Entities.Category { Id = Guid.NewGuid(), UserId = userId, Name = "Alimentação", Type = FinControl.Domain.Enums.CategoryType.Expense }; context.Categories.AddRange(salaryCategory, foodCategory); // Add sample account var account = new FinControl.Domain.Entities.Account { Id = Guid.NewGuid(), UserId = userId, Name = "Conta Corrente", Type = FinControl.Domain.Enums.AccountType.CheckingAccount, InitialBalance = 5000, CurrentBalance = 5000, Institution = "Banco do Brasil" }; context.Accounts.Add(account); // Add sample transactions var transaction1 = new FinControl.Domain.Entities.Transaction { Id = Guid.NewGuid(), AccountId = account.Id, CategoryId = salaryCategory.Id, Amount = 5000, Type = FinControl.Domain.Enums.TransactionType.Income, Description = "Salário mensal", Date = DateTime.UtcNow.AddDays(-10) }; var transaction2 = new FinControl.Domain.Entities.Transaction { Id = Guid.NewGuid(), AccountId = account.Id, CategoryId = foodCategory.Id, Amount = 300, Type = FinControl.Domain.Enums.TransactionType.Expense, Description = "Compras no supermercado", Date = DateTime.UtcNow.AddDays(-5) }; context.Transactions.AddRange(transaction1, transaction2); // Add sample goal var goal = new FinControl.Domain.Entities.Goal { Id = Guid.NewGuid(), UserId = userId, Name = "Fundo de Emergência", Description = "Poupar 3 meses de gastos", TargetAmount = 15000, CurrentAmount = 2000, TargetDate = DateTime.UtcNow.AddMonths(12) }; context.Goals.Add(goal); context.SaveChanges(); } }