using System.Security.Cryptography; using System.Text; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using WorkClub.Domain.Entities; using WorkClub.Domain.Enums; using WorkClub.Infrastructure.Data; namespace WorkClub.Infrastructure.Seed; public class SeedDataService { private readonly IServiceScopeFactory _serviceScopeFactory; public SeedDataService(IServiceScopeFactory serviceScopeFactory) { _serviceScopeFactory = serviceScopeFactory; } public async Task SeedAsync() { using var scope = _serviceScopeFactory.CreateScope(); var context = scope.ServiceProvider.GetRequiredService(); // Seed clubs if (!context.Clubs.Any()) { var clubs = new List { new Club { Id = Guid.NewGuid(), TenantId = GenerateDeterministicGuid("Sunrise Tennis Club"), Name = "Sunrise Tennis Club", SportType = SportType.Tennis, Description = "Community tennis club for all skill levels", CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new Club { Id = Guid.NewGuid(), TenantId = GenerateDeterministicGuid("Valley Cycling Club"), Name = "Valley Cycling Club", SportType = SportType.Cycling, Description = "Cycling enthusiasts community", CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow } }; context.Clubs.AddRange(clubs); await context.SaveChangesAsync(); } // Get clubs for member seeding var tennisClub = context.Clubs.First(c => c.Name == "Sunrise Tennis Club"); var cyclingClub = context.Clubs.First(c => c.Name == "Valley Cycling Club"); // Seed members if (!context.Members.Any()) { var members = new List { // admin@test.com: Admin in Club 1, Member in Club 2 new Member { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ExternalUserId = "admin-user-id", DisplayName = "Admin User", Email = "admin@test.com", Role = ClubRole.Admin, ClubId = tennisClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new Member { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, ExternalUserId = "admin-user-id", DisplayName = "Admin User", Email = "admin@test.com", Role = ClubRole.Member, ClubId = cyclingClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, // manager@test.com: Manager in Club 1 new Member { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ExternalUserId = "manager-user-id", DisplayName = "Manager User", Email = "manager@test.com", Role = ClubRole.Manager, ClubId = tennisClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, // member1@test.com: Member in Club 1 and Club 2 new Member { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ExternalUserId = "member1-user-id", DisplayName = "Member One", Email = "member1@test.com", Role = ClubRole.Member, ClubId = tennisClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new Member { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, ExternalUserId = "member1-user-id", DisplayName = "Member One", Email = "member1@test.com", Role = ClubRole.Member, ClubId = cyclingClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, // member2@test.com: Member in Club 1 new Member { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ExternalUserId = "member2-user-id", DisplayName = "Member Two", Email = "member2@test.com", Role = ClubRole.Member, ClubId = tennisClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, // viewer@test.com: Viewer in Club 1 new Member { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ExternalUserId = "viewer-user-id", DisplayName = "Viewer User", Email = "viewer@test.com", Role = ClubRole.Viewer, ClubId = tennisClub.Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow } }; context.Members.AddRange(members); await context.SaveChangesAsync(); } // Get admin member IDs for work item creation var adminMembers = context.Members.Where(m => m.Email == "admin@test.com").ToList(); var managerMember = context.Members.First(m => m.Email == "manager@test.com"); var member1Members = context.Members.Where(m => m.Email == "member1@test.com").ToList(); var member2Member = context.Members.First(m => m.Email == "member2@test.com"); // Seed work items if (!context.WorkItems.Any()) { var workItems = new List { // Club 1 - Tennis Club (5 items, all states) new WorkItem { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Court renovation", Description = "Resurface main court", Status = WorkItemStatus.Open, AssigneeId = null, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, ClubId = tennisClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(14), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new WorkItem { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Equipment order", Description = "Purchase new tennis rackets and balls", Status = WorkItemStatus.Assigned, AssigneeId = managerMember.Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, ClubId = tennisClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(7), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new WorkItem { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Tournament planning", Description = "Organize annual summer tournament", Status = WorkItemStatus.InProgress, AssigneeId = member1Members.First(m => m.ClubId == tennisClub.Id).Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, ClubId = tennisClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(30), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new WorkItem { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Member handbook review", Description = "Update and review club rules handbook", Status = WorkItemStatus.Review, AssigneeId = member2Member.Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, ClubId = tennisClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(21), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new WorkItem { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Website update", Description = "Update club website with new photos", Status = WorkItemStatus.Done, AssigneeId = managerMember.Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, ClubId = tennisClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(-5), CreatedAt = DateTimeOffset.UtcNow.AddDays(-10), UpdatedAt = DateTimeOffset.UtcNow }, // Club 2 - Cycling Club (3 items) new WorkItem { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, Title = "Route mapping", Description = "Create new cycling routes for summer", Status = WorkItemStatus.Open, AssigneeId = null, CreatedById = adminMembers.First(m => m.ClubId == cyclingClub.Id).Id, ClubId = cyclingClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(21), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new WorkItem { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, Title = "Safety training", Description = "Organize safety and maintenance training", Status = WorkItemStatus.Assigned, AssigneeId = member1Members.First(m => m.ClubId == cyclingClub.Id).Id, CreatedById = adminMembers.First(m => m.ClubId == cyclingClub.Id).Id, ClubId = cyclingClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(14), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new WorkItem { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, Title = "Group ride coordination", Description = "Schedule and coordinate weekly group rides", Status = WorkItemStatus.InProgress, AssigneeId = adminMembers.First(m => m.ClubId == cyclingClub.Id).Id, CreatedById = adminMembers.First(m => m.ClubId == cyclingClub.Id).Id, ClubId = cyclingClub.Id, DueDate = DateTimeOffset.UtcNow.AddDays(7), CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow } }; context.WorkItems.AddRange(workItems); await context.SaveChangesAsync(); } // Seed shifts if (!context.Shifts.Any()) { var now = DateTimeOffset.UtcNow; var shifts = new List { // Club 1 - Tennis Club (3 shifts) new Shift { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Court Maintenance - Yesterday", Description = "Daily court cleaning and maintenance", Location = "Main Court", StartTime = now.AddDays(-1).Date.ToLocalTime().AddHours(8), EndTime = now.AddDays(-1).Date.ToLocalTime().AddHours(12), Capacity = 2, ClubId = tennisClub.Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new Shift { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Court Maintenance - Today", Description = "Daily court cleaning and maintenance", Location = "Main Court", StartTime = now.Date.ToLocalTime().AddHours(14), EndTime = now.Date.ToLocalTime().AddHours(18), Capacity = 3, ClubId = tennisClub.Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new Shift { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, Title = "Tournament Setup - Next Week", Description = "Setup and preparation for summer tournament", Location = "All Courts", StartTime = now.AddDays(7).Date.ToLocalTime().AddHours(9), EndTime = now.AddDays(7).Date.ToLocalTime().AddHours(17), Capacity = 5, ClubId = tennisClub.Id, CreatedById = adminMembers.First(m => m.ClubId == tennisClub.Id).Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, // Club 2 - Cycling Club (2 shifts) new Shift { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, Title = "Group Ride - Today", Description = "Weekly morning group ride", Location = "Park entrance", StartTime = now.Date.ToLocalTime().AddHours(7), EndTime = now.Date.ToLocalTime().AddHours(9), Capacity = 10, ClubId = cyclingClub.Id, CreatedById = adminMembers.First(m => m.ClubId == cyclingClub.Id).Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }, new Shift { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, Title = "Maintenance Workshop - Next Week", Description = "Bike maintenance and repair workshop", Location = "Club shed", StartTime = now.AddDays(7).Date.ToLocalTime().AddHours(10), EndTime = now.AddDays(7).Date.ToLocalTime().AddHours(14), Capacity = 4, ClubId = cyclingClub.Id, CreatedById = adminMembers.First(m => m.ClubId == cyclingClub.Id).Id, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow } }; context.Shifts.AddRange(shifts); await context.SaveChangesAsync(); } // Seed shift signups if (!context.ShiftSignups.Any()) { var shifts = context.Shifts.ToList(); var signups = new List(); // Add some signups for Tennis Club shifts var tennisShifts = shifts.Where(s => s.ClubId == tennisClub.Id).ToList(); if (tennisShifts.Count > 0) { var tennyMembers = context.Members.Where(m => m.ClubId == tennisClub.Id).ToList(); if (tennyMembers.Count > 0) { signups.Add(new ShiftSignup { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ShiftId = tennisShifts[0].Id, MemberId = tennyMembers[0].Id, SignedUpAt = DateTimeOffset.UtcNow }); if (tennyMembers.Count > 1) { signups.Add(new ShiftSignup { Id = Guid.NewGuid(), TenantId = tennisClub.TenantId, ShiftId = tennisShifts[0].Id, MemberId = tennyMembers[1].Id, SignedUpAt = DateTimeOffset.UtcNow }); } } } // Add some signups for Cycling Club shifts var cyclingShifts = shifts.Where(s => s.ClubId == cyclingClub.Id).ToList(); if (cyclingShifts.Count > 0) { var cyclingMembers = context.Members.Where(m => m.ClubId == cyclingClub.Id).ToList(); if (cyclingMembers.Count > 0) { signups.Add(new ShiftSignup { Id = Guid.NewGuid(), TenantId = cyclingClub.TenantId, ShiftId = cyclingShifts[0].Id, MemberId = cyclingMembers[0].Id, SignedUpAt = DateTimeOffset.UtcNow }); } } if (signups.Count > 0) { context.ShiftSignups.AddRange(signups); await context.SaveChangesAsync(); } } } private static string GenerateDeterministicGuid(string input) { // Generate a deterministic GUID from a string using MD5 var hash = MD5.HashData(Encoding.UTF8.GetBytes(input)); return new Guid(hash.Take(16).ToArray()).ToString(); } }