using BookmarkApi.Core.Interfaces;
using BookmarkApi.Data.Entities;
using BookmarkApi.Shared.DTOs;

namespace BookmarkApi.Core.Services;

/// <summary>
/// 标签服务实现
/// </summary>
public class TagService : ITagService
{
    private readonly IFreeSql _freeSql;

    public TagService(IFreeSql freeSql)
    {
        _freeSql = freeSql;
    }

    /// <inheritdoc />
    public async Task<List<TagDto>> GetUserTagsAsync(Guid userId)
    {
        // 查询所有标签及其使用数量
        var tags = await _freeSql.Select<Tag>()
            .Where(t => t.UserId == userId)
            .OrderBy(t => t.Order)
            .ToListAsync();

        // 统计每个标签的使用数量
        var tagIds = tags.Select(t => t.Id).ToList();
        var bookmarkTags = await _freeSql.Select<BookmarkTag>()
            .Where(bt => tagIds.Contains(bt.TagId))
            .ToListAsync();

        var countDict = bookmarkTags
            .GroupBy(bt => bt.TagId)
            .ToDictionary(g => g.Key, g => g.Count());

        return tags.Select(t => new TagDto
        {
            Id = t.Id,
            Name = t.Name,
            Color = t.Color,
            Icon = t.Icon,
            Order = t.Order,
            Count = countDict.TryGetValue(t.Id, out var count) ? count : 0
        }).ToList();
    }

    /// <inheritdoc />
    public async Task<TagDto?> GetTagAsync(Guid tagId, Guid userId)
    {
        var tag = await _freeSql.Select<Tag>()
            .Where(t => t.Id == tagId && t.UserId == userId)
            .FirstAsync();

        if (tag == null)
        {
            return null;
        }

        // 统计使用数量
        var count = await _freeSql.Select<BookmarkTag>()
            .Where(bt => bt.TagId == tagId)
            .CountAsync();

        return new TagDto
        {
            Id = tag.Id,
            Name = tag.Name,
            Color = tag.Color,
            Icon = tag.Icon,
            Order = tag.Order,
            Count = (int)count
        };
    }

    /// <inheritdoc />
    public async Task<TagDto> CreateTagAsync(Guid userId, string name, string? color = null, string? icon = null)
    {
        // 检查标签名是否已存在
        var exists = await _freeSql.Select<Tag>()
            .Where(t => t.UserId == userId && t.Name == name)
            .AnyAsync();

        if (exists)
        {
            throw new InvalidOperationException($"标签 '{name}' 已存在");
        }

        // 获取最大排序值
        var maxOrder = await _freeSql.Select<Tag>()
            .Where(t => t.UserId == userId)
            .MaxAsync(t => t.Order);

        var tag = new Tag
        {
            Id = Guid.NewGuid(),
            UserId = userId,
            Name = name,
            Color = color,
            Icon = icon,
            Order = maxOrder + 1,
            CreatedAt = DateTime.UtcNow
        };

        await _freeSql.Insert(tag).ExecuteAffrowsAsync();

        return new TagDto
        {
            Id = tag.Id,
            Name = tag.Name,
            Color = tag.Color,
            Icon = tag.Icon,
            Order = tag.Order,
            Count = 0
        };
    }

