using Microsoft.EntityFrameworkCore;
using Hua.Todo.Application.CloudSync.Models;
using Hua.Todo.Application.Data;
using Hua.Todo.Core.Entities;

namespace Hua.Todo.Application.CloudSync.Services;

/// <summary>
/// 安全策略服务（按用户隔离）。
/// </summary>
public class SecurityPolicyService
{
    private readonly TodoDbContext _dbContext;

    /// <summary>
    /// 创建 <see cref="SecurityPolicyService"/>。
    /// </summary>
    /// <param name="dbContext">数据库上下文。</param>
    public SecurityPolicyService(TodoDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    /// <summary>
    /// 获取指定用户的安全策略。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="cancellationToken">取消令牌。</param>
    /// <returns>策略 DTO。</returns>
    public async Task<SecurityPolicyDto> GetPolicyAsync(Guid userId, CancellationToken cancellationToken)
    {
        var policy = await _dbContext.SecurityPolicies
            .AsNoTracking()
            .FirstOrDefaultAsync(p => p.UserId == userId, cancellationToken);

        return new SecurityPolicyDto
        {
            AllowPersist = policy?.AllowPersist ?? true,
            AllowSync = policy?.AllowSync ?? true,
            RequireSecondFactorFor = new List<string> { "sync:write", "policy:write" }
        };
    }

    /// <summary>
    /// 更新指定用户的安全策略（覆盖式更新）。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="allowPersist">是否允许落盘。</param>
    /// <param name="cancellationToken">取消令牌。</param>
    /// <returns>更新后的策略 DTO。</returns>
    public async Task<SecurityPolicyDto> UpdatePolicyAsync(Guid userId, bool allowPersist, bool allowSync, CancellationToken cancellationToken)
    {
        var policy = await _dbContext.SecurityPolicies.FirstOrDefaultAsync(p => p.UserId == userId, cancellationToken);
        if (policy == null)
        {
            policy = new SecurityPolicyEntity { Id = Guid.NewGuid(), UserId = userId, AllowPersist = allowPersist, AllowSync = allowSync };
            _dbContext.SecurityPolicies.Add(policy);
        }
        else
        {
            policy.AllowPersist = allowPersist;
            policy.AllowSync = allowSync;
        }

        await _dbContext.SaveChangesAsync(cancellationToken);

        return await GetPolicyAsync(userId, cancellationToken);
    }
}
