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 CloudTaskSyncService
{
    private readonly TodoDbContext _dbContext;

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

    /// <summary>
    /// 获取指定用户的任务全量。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="cancellationToken">取消令牌。</param>
    /// <returns>任务列表。</returns>
    public async Task<List<CloudTaskItem>> GetTasksAsync(Guid userId, CancellationToken cancellationToken)
    {
        var tasks = await _dbContext.Tasks
            .AsNoTracking()
            .Where(t => t.UserId == userId)
            .OrderByDescending(t => t.CreatedAt)
            .ToListAsync(cancellationToken);

        return tasks.Select(MapToItem).ToList();
    }

    /// <summary>
    /// 执行同步（增改删），并返回最新全量。
    /// </summary>
    /// <param name="userId">用户 ID。</param>
    /// <param name="request">同步请求。</param>
    /// <param name="cancellationToken">取消令牌。</param>
    /// <returns>同步响应。</returns>
    public async Task<SyncResponse> SyncAsync(Guid userId, SyncRequest request, CancellationToken cancellationToken)
    {
        request ??= new SyncRequest();

        if (request.Deletes.Count > 0)
        {
            var deleteIds = request.Deletes.Distinct().ToList();
            var toDelete = await _dbContext.Tasks
                .Where(t => t.UserId == userId && deleteIds.Contains(t.Id))
                .ToListAsync(cancellationToken);

            if (toDelete.Count > 0)
            {
                _dbContext.Tasks.RemoveRange(toDelete);
            }
        }

        if (request.Upserts.Count > 0)
        {
            foreach (var upsert in request.Upserts)
            {
                if (string.IsNullOrWhiteSpace(upsert.Title))
                {
                    continue;
                }

                if (upsert.Id.HasValue)
                {
                    var existing = await _dbContext.Tasks
                        .FirstOrDefaultAsync(t => t.UserId == userId && t.Id == upsert.Id.Value, cancellationToken);

                    if (existing != null)
                    {
                        existing.Title = upsert.Title.Trim();
                        existing.Priority = upsert.Priority;
                        existing.IsCompleted = upsert.IsCompleted;
                        existing.ParentTaskId = upsert.ParentTaskId;
                        existing.UpdatedAt = DateTime.UtcNow;
                        continue;
                    }
                }

                var entity = new TaskEntity
                {
                    UserId = userId,
                    Title = upsert.Title.Trim(),
                    Priority = upsert.Priority,
                    IsCompleted = upsert.IsCompleted,
                    CreatedAt = DateTime.UtcNow,
                    UpdatedAt = DateTime.UtcNow,
                    ParentTaskId = upsert.ParentTaskId
                };

                _dbContext.Tasks.Add(entity);
            }
        }

        await _dbContext.SaveChangesAsync(cancellationToken);

        return new SyncResponse
        {
            ServerTimeUtc = DateTime.UtcNow,
            Tasks = await GetTasksAsync(userId, cancellationToken)
        };
    }

    private static CloudTaskItem MapToItem(TaskEntity task)
    {
        return new CloudTaskItem
        {
            Id = task.Id,
            Title = task.Title,
            Priority = task.Priority,
            IsCompleted = task.IsCompleted,
            CreatedAtUtc = task.CreatedAt,
            UpdatedAtUtc = task.UpdatedAt,
            ParentTaskId = task.ParentTaskId
        };
    }
}

