using ZB.MOM.WW.ScadaBridge.Commons.Entities.ExternalSystems;

namespace ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Repositories;

public interface IExternalSystemRepository
{
    // ExternalSystemDefinition
    /// <summary>
    /// Gets an external system definition by ID.
    /// </summary>
    /// <param name="id">The external system ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The external system definition, or null if not found.</returns>
    Task<ExternalSystemDefinition?> GetExternalSystemByIdAsync(int id, CancellationToken cancellationToken = default);

    /// <summary>
    /// Returns the external system with the given name, or <c>null</c> if no such
    /// system exists. A name-keyed lookup so hot-path resolution (e.g. a script's
    /// <c>ExternalSystem.Call()</c>) does not have to fetch every system and filter
    /// in memory on each call.
    /// </summary>
    /// <param name="name">The external system name.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The external system definition, or null if not found.</returns>
    Task<ExternalSystemDefinition?> GetExternalSystemByNameAsync(string name, CancellationToken cancellationToken = default);

    /// <summary>
    /// Gets all external system definitions.
    /// </summary>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A read-only list of external system definitions.</returns>
    Task<IReadOnlyList<ExternalSystemDefinition>> GetAllExternalSystemsAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// Adds a new external system definition.
    /// </summary>
    /// <param name="definition">The external system definition to add.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task AddExternalSystemAsync(ExternalSystemDefinition definition, CancellationToken cancellationToken = default);

    /// <summary>
    /// Updates an existing external system definition.
    /// </summary>
    /// <param name="definition">The external system definition to update.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task UpdateExternalSystemAsync(ExternalSystemDefinition definition, CancellationToken cancellationToken = default);

    /// <summary>
    /// Deletes an external system definition by ID.
    /// </summary>
    /// <param name="id">The external system ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task DeleteExternalSystemAsync(int id, CancellationToken cancellationToken = default);

    // ExternalSystemMethod
    /// <summary>
    /// Gets an external system method by ID.
    /// </summary>
    /// <param name="id">The method ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The external system method, or null if not found.</returns>
    Task<ExternalSystemMethod?> GetExternalSystemMethodByIdAsync(int id, CancellationToken cancellationToken = default);

    /// <summary>
    /// Returns the method with the given name belonging to the given external system,
    /// or <c>null</c> if no such method exists. A name-keyed lookup so hot-path
    /// resolution does not have to fetch every method of the system and filter in
    /// memory on each call.
    /// </summary>
    /// <param name="externalSystemId">The external system ID.</param>
    /// <param name="methodName">The method name.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The external system method, or null if not found.</returns>
    Task<ExternalSystemMethod?> GetMethodByNameAsync(int externalSystemId, string methodName, CancellationToken cancellationToken = default);

    /// <summary>
    /// Gets all methods for a given external system.
    /// </summary>
    /// <param name="externalSystemId">The external system ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A read-only list of external system methods.</returns>
    Task<IReadOnlyList<ExternalSystemMethod>> GetMethodsByExternalSystemIdAsync(int externalSystemId, CancellationToken cancellationToken = default);

    /// <summary>
    /// Adds a new external system method.
    /// </summary>
    /// <param name="method">The external system method to add.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task AddExternalSystemMethodAsync(ExternalSystemMethod method, CancellationToken cancellationToken = default);

    /// <summary>
    /// Updates an existing external system method.
    /// </summary>
    /// <param name="method">The external system method to update.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task UpdateExternalSystemMethodAsync(ExternalSystemMethod method, CancellationToken cancellationToken = default);

    /// <summary>
    /// Deletes an external system method by ID.
    /// </summary>
    /// <param name="id">The method ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task DeleteExternalSystemMethodAsync(int id, CancellationToken cancellationToken = default);

    // DatabaseConnectionDefinition
    /// <summary>
    /// Gets a database connection definition by ID.
    /// </summary>
    /// <param name="id">The database connection ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The database connection definition, or null if not found.</returns>
    Task<DatabaseConnectionDefinition?> GetDatabaseConnectionByIdAsync(int id, CancellationToken cancellationToken = default);

    /// <summary>
    /// Returns the database connection definition with the given name, or <c>null</c>
    /// if no such connection exists. A name-keyed lookup so hot-path resolution (e.g.
    /// a script's <c>Database.Connection()</c> / <c>Database.CachedWrite()</c>) does
    /// not have to fetch every connection and filter in memory on each call.
    /// </summary>
    /// <param name="name">The database connection name.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The database connection definition, or null if not found.</returns>
    Task<DatabaseConnectionDefinition?> GetDatabaseConnectionByNameAsync(string name, CancellationToken cancellationToken = default);

    /// <summary>
    /// Gets all database connection definitions.
    /// </summary>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A read-only list of database connection definitions.</returns>
    Task<IReadOnlyList<DatabaseConnectionDefinition>> GetAllDatabaseConnectionsAsync(CancellationToken cancellationToken = default);

    /// <summary>
    /// Adds a new database connection definition.
    /// </summary>
    /// <param name="definition">The database connection definition to add.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task AddDatabaseConnectionAsync(DatabaseConnectionDefinition definition, CancellationToken cancellationToken = default);

    /// <summary>
    /// Updates an existing database connection definition.
    /// </summary>
    /// <param name="definition">The database connection definition to update.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task UpdateDatabaseConnectionAsync(DatabaseConnectionDefinition definition, CancellationToken cancellationToken = default);

    /// <summary>
    /// Deletes a database connection definition by ID.
    /// </summary>
    /// <param name="id">The database connection ID.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task DeleteDatabaseConnectionAsync(int id, CancellationToken cancellationToken = default);

    /// <summary>
    /// Saves pending changes to the repository.
    /// </summary>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>The number of entities saved.</returns>
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
