using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Sites;

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

/// <summary>
/// Repository interface for site and data connection management.
/// </summary>
public interface ISiteRepository
{
    // Sites
    /// <summary>Retrieves a site by its ID.</summary>
    /// <param name="id">The site primary key.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to the matching <see cref="Site"/>, or <c>null</c> if not found.</returns>
    Task<Site?> GetSiteByIdAsync(int id, CancellationToken cancellationToken = default);
    /// <summary>Retrieves a site by its identifier.</summary>
    /// <param name="siteIdentifier">The unique site identifier string.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to the matching <see cref="Site"/>, or <c>null</c> if not found.</returns>
    Task<Site?> GetSiteByIdentifierAsync(string siteIdentifier, CancellationToken cancellationToken = default);
    /// <summary>Retrieves all sites.</summary>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to a read-only list of all <see cref="Site"/> entities.</returns>
    Task<IReadOnlyList<Site>> GetAllSitesAsync(CancellationToken cancellationToken = default);
    /// <summary>Adds a new site.</summary>
    /// <param name="site">The site entity to add.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task AddSiteAsync(Site site, CancellationToken cancellationToken = default);
    /// <summary>Updates an existing site.</summary>
    /// <param name="site">The site entity with updated values.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task UpdateSiteAsync(Site site, CancellationToken cancellationToken = default);
    /// <summary>Deletes a site.</summary>
    /// <param name="id">The site primary key.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task DeleteSiteAsync(int id, CancellationToken cancellationToken = default);

    // Data Connections
    /// <summary>Retrieves a data connection by its ID.</summary>
    /// <param name="id">The data connection primary key.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to the matching <see cref="DataConnection"/>, or <c>null</c> if not found.</returns>
    Task<DataConnection?> GetDataConnectionByIdAsync(int id, CancellationToken cancellationToken = default);
    /// <summary>Retrieves all data connections.</summary>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to a read-only list of all <see cref="DataConnection"/> entities.</returns>
    Task<IReadOnlyList<DataConnection>> GetAllDataConnectionsAsync(CancellationToken cancellationToken = default);
    /// <summary>Retrieves all data connections for a site.</summary>
    /// <param name="siteId">The site primary key to filter by.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to a read-only list of <see cref="DataConnection"/> entities for the given site.</returns>
    Task<IReadOnlyList<DataConnection>> GetDataConnectionsBySiteIdAsync(int siteId, CancellationToken cancellationToken = default);
    /// <summary>Adds a new data connection.</summary>
    /// <param name="connection">The data connection entity to add.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task AddDataConnectionAsync(DataConnection connection, CancellationToken cancellationToken = default);
    /// <summary>Updates an existing data connection.</summary>
    /// <param name="connection">The data connection entity with updated values.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task UpdateDataConnectionAsync(DataConnection connection, CancellationToken cancellationToken = default);
    /// <summary>Deletes a data connection.</summary>
    /// <param name="id">The data connection primary key.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that represents the asynchronous operation.</returns>
    Task DeleteDataConnectionAsync(int id, CancellationToken cancellationToken = default);

    // Instances (for deletion / move constraint checks)
    /// <summary>Retrieves all instances deployed to a site.</summary>
    /// <param name="siteId">The site primary key to filter by.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to a read-only list of <see cref="Instance"/> entities for the given site.</returns>
    Task<IReadOnlyList<Instance>> GetInstancesBySiteIdAsync(int siteId, CancellationToken cancellationToken = default);

    /// <summary>
    /// Retrieves the distinct instances that have at least one
    /// <see cref="InstanceConnectionBinding"/> referencing the given data
    /// connection. Used as the primary data-integrity guard for moving a
    /// connection between sites: a bound connection cannot leave its site
    /// without orphaning the (site-scoped) binding, so the move handler rejects
    /// the move and names the returned instances as blockers.
    /// </summary>
    /// <param name="dataConnectionId">The data connection primary key.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to the distinct referencing <see cref="Instance"/> entities (empty when none).</returns>
    Task<IReadOnlyList<Instance>> GetInstancesReferencingDataConnectionAsync(int dataConnectionId, CancellationToken cancellationToken = default);

    /// <summary>
    /// Retrieves a site's instances with their
    /// <see cref="Instance.NativeAlarmSourceOverrides"/> eagerly loaded. Purpose-built
    /// for the move-data-connection guard, which must scan source-site instance
    /// overrides for name-based connection references without paying the eager-load
    /// cost on the hot-path <see cref="GetInstancesBySiteIdAsync"/>.
    /// </summary>
    /// <param name="siteId">The site primary key to filter by.</param>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to the site's <see cref="Instance"/> entities with overrides loaded (empty when none).</returns>
    Task<IReadOnlyList<Instance>> GetInstancesWithNativeAlarmOverridesBySiteIdAsync(int siteId, CancellationToken cancellationToken = default);

    /// <summary>Saves all pending changes to the database.</summary>
    /// <param name="cancellationToken">Cancellation token.</param>
    /// <returns>A task that resolves to the number of state entries written to the database.</returns>
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