    /// <inheritdoc />
    public async Task<TagDto?> UpdateTagAsync(Guid tagId, Guid userId, string? name = null, string? color = null, string? icon = null)
    {
        var tag = await _freeSql.Select<Tag>()
            .Where(t => t.Id == tagId && t.UserId == userId)
            .FirstAsync();

        if (tag == null)
        {
            return null;
        }

        // 如果修改名称，检查是否与其他标签重复
        if (!string.IsNullOrEmpty(name) && name != tag.Name)
        {
            var exists = await _freeSql.Select<Tag>()
                .Where(t => t.UserId == userId && t.Name == name && t.Id != tagId)
                .AnyAsync();

            if (exists)
            {
                throw new InvalidOperationException($"标签 '{name}' 已存在");
            }

            tag.Name = name;
        }

        if (color != null)
        {
            tag.Color = color;
        }

        if (icon != null)
        {
            tag.Icon = icon;
        }

        await _freeSql.Update<Tag>()
            .SetSource(tag)
            .ExecuteAffrowsAsync();

        // 统计使用数量
        var count = await _freeSql.Select<BookmarkTag>()
            .Where(bt => bt.TagId == tagId)
            .CountAsync();

        return new TagDto
        {
            Id = tag.Id,
            Name = tag.Name,
            Color = tag.Color,
            Icon = tag.Icon,
            Order = tag.Order,
            Count = (int)count
        };
    }

    /// <inheritdoc />
    public async Task<bool> RenameTagAsync(Guid userId, string oldName, string newName)
    {
        var tag = await _freeSql.Select<Tag>()
            .Where(t => t.UserId == userId && t.Name == oldName)
            .FirstAsync();

        if (tag == null)
        {
            return false;
        }

        // 检查新名称是否已存在
        var exists = await _freeSql.Select<Tag>()
            .Where(t => t.UserId == userId && t.Name == newName)
            .AnyAsync();

        if (exists)
        {
            throw new InvalidOperationException($"标签 '{newName}' 已存在");
        }

        await _freeSql.Update<Tag>()
            .Set(t => t.Name, newName)
            .Where(t => t.Id == tag.Id)
            .ExecuteAffrowsAsync();

        return true;
    }

    /// <inheritdoc />
    public async Task<bool> DeleteTagAsync(Guid tagId, Guid userId)
    {
        // 先删除关联
        await _freeSql.Delete<BookmarkTag>()
            .Where(bt => bt.TagId == tagId)
            .ExecuteAffrowsAsync();

        // 删除标签
        var affectedRows = await _freeSql.Delete<Tag>()
            .Where(t => t.Id == tagId && t.UserId == userId)
            .ExecuteAffrowsAsync();

        return affectedRows > 0;
    }

    /// <inheritdoc />
    public async Task<int> MergeTagsAsync(Guid userId, Guid[] sourceTagIds, Guid targetTagId)
    {
        // 验证目标标签存在
        var targetTag = await _freeSql.Select<Tag>()
            .Where(t => t.Id == targetTagId && t.UserId == userId)
            .FirstAsync();

        if (targetTag == null)
        {
            throw new InvalidOperationException("目标标签不存在");
        }

        // 获取所有源标签关联的书签
        var sourceBookmarkTags = await _freeSql.Select<BookmarkTag>()
            .Where(bt => sourceTagIds.Contains(bt.TagId))
            .ToListAsync();

        var affectedCount = 0;

        foreach (var bt in sourceBookmarkTags)
        {
            // 检查目标标签是否已经关联该书签
            var exists = await _freeSql.Select<BookmarkTag>()
                .Where(x => x.BookmarkId == bt.BookmarkId && x.TagId == targetTagId)
                .AnyAsync();

            if (!exists)
            {
                // 创建新关联
                var newBt = new BookmarkTag
                {
                    Id = Guid.NewGuid(),
                    BookmarkId = bt.BookmarkId,
                    TagId = targetTagId,
                    CreatedAt = DateTime.UtcNow
                };

                await _freeSql.Insert(newBt).ExecuteAffrowsAsync();
                affectedCount++;
            }
        }

        // 删除源标签的所有关联
        await _freeSql.Delete<BookmarkTag>()
            .Where(bt => sourceTagIds.Contains(bt.TagId))
            .ExecuteAffrowsAsync();

        // 删除源标签
        await _freeSql.Delete<Tag>()
            .Where(t => sourceTagIds.Contains(t.Id) && t.UserId == userId)
            .ExecuteAffrowsAsync();

        return affectedCount;
    }
}
