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

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

/// <summary>
///     Base for every FOCAS CLI command. Carries the CNC endpoint options
///     (host / port / series) + exposes <see cref="BuildOptions"/> so each command
///     can synthesise a <see cref="FocasDriverOptions"/> with one device + one tag.
/// </summary>
public abstract class FocasCommandBase : DriverCommandBase
{
    [CommandOption("cnc-host", 'h', Description =
        "CNC IP address or hostname. FOCAS-over-EIP listens on port 8193 by default.",
        IsRequired = true)]
    public string CncHost { get; init; } = default!;

    [CommandOption("cnc-port", 'p', Description = "FOCAS TCP port (default 8193).")]
    public int CncPort { get; init; } = 8193;

    [CommandOption("series", 's', Description =
        "CNC series: Unknown / Zero_i_D / Zero_i_F / Zero_i_MF / Zero_i_TF / Sixteen_i / " +
        "Thirty_i / ThirtyOne_i / ThirtyTwo_i / PowerMotion_i (default Unknown).")]
    public FocasCncSeries Series { get; init; } = FocasCncSeries.Unknown;

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

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

    /// <summary>Canonical FOCAS host-address string, shape <c>focas://host:port</c>.</summary>
    protected string HostAddress => $"focas://{CncHost}:{CncPort}";

    /// <summary>
    ///     Build a <see cref="FocasDriverOptions"/> with the CNC target this base collected
    ///     + the tag list a subclass supplies. Probe disabled; the default
    ///     <see cref="FwlibFocasClientFactory"/> attempts <c>Fwlib32.dll</c> P/Invoke, which
    ///     throws <see cref="DllNotFoundException"/> at first call when the DLL is absent —
    ///     surfaced through the driver as <c>BadCommunicationError</c>.
    /// </summary>
    protected FocasDriverOptions BuildOptions(IReadOnlyList<FocasTagDefinition> tags) => new()
    {
        Devices = [new FocasDeviceOptions(
            HostAddress: HostAddress,
            DeviceName: $"cli-{CncHost}:{CncPort}",
            Series: Series)],
        Tags = tags,
        Timeout = Timeout,
        Probe = new FocasProbeOptions { Enabled = false },
    };

    protected string DriverInstanceId => $"focas-cli-{CncHost}:{CncPort}";
}
