using System.Text;

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;

using MilitaryTrainingManagement.Authorization;
using MilitaryTrainingManagement.Configuration;
using MilitaryTrainingManagement.Data;
using MilitaryTrainingManagement.Models.Enums;
using MilitaryTrainingManagement.Services.Implementations;
using MilitaryTrainingManagement.Services.Interfaces;

var builder = WebApplication.CreateBuilder(args);

// 配置文件存储选项
builder.Services.Configure<FileStorageOptions>(
    builder.Configuration.GetSection(FileStorageOptions.SectionName));

// 添加HttpContextAccessor用于审计拦截器
builder.Services.AddHttpContextAccessor();

// 注册审计拦截器
builder.Services.AddScoped<AuditInterceptor>();

// 配置数据库连接 - 使用SQL Server
builder.Services.AddDbContext<ApplicationDbContext>((serviceProvider, options) =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
    // 注册审计拦截器
    var interceptor = serviceProvider.GetRequiredService<AuditInterceptor>();
    options.AddInterceptors(interceptor);
});

// 配置JWT认证
var jwtKey = builder.Configuration["Jwt:Key"] ?? throw new InvalidOperationException("JWT Key not configured");
var jwtIssuer = builder.Configuration["Jwt:Issuer"] ?? "MilitaryTrainingManagement";
var jwtAudience = builder.Configuration["Jwt:Audience"] ?? "MilitaryTrainingManagementUsers";

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = jwtIssuer,
            ValidAudience = jwtAudience,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtKey))
        };
    });

// 配置授权策略
builder.Services.AddAuthorization(options =>
{
    // 师团级权限策略
    options.AddPolicy("DivisionLevel", policy =>
        policy.Requirements.Add(new OrganizationalLevelRequirement(OrganizationalLevel.Division)));

    // 团级及以上权限策略
    options.AddPolicy("RegimentLevel", policy =>
        policy.Requirements.Add(new OrganizationalLevelRequirement(OrganizationalLevel.Regiment)));

    // 营级及以上权限策略
    options.AddPolicy("BattalionLevel", policy =>
        policy.Requirements.Add(new OrganizationalLevelRequirement(OrganizationalLevel.Battalion)));

    // 连级及以上权限策略（所有已认证用户）
    options.AddPolicy("CompanyLevel", policy =>
        policy.Requirements.Add(new OrganizationalLevelRequirement(OrganizationalLevel.Company)));
});

// 注册授权处理器
builder.Services.AddScoped<IAuthorizationHandler, OrganizationalLevelAuthorizationHandler>();
builder.Services.AddScoped<IAuthorizationHandler, OrganizationalResourceAuthorizationHandler>();
builder.Services.AddScoped<IOrganizationalAuthorizationService, OrganizationalAuthorizationService>();

// 注册服务
builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
builder.Services.AddScoped<IOrganizationService, OrganizationService>();
builder.Services.AddScoped<IAllocationService, AllocationService>();
builder.Services.AddScoped<IReportingService, ReportingService>();
builder.Services.AddScoped<IDataAggregatorService, DataAggregatorService>();
builder.Services.AddScoped<IPersonnelService, PersonnelService>();
builder.Services.AddScoped<IWorkflowService, WorkflowService>();
builder.Services.AddScoped<IAuditService, AuditService>();
builder.Services.AddScoped<IFileUploadService, FileUploadService>();

// 配置控制器
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
        // 将枚举序列化为字符串
        options.JsonSerializerOptions.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
        // 使用 camelCase 命名策略（输出）
        options.JsonSerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
        // 允许不区分大小写的属性名匹配（输入）
        options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
    });

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "兵团训练物资管控系统 API", Version = "v1" });
    c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        Description = "JWT Authorization header using the Bearer scheme",
        Name = "Authorization",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.ApiKey,
        Scheme = "Bearer"
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    });
});

// 配置CORS
#if DEBUG
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowAll", policy =>
    {
        policy.AllowAnyOrigin()
              .AllowAnyMethod()
              .AllowAnyHeader();
    });
});
#endif
var app = builder.Build();

