using Microsoft.EntityFrameworkCore;
using DramaLing.Api.Data;
using DramaLing.Api.Services;
using DramaLing.Api.Services.AI;
using DramaLing.Api.Services.Caching;
using DramaLing.Api.Repositories;
using DramaLing.Api.Models.Configuration;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Extensions.Options;
using System.Text;

namespace DramaLing.Api.Extensions;

/// <summary>
/// 服務集合擴展方法，用於組織和模組化依賴注入配置
/// </summary>
public static class ServiceCollectionExtensions
{
    /// <summary>
    /// 配置資料庫服務
    /// </summary>
    public static IServiceCollection AddDatabaseServices(this IServiceCollection services, IConfiguration configuration)
    {
        var useInMemoryDb = Environment.GetEnvironmentVariable("USE_INMEMORY_DB") == "true";

        if (useInMemoryDb)
        {
            services.AddDbContext<DramaLingDbContext>(options =>
                options.UseSqlite("Data Source=:memory:"));
        }
        else
        {
            var connectionString = Environment.GetEnvironmentVariable("DRAMALING_DB_CONNECTION")
                ?? configuration.GetConnectionString("DefaultConnection")
                ?? "Data Source=dramaling_test.db";

            services.AddDbContext<DramaLingDbContext>(options =>
                options.UseSqlite(connectionString));
        }

        return services;
    }

    /// <summary>
    /// 配置 Repository 服務
    /// </summary>
    public static IServiceCollection AddRepositoryServices(this IServiceCollection services)
    {
        services.AddScoped(typeof(IRepository<>), typeof(BaseRepository<>));
        services.AddScoped<IFlashcardRepository, SimpleFlashcardRepository>();
        services.AddScoped<IUserRepository, UserRepository>();

        return services;
    }

    /// <summary>
    /// 配置快取服務
    /// </summary>
    public static IServiceCollection AddCachingServices(this IServiceCollection services)
    {
        services.AddMemoryCache();
        services.AddScoped<ICacheService, HybridCacheService>();

        return services;
    }

    /// <summary>
    /// 配置 AI 服務
    /// </summary>
    public static IServiceCollection AddAIServices(this IServiceCollection services, IConfiguration configuration)
    {
        // 強型別配置
        services.Configure<GeminiOptions>(configuration.GetSection(GeminiOptions.SectionName));
        services.AddSingleton<IValidateOptions<GeminiOptions>, GeminiOptionsValidator>();

        // AI 提供商服務
        services.AddHttpClient<GeminiAIProvider>();
        services.AddScoped<IAIProvider, GeminiAIProvider>();
        services.AddScoped<IAIProviderManager, AIProviderManager>();

        // 舊的 Gemini 服務 (向後相容)
        services.AddHttpClient<IGeminiService, GeminiService>();

        return services;
    }

    /// <summary>
    /// 配置業務服務
    /// </summary>
    public static IServiceCollection AddBusinessServices(this IServiceCollection services)
    {
        services.AddScoped<IAuthService, AuthService>();
        services.AddScoped<IUsageTrackingService, UsageTrackingService>();
        services.AddScoped<IAzureSpeechService, AzureSpeechService>();
        services.AddScoped<IAudioCacheService, AudioCacheService>();

        return services;
    }

    /// <summary>
    /// 配置身份驗證
    /// </summary>
    public static IServiceCollection AddAuthenticationServices(this IServiceCollection services, IConfiguration configuration)
    {
        var supabaseUrl = Environment.GetEnvironmentVariable("DRAMALING_SUPABASE_URL")
            ?? configuration["Supabase:Url"]
            ?? "https://localhost";

        var jwtSecret = Environment.GetEnvironmentVariable("DRAMALING_SUPABASE_JWT_SECRET")
            ?? configuration["Supabase:JwtSecret"]
            ?? "dev-secret-minimum-32-characters-long-for-jwt-signing-in-development-mode-only";

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateLifetime = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = supabaseUrl,
                    ValidAudience = "authenticated",
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecret))
                };
            });

        return services;
    }

    /// <summary>
    /// 配置 CORS 政策
    /// </summary>
    public static IServiceCollection AddCorsServices(this IServiceCollection services)
    {
        services.AddCors(options =>
        {
            options.AddPolicy("AllowFrontend", policy =>
            {
                policy.WithOrigins("http://localhost:3000", "http://localhost:3001", "http://localhost:3002")
                      .AllowAnyHeader()
                      .AllowAnyMethod()
                      .AllowCredentials()
                      .SetPreflightMaxAge(TimeSpan.FromMinutes(5));
            });

            options.AddPolicy("AllowAll", policy =>
            {
                policy.AllowAnyOrigin()
                      .AllowAnyHeader()
                      .AllowAnyMethod();
            });
        });

        return services;
    }

    /// <summary>
    /// 配置 API 文檔服務
    /// </summary>
    public static IServiceCollection AddApiDocumentationServices(this IServiceCollection services)
    {
        services.AddEndpointsApiExplorer();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new() { Title = "DramaLing API", Version = "v1" });

            // JWT Authentication for Swagger
            c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme",
                Name = "Authorization",
                In = Microsoft.OpenApi.Models.ParameterLocation.Header,
                Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
                Scheme = "Bearer"
            });

            c.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
            {
                {
                    new Microsoft.OpenApi.Models.OpenApiSecurityScheme
                    {
                        Reference = new Microsoft.OpenApi.Models.OpenApiReference
                        {
                            Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        }
                    },
                    Array.Empty<string>()
                }
            });
        });

        return services;
    }
}