using ZB.MOM.WW.ScadaBridge.Commons.Types;

namespace ZB.MOM.WW.ScadaBridge.CentralUI.ScriptAnalysis;

/// <summary>
/// Globals type seen by inbound API method scripts during analysis. Mirrors
/// the surface the runtime exposes (see ZB.MOM.WW.ScadaBridge.InboundAPI.InboundScriptContext
/// and RouteHelper). The methods here are never invoked — Roslyn only reads
/// their signatures to type-check API method scripts and offer completions.
/// </summary>
public class InboundScriptHost
{
    /// <summary>
    /// The request parameters passed to the inbound API method.
    /// </summary>
    public ScriptParameters Parameters { get; init; } = new();

    /// <summary>
    /// The route helper for accessing target instances.
    /// </summary>
    public RouteHelper Route { get; } = new();

    /// <summary>
    /// Scoped, parameterized database access. Editor mirror of
    /// ZB.MOM.WW.ScadaBridge.InboundAPI.InboundDatabaseHelper — its
    /// signatures must match the runtime helper so a script using <c>Database.*</c>
    /// type-checks during analysis.
    /// </summary>
    public DatabaseAccessor Database { get; } = new();

    /// <summary>
    /// The cancellation token for the operation.
    /// </summary>
    public System.Threading.CancellationToken CancellationToken { get; }

    /// <summary>Editor mirror of ZB.MOM.WW.ScadaBridge.InboundAPI.InboundDatabaseHelper.</summary>
    public class DatabaseAccessor
    {
        /// <summary>First column of the first row as <typeparamref name="T"/> (default if no rows).</summary>
        /// <typeparam name="T">The scalar result type.</typeparam>
        /// <param name="connectionName">A configured database connection name.</param>
        /// <param name="sql">The SQL statement; values supplied via <paramref name="parameters"/>.</param>
        /// <param name="parameters">Optional anonymous object of bound parameters.</param>
        /// <returns>A task that resolves to the scalar, or default.</returns>
        public System.Threading.Tasks.Task<T?> QuerySingleAsync<T>(
            string connectionName, string sql, object? parameters = null) =>
            System.Threading.Tasks.Task.FromResult<T?>(default);

        /// <summary>All rows as case-insensitive column→value dictionaries.</summary>
        /// <param name="connectionName">A configured database connection name.</param>
        /// <param name="sql">The SQL statement; values supplied via <paramref name="parameters"/>.</param>
        /// <param name="parameters">Optional anonymous object of bound parameters.</param>
        /// <returns>A task that resolves to the result rows.</returns>
        public System.Threading.Tasks.Task<IReadOnlyList<IReadOnlyDictionary<string, object?>>> QueryAsync(
            string connectionName, string sql, object? parameters = null) =>
            System.Threading.Tasks.Task.FromResult<IReadOnlyList<IReadOnlyDictionary<string, object?>>>(
                new List<IReadOnlyDictionary<string, object?>>());

        /// <summary>Runs a write statement; returns rows affected.</summary>
        /// <param name="connectionName">A configured database connection name.</param>
        /// <param name="sql">The SQL statement; values supplied via <paramref name="parameters"/>.</param>
        /// <param name="parameters">Optional anonymous object of bound parameters.</param>
        /// <returns>A task that resolves to the number of rows affected.</returns>
        public System.Threading.Tasks.Task<int> ExecuteAsync(
            string connectionName, string sql, object? parameters = null) =>
            System.Threading.Tasks.Task.FromResult(0);
    }

    /// <summary>Editor mirror of ZB.MOM.WW.ScadaBridge.InboundAPI.RouteHelper.</summary>
    public class RouteHelper
    {
        /// <summary>
        /// Targets a specific instance for method invocation.
        /// </summary>
        /// <param name="instanceCode">The instance code to target.</param>
        /// <returns>A <see cref="RouteTarget"/> scoped to the specified instance.</returns>
        public RouteTarget To(string instanceCode) => new();
    }

    /// <summary>Editor mirror of ZB.MOM.WW.ScadaBridge.InboundAPI.RouteTarget.</summary>
    public class RouteTarget
    {
        /// <summary>
        /// Calls a script on the target instance.
        /// </summary>
        /// <param name="scriptName">The name of the script to call.</param>
        /// <param name="parameters">Optional parameters to pass to the script.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task that resolves to the script's return value, or null.</returns>
        public System.Threading.Tasks.Task<object?> Call(
            string scriptName,
            object? parameters = null,
            System.Threading.CancellationToken cancellationToken = default) =>
            System.Threading.Tasks.Task.FromResult<object?>(null);

        /// <summary>
        /// Gets an attribute value from the target instance.
        /// </summary>
        /// <param name="attributeName">The name of the attribute to retrieve.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task that resolves to the attribute value, or null if not found.</returns>
        public System.Threading.Tasks.Task<object?> GetAttribute(
            string attributeName,
            System.Threading.CancellationToken cancellationToken = default) =>
            System.Threading.Tasks.Task.FromResult<object?>(null);

        /// <summary>
        /// Gets multiple attribute values from the target instance.
        /// </summary>
        /// <param name="attributeNames">The names of the attributes to retrieve.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task that resolves to a dictionary mapping attribute names to their values.</returns>
        public System.Threading.Tasks.Task<IReadOnlyDictionary<string, object?>> GetAttributes(
            IEnumerable<string> attributeNames,
            System.Threading.CancellationToken cancellationToken = default) =>
            System.Threading.Tasks.Task.FromResult<IReadOnlyDictionary<string, object?>>(
                new Dictionary<string, object?>());

        /// <summary>
        /// Sets a single attribute value on the target instance.
        /// </summary>
        /// <param name="attributeName">The name of the attribute to set.</param>
        /// <param name="value">The value to set.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task representing the asynchronous operation.</returns>
        public System.Threading.Tasks.Task SetAttribute(
            string attributeName,
            string value,
            System.Threading.CancellationToken cancellationToken = default) =>
            System.Threading.Tasks.Task.CompletedTask;

        /// <summary>
        /// Sets multiple attribute values on the target instance.
        /// </summary>
        /// <param name="attributeValues">Dictionary of attribute names to values.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task representing the asynchronous operation.</returns>
        public System.Threading.Tasks.Task SetAttributes(
            IReadOnlyDictionary<string, string> attributeValues,
            System.Threading.CancellationToken cancellationToken = default) =>
            System.Threading.Tasks.Task.CompletedTask;

        /// <summary>
        /// Waits until a named attribute on the target instance reaches the specified value,
        /// or until the timeout elapses.
        /// </summary>
        /// <param name="attributeName">The name of the attribute to watch.</param>
        /// <param name="targetValue">The value to wait for.</param>
        /// <param name="timeout">Maximum time to wait before returning false.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task that resolves to true if the attribute reached the target value within the timeout, false otherwise.</returns>
        public System.Threading.Tasks.Task<bool> WaitForAttribute(
            string attributeName,
            object? targetValue,
            System.TimeSpan timeout,
            System.Threading.CancellationToken cancellationToken = default) =>
            System.Threading.Tasks.Task.FromResult(false);
    }
}
