using AsbCloudDb;
using AsbCloudDb.Model;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Refit;
using System.Net.Http.Headers;
using System.Text.Json;
using AsbCloudWebApi.IntegrationTests.Converters;
using Xunit;

namespace AsbCloudWebApi.IntegrationTests;

public class WebAppFactoryFixture : WebApplicationFactory<Startup>,
	IAsyncLifetime
{
    private static readonly JsonSerializerOptions jsonSerializerOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true,
		Converters = { new ValidationResultConverter() }
    };

    private static readonly RefitSettings refitSettings = new RefitSettings(new SystemTextJsonContentSerializer(jsonSerializerOptions));

    protected override void ConfigureWebHost(IWebHostBuilder builder)
	{
		var configuration = new ConfigurationBuilder()
			.AddJsonFile("appsettings.json")
			.Build();
		var connectionString = configuration.GetConnectionString("TestConnection")!;

        builder.ConfigureServices(services =>
		{
			var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(DbContextOptions<AsbCloudDbContext>));

			if (descriptor is not null)
				services.Remove(descriptor);

			services.AddDbContext<AsbCloudDbContext>(options =>
				options.UseNpgsql(connectionString));
		});
	}

	public async Task InitializeAsync()
	{
		using var scope = Services.CreateScope();
		var scopedServices = scope.ServiceProvider;
		var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
        dbContext.Database.EnsureDeleted();
        dbContext.Database.EnsureCreatedAndMigrated();
		await FillBaseDatasets(dbContext);
	}

    private static async Task FillBaseDatasets(AsbCloudDbContext dbContext)
    {
        dbContext.AddRange(Data.Defaults.Deposits);
        dbContext.AddRange(Data.Defaults.Clusters);
        dbContext.AddRange(Data.Defaults.Wells);
        dbContext.AddRange(Data.Defaults.RelationsCompanyWell);
		dbContext.AddRange(Data.Defaults.Telemetries);
		dbContext.AddRange(Data.Defaults.Drillers);
        dbContext.AddRange(Data.Defaults.WellOperations);
        await dbContext.SaveChangesAsync();
    }

    public new async Task DisposeAsync()
	{
		using var scope = Services.CreateScope();
		var scopedServices = scope.ServiceProvider;
		var dbContext = scopedServices.GetRequiredService<AsbCloudDbContext>();
		
		await dbContext.Database.EnsureDeletedAsync();
    }

    public HttpClient GetAuthorizedHttpClient()
    {
        var httpClient = CreateClient();
        var jwtToken = ApiTokenHelper.GetAdminUserToken();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
        return httpClient;
    }

    public T GetAuthorizedHttpClient<T>()
    {
        var httpClient = GetAuthorizedHttpClient();
        return RestService.For<T>(httpClient, refitSettings);
    }

}