using Microsoft.AspNetCore.Identity;
using SolutionErp.Application.Common.Interfaces;
using SolutionErp.Domain.Contracts;
using SolutionErp.Domain.Identity;

namespace SolutionErp.Infrastructure.Services;

// Impl IChangelogService. Resolve current user qua ICurrentUser (null = system,
// vd SLA auto-approve). Denormalize UserName để log readable mà không cần JOIN
// Users table khi render.
public class ChangelogService : IChangelogService
{
    private readonly IApplicationDbContext _db;
    private readonly ICurrentUser _currentUser;
    private readonly UserManager<User> _userManager;

    public ChangelogService(IApplicationDbContext db, ICurrentUser currentUser, UserManager<User> userManager)
    {
        _db = db;
        _currentUser = currentUser;
        _userManager = userManager;
    }

    private async Task<(Guid? Id, string? Name)> ResolveActorAsync()
    {
        if (_currentUser.UserId is null) return (null, null);
        var user = await _userManager.FindByIdAsync(_currentUser.UserId.Value.ToString());
        return (user?.Id, user?.FullName ?? user?.Email);
    }

    public async Task LogContractChangeAsync(
        Guid contractId, ChangelogAction action, string? summary = null,
        string? fieldChangesJson = null, string? contextNote = null,
        ContractPhase? phaseAtChange = null, CancellationToken ct = default)
    {
        var (uid, uname) = await ResolveActorAsync();
        _db.ContractChangelogs.Add(new ContractChangelog
        {
            ContractId = contractId,
            EntityType = ChangelogEntityType.Contract,
            EntityId = null,
            Action = action,
            PhaseAtChange = phaseAtChange,
            UserId = uid,
            UserName = uname,
            Summary = summary,
            FieldChangesJson = fieldChangesJson,
            ContextNote = contextNote,
        });
    }

    public async Task LogDetailChangeAsync(
        Guid contractId, Guid detailId, ChangelogAction action,
        string? summary = null, string? fieldChangesJson = null,
        ContractPhase? phaseAtChange = null, CancellationToken ct = default)
    {
        var (uid, uname) = await ResolveActorAsync();
        _db.ContractChangelogs.Add(new ContractChangelog
        {
            ContractId = contractId,
            EntityType = ChangelogEntityType.Detail,
            EntityId = detailId,
            Action = action,
            PhaseAtChange = phaseAtChange,
            UserId = uid,
            UserName = uname,
            Summary = summary,
            FieldChangesJson = fieldChangesJson,
        });
    }

    public async Task LogWorkflowTransitionAsync(
        Guid contractId, ContractPhase fromPhase, ContractPhase toPhase,
        string? comment, CancellationToken ct = default)
    {
        var (uid, uname) = await ResolveActorAsync();
        _db.ContractChangelogs.Add(new ContractChangelog
        {
            ContractId = contractId,
            EntityType = ChangelogEntityType.Workflow,
            EntityId = null,
            Action = ChangelogAction.Transition,
            PhaseAtChange = toPhase,
            UserId = uid,
            UserName = uname ?? "Hệ thống",
            Summary = $"Chuyển phase {fromPhase} → {toPhase}",
            ContextNote = comment,
        });
    }

    public async Task LogCommentAddedAsync(
        Guid contractId, string content, ContractPhase phase, CancellationToken ct = default)
    {
        var (uid, uname) = await ResolveActorAsync();
        _db.ContractChangelogs.Add(new ContractChangelog
        {
            ContractId = contractId,
            EntityType = ChangelogEntityType.Comment,
            EntityId = null,
            Action = ChangelogAction.Insert,
            PhaseAtChange = phase,
            UserId = uid,
            UserName = uname,
            Summary = "Thêm góp ý",
            ContextNote = content.Length > 200 ? content[..200] + "..." : content,
        });
    }

    public async Task LogAttachmentAsync(
        Guid contractId, Guid attachmentId, ChangelogAction action,
        string fileName, ContractPhase phase, CancellationToken ct = default)
    {
        var (uid, uname) = await ResolveActorAsync();
        var verb = action switch
        {
            ChangelogAction.Insert => "Tải lên",
            ChangelogAction.Delete => "Xóa",
            _ => "Cập nhật",
        };
        _db.ContractChangelogs.Add(new ContractChangelog
        {
            ContractId = contractId,
            EntityType = ChangelogEntityType.Attachment,
            EntityId = attachmentId,
            Action = action,
            PhaseAtChange = phase,
            UserId = uid,
            UserName = uname,
            Summary = $"{verb} file: {fileName}",
        });
    }
}