// 配置HTTP请求管道

// 启用静态文件服务
app.UseStaticFiles();

app.UseSwagger();
app.UseSwaggerUI();


app.UseHttpsRedirection();
#if DEBUG
app.UseCors("AllowAll");
#endif
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();

// 初始化数据库和种子数据
using (var scope = app.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
    var authService = scope.ServiceProvider.GetRequiredService<IAuthenticationService>();
    var environment = scope.ServiceProvider.GetRequiredService<IWebHostEnvironment>();

    // 确保uploads目录存在并有写入权限
    try
    {
        var uploadsPath = Path.Combine(environment.WebRootPath ?? environment.ContentRootPath, "uploads");
        var photosPath = Path.Combine(uploadsPath, "photos");
        var documentsPath = Path.Combine(uploadsPath, "documents");
        
        Directory.CreateDirectory(uploadsPath);
        Directory.CreateDirectory(photosPath);
        Directory.CreateDirectory(documentsPath);
        
        Console.WriteLine($"Uploads 目录已创建: {uploadsPath}");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"创建 uploads 目录时出错: {ex.Message}");
    }

    // 确保数据库已创建
    context.Database.EnsureCreated();
    
    // 手动创建 MaterialCategories 表（如果不存在）
    try
    {
        var tableExists = context.Database.ExecuteSqlRaw(@"
            IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'MaterialCategories')
            BEGIN
                CREATE TABLE MaterialCategories (
                    Id INT PRIMARY KEY IDENTITY(1,1),
                    Name NVARCHAR(50) NOT NULL,
                    Description NVARCHAR(200),
                    IsActive BIT NOT NULL DEFAULT 1,
                    CreatedAt DATETIME2 NOT NULL,
                    SortOrder INT NOT NULL DEFAULT 0
                );
                CREATE UNIQUE INDEX IX_MaterialCategories_Name ON MaterialCategories(Name);
            END
        ");
        Console.WriteLine("MaterialCategories 表检查完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"创建 MaterialCategories 表时出错: {ex.Message}");
    }

    // 添加Personnel表的新列（如果不存在）
    try
    {
        context.Database.ExecuteSqlRaw(@"
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'Unit')
                ALTER TABLE Personnel ADD Unit nvarchar(100) NULL;
            
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'Ethnicity')
                ALTER TABLE Personnel ADD Ethnicity nvarchar(50) NULL;
            
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'PoliticalStatus')
                ALTER TABLE Personnel ADD PoliticalStatus nvarchar(50) NULL;
            
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'BirthDate')
                ALTER TABLE Personnel ADD BirthDate nvarchar(20) NULL;
            
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'EnlistmentDate')
                ALTER TABLE Personnel ADD EnlistmentDate nvarchar(20) NULL;
            
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'Specialty')
                ALTER TABLE Personnel ADD Specialty nvarchar(200) NULL;
            
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'PendingUpgradeByUnitId')
                ALTER TABLE Personnel ADD PendingUpgradeByUnitId INT NULL;
        ");
        Console.WriteLine("Personnel 表列检查完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"添加 Personnel 表列时出错: {ex.Message}");
    }

    // 添加UserAccounts表的PlainPassword列（如果不存在）
    try
    {
        context.Database.ExecuteSqlRaw(@"
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('UserAccounts') AND name = 'PlainPassword')
                ALTER TABLE UserAccounts ADD PlainPassword nvarchar(100) NULL;
        ");
        Console.WriteLine("UserAccounts 表 PlainPassword 列检查完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"添加 UserAccounts 表 PlainPassword 列时出错: {ex.Message}");
    }

    // 创建 ConsumptionReports 表（如果不存在）
    try
    {
        context.Database.ExecuteSqlRaw(@"
            IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ConsumptionReports')
            BEGIN
                CREATE TABLE ConsumptionReports (
                    Id INT PRIMARY KEY IDENTITY(1,1),
                    AllocationDistributionId INT NOT NULL,
                    ReportedAmount DECIMAL(18,2) NOT NULL,
                    CumulativeAmount DECIMAL(18,2) NOT NULL,
                    Remarks NVARCHAR(500) NULL,
                    ReportedByUserId INT NOT NULL,
                    ReportedAt DATETIME2 NOT NULL,
                    CONSTRAINT FK_ConsumptionReports_AllocationDistributions 
                        FOREIGN KEY (AllocationDistributionId) 
                        REFERENCES AllocationDistributions(Id) ON DELETE CASCADE,
                    CONSTRAINT FK_ConsumptionReports_UserAccounts 
                        FOREIGN KEY (ReportedByUserId) 
                        REFERENCES UserAccounts(Id)
                );
                CREATE INDEX IX_ConsumptionReports_AllocationDistributionId ON ConsumptionReports(AllocationDistributionId);
                CREATE INDEX IX_ConsumptionReports_ReportedAt ON ConsumptionReports(ReportedAt);
                CREATE INDEX IX_ConsumptionReports_ReportedByUserId ON ConsumptionReports(ReportedByUserId);
            END
        ");
        Console.WriteLine("ConsumptionReports 表检查完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"创建 ConsumptionReports 表时出错: {ex.Message}");
    }

    // 添加 ConsumptionReports.ReportedByUnitId 列（如果不存在）
    try
    {
        context.Database.ExecuteSqlRaw(@"
            IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('ConsumptionReports') AND name = 'ReportedByUnitId')
                ALTER TABLE ConsumptionReports ADD ReportedByUnitId INT NOT NULL DEFAULT 1;
        ");
        Console.WriteLine("ConsumptionReports.ReportedByUnitId 列检查完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"添加 ConsumptionReports.ReportedByUnitId 列时出错: {ex.Message}");
    }

    // 创建 ConsumptionReportChangeRequests 表（如果不存在）
    try
    {
        context.Database.ExecuteSqlRaw(@"
            IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'ConsumptionReportChangeRequests')
            BEGIN
                CREATE TABLE ConsumptionReportChangeRequests (
                    Id INT IDENTITY(1,1) PRIMARY KEY,
                    ConsumptionReportId INT NOT NULL,
                    RequestType INT NOT NULL,
                    Reason NVARCHAR(500) NOT NULL,
                    Status INT NOT NULL,
                    RequestedByUnitId INT NOT NULL,
                    RequestedByUserId INT NOT NULL,
                    RequestedAt DATETIME2 NOT NULL,
                    ProcessedByUnitId INT NULL,
                    ProcessedByUserId INT NULL,
                    ProcessedAt DATETIME2 NULL,
                    ProcessComments NVARCHAR(500) NULL,
                    CONSTRAINT FK_ConsumptionReportChangeRequests_ConsumptionReports 
                        FOREIGN KEY (ConsumptionReportId) REFERENCES ConsumptionReports(Id) ON DELETE CASCADE,
                    CONSTRAINT FK_ConsumptionReportChangeRequests_RequestedByUnit 
                        FOREIGN KEY (RequestedByUnitId) REFERENCES OrganizationalUnits(Id),
                    CONSTRAINT FK_ConsumptionReportChangeRequests_RequestedByUser 
                        FOREIGN KEY (RequestedByUserId) REFERENCES UserAccounts(Id),
                    CONSTRAINT FK_ConsumptionReportChangeRequests_ProcessedByUnit 
                        FOREIGN KEY (ProcessedByUnitId) REFERENCES OrganizationalUnits(Id),
                    CONSTRAINT FK_ConsumptionReportChangeRequests_ProcessedByUser 
                        FOREIGN KEY (ProcessedByUserId) REFERENCES UserAccounts(Id)
                );
                CREATE INDEX IX_ConsumptionReportChangeRequests_ConsumptionReportId ON ConsumptionReportChangeRequests(ConsumptionReportId);
                CREATE INDEX IX_ConsumptionReportChangeRequests_Status ON ConsumptionReportChangeRequests(Status);
                CREATE INDEX IX_ConsumptionReportChangeRequests_RequestedByUnitId ON ConsumptionReportChangeRequests(RequestedByUnitId);
            END
        ");
        Console.WriteLine("ConsumptionReportChangeRequests 表检查完成");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"创建 ConsumptionReportChangeRequests 表时出错: {ex.Message}");
    }

    // 如果没有物资类别，创建默认类别
    if (!context.MaterialCategories.Any())
    {
        var categories = new[]
        {
            new MilitaryTrainingManagement.Models.Entities.MaterialCategory
            {
                Name = "弹药",
                Description = "各类训练弹药",
                IsActive = true,
                SortOrder = 1,
                CreatedAt = DateTime.UtcNow
            },
            new MilitaryTrainingManagement.Models.Entities.MaterialCategory
            {
                Name = "装备",
                Description = "训练装备器材",
                IsActive = true,
                SortOrder = 2,
                CreatedAt = DateTime.UtcNow
            },
            new MilitaryTrainingManagement.Models.Entities.MaterialCategory
            {
                Name = "物资",
                Description = "训练保障物资",
                IsActive = true,
                SortOrder = 3,
                CreatedAt = DateTime.UtcNow
            },
            new MilitaryTrainingManagement.Models.Entities.MaterialCategory
            {
                Name = "器材",
                Description = "训练辅助器材",
                IsActive = true,
                SortOrder = 4,
                CreatedAt = DateTime.UtcNow
            }
        };
        context.MaterialCategories.AddRange(categories);
        await context.SaveChangesAsync();
        Console.WriteLine("默认物资类别已创建！");
    }

    // 如果没有组织单位，创建种子数据
    if (!context.OrganizationalUnits.Any())
    {
        // 创建师团级组织
        var division = new MilitaryTrainingManagement.Models.Entities.OrganizationalUnit
        {
            Name = "第一师团",
            Level = OrganizationalLevel.Division,
            CreatedAt = DateTime.UtcNow
        };
        context.OrganizationalUnits.Add(division);
        await context.SaveChangesAsync();

        // 创建团级组织
        var regiment = new MilitaryTrainingManagement.Models.Entities.OrganizationalUnit
        {
            Name = "第一团",
            Level = OrganizationalLevel.Regiment,
            ParentId = division.Id,
            CreatedAt = DateTime.UtcNow
        };
        context.OrganizationalUnits.Add(regiment);
        await context.SaveChangesAsync();

        // 创建营级组织
        var battalion = new MilitaryTrainingManagement.Models.Entities.OrganizationalUnit
        {
            Name = "第一营",
            Level = OrganizationalLevel.Battalion,
            ParentId = regiment.Id,
            CreatedAt = DateTime.UtcNow
        };
        context.OrganizationalUnits.Add(battalion);
        await context.SaveChangesAsync();

        // 创建连级组织
        var company = new MilitaryTrainingManagement.Models.Entities.OrganizationalUnit
        {
            Name = "第一连",
            Level = OrganizationalLevel.Company,
            ParentId = battalion.Id,
            CreatedAt = DateTime.UtcNow
        };
        context.OrganizationalUnits.Add(company);
        await context.SaveChangesAsync();

        // 创建师团管理员账户
        await authService.CreateUserAsync("admin", "admin123", "师团管理员", division.Id);

        // 创建团级账户
        await authService.CreateUserAsync("regiment", "regiment123", "团级管理员", regiment.Id);

        // 创建营级账户
        await authService.CreateUserAsync("battalion", "battalion123", "营级管理员", battalion.Id);

        // 创建连级账户
        await authService.CreateUserAsync("company", "company123", "连级管理员", company.Id);

        Console.WriteLine("种子数据已创建！");
        Console.WriteLine("默认账户：");
        Console.WriteLine("  师团管理员: admin / admin123");
        Console.WriteLine("  团级管理员: regiment / regiment123");
        Console.WriteLine("  营级管理员: battalion / battalion123");
        Console.WriteLine("  连级管理员: company / company123");
    }
}

app.Run();
