using Microsoft.EntityFrameworkCore;
using ZB.MOM.WW.OtOpcUa.Configuration;
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;

namespace ZB.MOM.WW.OtOpcUa.Admin.Services;

/// <summary>Draft-generation CRUD for <see cref="ScriptedAlarm"/> rows.</summary>
public sealed class ScriptedAlarmService(OtOpcUaConfigDbContext db)
{
    public Task<List<ScriptedAlarm>> ListAsync(long generationId, CancellationToken ct) =>
        db.ScriptedAlarms.AsNoTracking()
            .Where(a => a.GenerationId == generationId)
            .OrderBy(a => a.EquipmentId).ThenBy(a => a.Name)
            .ToListAsync(ct);

    public async Task<ScriptedAlarm> AddAsync(
        long generationId, string equipmentId, string name, string alarmType,
        int severity, string messageTemplate, string predicateScriptId,
        bool historizeToAveva, bool retain, CancellationToken ct)
    {
        var a = new ScriptedAlarm
        {
            GenerationId = generationId,
            ScriptedAlarmId = $"sal-{Guid.NewGuid():N}"[..20],
            EquipmentId = equipmentId,
            Name = name,
            AlarmType = alarmType,
            Severity = severity,
            MessageTemplate = messageTemplate,
            PredicateScriptId = predicateScriptId,
            HistorizeToAveva = historizeToAveva,
            Retain = retain,
        };
        db.ScriptedAlarms.Add(a);
        await db.SaveChangesAsync(ct);
        return a;
    }

    public async Task DeleteAsync(long generationId, string scriptedAlarmId, CancellationToken ct)
    {
        var a = await db.ScriptedAlarms.FirstOrDefaultAsync(x => x.GenerationId == generationId && x.ScriptedAlarmId == scriptedAlarmId, ct);
        if (a is null) return;
        db.ScriptedAlarms.Remove(a);
        await db.SaveChangesAsync(ct);
    }

    /// <summary>
    ///     Returns the persistent state row (ack/confirm/shelve) for this alarm identity —
    ///     alarm state is NOT generation-scoped per Phase 7 plan decision #14, so the
    ///     lookup is by <see cref="ScriptedAlarm.ScriptedAlarmId"/> only.
    /// </summary>
    public Task<ScriptedAlarmState?> GetStateAsync(string scriptedAlarmId, CancellationToken ct) =>
        db.ScriptedAlarmStates.AsNoTracking()
            .FirstOrDefaultAsync(s => s.ScriptedAlarmId == scriptedAlarmId, ct);
}
