using Microsoft.EntityFrameworkCore;

public class ExternalIdentifierService : IExternalIdentifierService
{
    private readonly AppDbContext _db;

    public ExternalIdentifierService(AppDbContext db) => _db = db;

    public async Task<Guid?> ResolveInternalIdAsync(
        ExternalResourceType resourceType, string system, string value)
    {
        var row = await _db.ExternalResourceIdentifiers
            .AsNoTracking()
            .FirstOrDefaultAsync(e =>
                e.ResourceType == resourceType &&
                e.System == system &&
                e.Value == value);

        return row?.InternalId;
    }

    public async Task LinkAsync(
        ExternalResourceType resourceType, Guid internalId, string system, string value)
    {
        var existing = await _db.ExternalResourceIdentifiers
            .FirstOrDefaultAsync(e =>
                e.ResourceType == resourceType &&
                e.System == system &&
                e.Value == value);

        if (existing is not null)
        {
            if (existing.InternalId != internalId)
                throw new ConflictException(
                    $"Identifier {system}|{value} is already linked to a different internal resource.",
                    "IDENTIFIER_ALREADY_LINKED");
            return;
        }

        _db.ExternalResourceIdentifiers.Add(new ExternalResourceIdentifier
        {
            Id = Guid.NewGuid(),
            ResourceType = resourceType,
            InternalId = internalId,
            System = system,
            Value = value,
            CreatedAt = DateTimeOffset.UtcNow
        });

        await _db.SaveChangesAsync();
    }

    public async Task<(string System, string Value)?> FindPrimaryIdentifierAsync(
        ExternalResourceType resourceType, Guid internalId, string[] acceptedSystems)
    {
        var rows = await _db.ExternalResourceIdentifiers
            .AsNoTracking()
            .Where(e => e.ResourceType == resourceType && e.InternalId == internalId)
            .ToListAsync();

        foreach (var system in acceptedSystems)
        {
            var match = rows.FirstOrDefault(r => r.System == system);
            if (match is not null)
                return (match.System, match.Value);
        }

        return rows.Count > 0 ? (rows[0].System, rows[0].Value) : null;
    }
}