using CliFx.Attributes;
using ZB.MOM.WW.OtOpcUa.Driver.Cli.Common;

namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Cli;

/// <summary>
///     Base for every AB CIP CLI command. Carries the libplctag endpoint options
///     (<c>--gateway</c> + <c>--family</c>) and exposes <see cref="BuildOptions"/> so each
///     command can synthesise an <see cref="AbCipDriverOptions"/> from CLI flags + its own
///     tag list.
/// </summary>
public abstract class AbCipCommandBase : DriverCommandBase
{
    [CommandOption("gateway", 'g', Description =
        "Canonical AB CIP gateway: ab://host[:port]/cip-path. Port defaults to 44818 " +
        "(EtherNet/IP). cip-path is family-specific: ControlLogix / CompactLogix need " +
        "'1,0' to reach slot 0 of the CPU chassis; Micro800 takes an empty path; " +
        "GuardLogix typically '1,0' same as ControlLogix.",
        IsRequired = true)]
    public string Gateway { get; init; } = default!;

    [CommandOption("family", 'f', Description =
        "ControlLogix / CompactLogix / Micro800 / GuardLogix (default ControlLogix).")]
    public AbCipPlcFamily Family { get; init; } = AbCipPlcFamily.ControlLogix;

    [CommandOption("timeout-ms", Description = "Per-operation timeout in ms (default 5000).")]
    public int TimeoutMs { get; init; } = 5000;

    /// <inheritdoc />
    public override TimeSpan Timeout
    {
        get => TimeSpan.FromMilliseconds(TimeoutMs);
        init { /* driven by TimeoutMs */ }
    }

    /// <summary>
    ///     Build an <see cref="AbCipDriverOptions"/> with the device + tag list a subclass
    ///     supplies. Probe + alarm projection are disabled — CLI runs are one-shot; the
    ///     probe loop would race the operator's own reads.
    /// </summary>
    protected AbCipDriverOptions BuildOptions(IReadOnlyList<AbCipTagDefinition> tags) => new()
    {
        Devices = [new AbCipDeviceOptions(
            HostAddress: Gateway,
            PlcFamily: Family,
            DeviceName: $"cli-{Family}")],
        Tags = tags,
        Timeout = Timeout,
        Probe = new AbCipProbeOptions { Enabled = false },
        EnableControllerBrowse = false,
        EnableAlarmProjection = false,
    };

    /// <summary>
    ///     Short instance id used in Serilog output so operators running the CLI against
    ///     multiple gateways in parallel can distinguish the logs.
    /// </summary>
    protected string DriverInstanceId => $"abcip-cli-{Gateway}";
}
