using Fast.Shared.Database.Models;
using Microsoft.AspNetCore.DataProtection.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace Fast.Shared.Database;

public partial class MyDbContext : IdentityDbContext<AppUser, IdentityRole<int>, int>, IDataProtectionKeyContext
{
    partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
    {
        //base.OnModelCreating is needed so that the Identity tables are created
        base.OnModelCreating(modelBuilder);

        foreach (var entity in modelBuilder.Model.GetEntityTypes())
        {
            if (IsAspEntity(entity))
                RenameAspEntity(entity);
        }

        // Configure view entities as tables in local mode so we can seed data
        if (ProgramShared.IsLocalModeEnabled)
        {
            ConfigureLocalModeEntities(modelBuilder);
        }
    }

    /// Configures view entities as regular tables for local mode.
    /// This allows us to insert seed data into these entities.
    private static void ConfigureLocalModeEntities(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<VwBrokerOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.BrokerId);
            entity.ToTable("vw_broker_overview_info");
        });

        modelBuilder.Entity<VwBusinessCalendar>(entity =>
        {
            entity.HasKey(e => e.Date);
            entity.ToTable("vw_business_calendar");
        });

        modelBuilder.Entity<VwBusinessTypeOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.BusinessTypeId);
            entity.ToTable("vw_business_type_overview_info");
        });

        modelBuilder.Entity<VwContactOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.ContactId);
            entity.ToTable("vw_contact_overview_info");
        });

        modelBuilder.Entity<VwCounterpartyOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.CounterpartyId);
            entity.ToTable("vw_counterparty_overview_info");
        });

        modelBuilder.Entity<VwCreditLimitCollateralOverview>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_credit_limit_collateral_overview");
        });

        modelBuilder.Entity<VwCrudePathFinalMeter>(entity =>
        {
            entity.HasKey(e => new { e.PathId, e.FinalMeterId });
            entity.ToTable("vw_crude_path_final_meter");
        });

        modelBuilder.Entity<VwCrudePathingOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PathId);
            entity.ToTable("vw_crude_pathing_overview_info");
        });

        modelBuilder.Entity<VwDealConfirmationInfo>(entity =>
        {
            entity.HasKey(e => e.TicketNum);
            entity.ToTable("vw_deal_confirmation_info");
        });

        modelBuilder.Entity<VwDealOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.DealId);
            entity.ToTable("vw_deal_overview_info");
        });

        modelBuilder.Entity<VwGasPathFinalMeter>(entity =>
        {
            entity.HasKey(e => new { e.PathId, e.FinalMeterId });
            entity.ToTable("vw_gas_path_final_meter");
        });

        modelBuilder.Entity<VwGasPathingOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PathId);
            entity.ToTable("vw_gas_pathing_overview_info");
        });

        modelBuilder.Entity<VwIndexOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.IndexId);
            entity.ToTable("vw_index_overview_info");
        });

        modelBuilder.Entity<VwInvoiceCrude>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_invoice_crude");
        });

        modelBuilder.Entity<VwInvoiceGa>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_invoice_gas");
        });

        modelBuilder.Entity<VwMeterOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_meter_overview_info");
        });

        modelBuilder.Entity<VwMeterPointCrude>(entity =>
        {
            entity.HasKey(e => new { e.MeterId, e.PointId });
            entity.ToTable("vw_meter_point_crude");
        });

        modelBuilder.Entity<VwMeterPointGa>(entity =>
        {
            entity.HasKey(e => new { e.MeterId, e.PointId });
            entity.ToTable("vw_meter_point_gas");
        });

        modelBuilder.Entity<VwPaymentInstructionOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PaymentInstructionId);
            entity.ToTable("vw_payment_instruction_overview_info");
        });

        modelBuilder.Entity<VwPipeContractOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PipeContractId);
            entity.ToTable("vw_pipe_contract_overview_info");
        });

        modelBuilder.Entity<VwPipeRateScheduleOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PipeRateScheduleId);
            entity.ToTable("vw_pipe_rate_schedule_overview_info");
        });

        modelBuilder.Entity<VwPipelineOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PipeId);
            entity.ToTable("vw_pipeline_overview_info");
        });

        modelBuilder.Entity<VwPlantStatementOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PlantStatementId);
            entity.ToTable("vw_plant_statement_overview_info");
        });

        modelBuilder.Entity<VwPointOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.PointId);
            entity.ToTable("vw_point_overview_info");
        });

        modelBuilder.Entity<VwRptCounterparty>(entity =>
        {
            entity.HasKey(e => e.CounterpartyId);
            entity.ToTable("vw_rpt_counterparty");
        });

        modelBuilder.Entity<VwRptCreditLimit>(entity =>
        {
            entity.HasKey(e => e.ParentCounterpartyId);
            entity.ToTable("vw_rpt_credit_limit");
        });

        modelBuilder.Entity<VwRptDailyIndexPrice>(entity =>
        {
            entity.HasKey(e => new { e.IndexId, e.PriceDate, e.ContractMonth });
            entity.ToTable("vw_rpt_daily_index_price");
        });

        modelBuilder.Entity<VwRptDeal>(entity =>
        {
            entity.HasKey(e => e.TicketNumber);
            entity.ToTable("vw_rpt_deal");
        });

        modelBuilder.Entity<VwRptForwardIndexPrice>(entity =>
        {
            entity.HasKey(e => new { e.IndexId, e.PriceDate, e.ContractMonth });
            entity.ToTable("vw_rpt_forward_index_price");
        });

        modelBuilder.Entity<VwRptMeterDatum>(entity =>
        {
            entity.HasKey(e => e.MeterName);
            entity.ToTable("vw_rpt_meter_data");
        });

        modelBuilder.Entity<VwRptMonthlyIndexPrice>(entity =>
        {
            entity.HasKey(e => new { e.IndexId, e.PriceDate });
            entity.ToTable("vw_rpt_monthly_index_price");
        });

        modelBuilder.Entity<VwRptPlantStatement>(entity =>
        {
            entity.HasKey(e => new { e.PlantId, e.MeterId, e.ProductionMonth });
            entity.ToTable("vw_rpt_plant_statement");
        });

        modelBuilder.Entity<VwRptValuationDataDeal>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_rpt_valuation_data_deals");
        });

        modelBuilder.Entity<VwSalesTaxOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_sales_tax_overview_info");
        });

        modelBuilder.Entity<VwSeveranceTaxOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.StateId);
            entity.ToTable("vw_severance_tax_overview_info");
        });

        modelBuilder.Entity<VwUserOverviewInfo>(entity =>
        {
            entity.HasKey(e => e.UserInfoId);
            entity.ToTable("vw_user_overview_info");
        });

        modelBuilder.Entity<VwValDeal>(entity =>
        {
            entity.HasKey(e => e.Id);
            entity.ToTable("vw_val_deal");
        });

        modelBuilder.Entity<VwValDealVolume>(entity =>
        {
            entity.HasKey(e => new { e.DealId, e.DateKey });
            entity.ToTable("vw_val_deal_volume");
        });
    }

    private readonly Dictionary<string, string> AspEntityNames = new()
    {
        { "AppUser", "app_user" },
        { "AspRole", "asp_role" },
        { "AspRoleClaim", "asp_role_claim" },
        { "AspUserClaim", "asp_user_claim" },
        { "AspUserLogin", "asp_user_login" },
        { "AspUserRole", "asp_user_role" },
        { "AspUserToken", "asp_user_token" },
        { "Fast.Shared.Database.Models.AppUser", "app_user" },
        { "Fast.Shared.Database.Models.AspRole", "asp_role" },
        { "Fast.Shared.Database.Models.AspRoleClaim", "asp_role_claim" },
        { "Fast.Shared.Database.Models.AspUserClaim", "asp_user_claim" },
        { "Fast.Shared.Database.Models.AspUserLogin", "asp_user_login" },
        { "Fast.Shared.Database.Models.AspUserRole", "asp_user_role" },
        { "Fast.Shared.Database.Models.AspUserToken", "asp_user_token" }
    };

    private bool IsAspEntity(Microsoft.EntityFrameworkCore.Metadata.IMutableEntityType entity)
    {
        if (AspEntityNames.ContainsKey(entity.Name))
            return true;
        return false;
    }

    private void RenameAspEntity(Microsoft.EntityFrameworkCore.Metadata.IMutableEntityType entity)
    {
        var newTableName = AspEntityNames[entity.Name];
        entity.SetTableName(newTableName);


        if (newTableName == "app_user")
        {
            var properties = entity.GetProperties().ToList();
            foreach (var property in properties)
                property.SetColumnName(property.Name.ToSnakeCase());
        }
    }
}
