using ZB.MOM.WW.ScadaBridge.Commons.Entities.Deployment;
using ZB.MOM.WW.ScadaBridge.Commons.Entities.Instances;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Enums;

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

public interface IDeploymentManagerRepository
{
    // DeploymentRecord
    /// <summary>
    /// Gets a deployment record by its ID.
    /// </summary>
    /// <param name="id">The deployment record ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The deployment record, or null if not found.</returns>
    Task<DeploymentRecord?> GetDeploymentRecordByIdAsync(int id, CancellationToken cancellationToken = default);
    /// <summary>
    /// Gets all deployment records.
    /// </summary>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A read-only list of all deployment records.</returns>
    Task<IReadOnlyList<DeploymentRecord>> GetAllDeploymentRecordsAsync(CancellationToken cancellationToken = default);
    /// <summary>
    /// Gets all deployment records for a specific instance.
    /// </summary>
    /// <param name="instanceId">The instance ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A read-only list of deployment records for the instance.</returns>
    Task<IReadOnlyList<DeploymentRecord>> GetDeploymentsByInstanceIdAsync(int instanceId, CancellationToken cancellationToken = default);
    /// <summary>
    /// Gets the current deployment status for an instance.
    /// </summary>
    /// <param name="instanceId">The instance ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The current deployment record, or null if no deployment exists.</returns>
    Task<DeploymentRecord?> GetCurrentDeploymentStatusAsync(int instanceId, CancellationToken cancellationToken = default);
    /// <summary>
    /// Gets a deployment record by deployment ID.
    /// </summary>
    /// <param name="deploymentId">The deployment ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The deployment record, or null if not found.</returns>
    Task<DeploymentRecord?> GetDeploymentByDeploymentIdAsync(string deploymentId, CancellationToken cancellationToken = default);
    /// <summary>
    /// Adds a new deployment record.
    /// </summary>
    /// <param name="record">The deployment record to add.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task AddDeploymentRecordAsync(DeploymentRecord record, CancellationToken cancellationToken = default);
    /// <summary>
    /// Updates an existing deployment record.
    /// </summary>
    /// <param name="record">The deployment record to update.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task UpdateDeploymentRecordAsync(DeploymentRecord record, CancellationToken cancellationToken = default);
    /// <summary>
    /// Deletes a deployment record by ID, enforcing optimistic concurrency against the
    /// supplied <paramref name="expectedRowVersion"/>. The caller MUST pass the
    /// <c>RowVersion</c> it last observed on the record so EF emits
    /// <c>DELETE ... WHERE Id = @id AND RowVersion = @prior</c>. A concurrent edit
    /// surfaces as <see cref="Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException"/>
    /// on <see cref="SaveChangesAsync(CancellationToken)"/>, matching the documented
    /// "Optimistic concurrency is used on deployment status records" design rule.
    /// </summary>
    /// <param name="id">The deployment record ID to delete.</param>
    /// <param name="expectedRowVersion">The RowVersion the caller observed; used as the optimistic-concurrency token.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task DeleteDeploymentRecordAsync(int id, byte[] expectedRowVersion, CancellationToken cancellationToken = default);

    // SystemArtifactDeploymentRecord
    /// <summary>
    /// Gets a system artifact deployment record by ID.
    /// </summary>
    /// <param name="id">The system artifact deployment record ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The system artifact deployment record, or null if not found.</returns>
    Task<SystemArtifactDeploymentRecord?> GetSystemArtifactDeploymentByIdAsync(int id, CancellationToken cancellationToken = default);
    /// <summary>
    /// Gets all system artifact deployment records.
    /// </summary>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A read-only list of all system artifact deployment records.</returns>
    Task<IReadOnlyList<SystemArtifactDeploymentRecord>> GetAllSystemArtifactDeploymentsAsync(CancellationToken cancellationToken = default);
    /// <summary>
    /// Adds a new system artifact deployment record.
    /// </summary>
    /// <param name="record">The system artifact deployment record to add.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task AddSystemArtifactDeploymentAsync(SystemArtifactDeploymentRecord record, CancellationToken cancellationToken = default);
    /// <summary>
    /// Updates an existing system artifact deployment record.
    /// </summary>
    /// <param name="record">The system artifact deployment record to update.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task UpdateSystemArtifactDeploymentAsync(SystemArtifactDeploymentRecord record, CancellationToken cancellationToken = default);
    /// <summary>
    /// Deletes a system artifact deployment record by ID.
    /// </summary>
    /// <param name="id">The system artifact deployment record ID to delete.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task DeleteSystemArtifactDeploymentAsync(int id, CancellationToken cancellationToken = default);

    // WP-8: DeployedConfigSnapshot
    /// <summary>
    /// Gets the deployed config snapshot for an instance.
    /// </summary>
    /// <param name="instanceId">The instance ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The deployed config snapshot, or null if not found.</returns>
    Task<DeployedConfigSnapshot?> GetDeployedSnapshotByInstanceIdAsync(int instanceId, CancellationToken cancellationToken = default);
    /// <summary>
    /// Adds a new deployed config snapshot.
    /// </summary>
    /// <param name="snapshot">The deployed config snapshot to add.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task AddDeployedSnapshotAsync(DeployedConfigSnapshot snapshot, CancellationToken cancellationToken = default);
    /// <summary>
    /// Updates an existing deployed config snapshot.
    /// </summary>
    /// <param name="snapshot">The deployed config snapshot to update.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task UpdateDeployedSnapshotAsync(DeployedConfigSnapshot snapshot, CancellationToken cancellationToken = default);
    /// <summary>
    /// Deletes the deployed config snapshot for an instance.
    /// </summary>
    /// <param name="instanceId">The instance ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task DeleteDeployedSnapshotAsync(int instanceId, CancellationToken cancellationToken = default);

    // Instance lookups for deployment pipeline
    /// <summary>
    /// Gets an instance by ID.
    /// </summary>
    /// <param name="instanceId">The instance ID.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The instance, or null if not found.</returns>
    Task<Instance?> GetInstanceByIdAsync(int instanceId, CancellationToken cancellationToken = default);
    /// <summary>
    /// Gets an instance by unique name.
    /// </summary>
    /// <param name="uniqueName">The unique instance name.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>The instance, or null if not found.</returns>
    Task<Instance?> GetInstanceByUniqueNameAsync(string uniqueName, CancellationToken cancellationToken = default);
    /// <summary>
    /// Updates an instance.
    /// </summary>
    /// <param name="instance">The instance to update.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task UpdateInstanceAsync(Instance instance, CancellationToken cancellationToken = default);

    /// <summary>
    /// Removes an instance and everything that depends on it: deployment
    /// records, deployed config snapshot, attribute/alarm overrides, and
    /// connection bindings.
    /// </summary>
    /// <param name="instanceId">The instance ID to delete.</param>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the asynchronous operation.</returns>
    Task DeleteInstanceAsync(int instanceId, CancellationToken cancellationToken = default);

    /// <summary>
    /// Saves all pending changes to the database.
    /// </summary>
    /// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
    /// <returns>A task representing the number of entities saved.</returns>
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
