# TASK 3.1: Create IMonitorSpecRepository Interface

## Summary

Define the repository interface for managing `MonitorSpec` entities in the Data project. This abstraction allows for different storage implementations and simplifies testing. Placing it in the Data project keeps repository contracts co-located with entities and the DbContext.

## Dependencies

- TASK 1.1 (MonitorSpec entity must exist)

## Files to Create

### 1. `backend/Kds.Ai.Data/Repositories/IMonitorSpecRepository.cs`

```csharp
using Kds.Ai.Data.Entities;
using Kds.Ai.Data.Enums;

namespace Kds.Ai.Data.Repositories;

/// <summary>
/// Repository for managing MonitorSpec entities
/// </summary>
public interface IMonitorSpecRepository
{
    /// <summary>
    /// Get a monitor spec by its ID
    /// </summary>
    Task<MonitorSpec?> GetByIdAsync(Guid id, CancellationToken ct = default);
    
    /// <summary>
    /// Get a monitor spec by name
    /// </summary>
    Task<MonitorSpec?> GetByNameAsync(string name, CancellationToken ct = default);
    
    /// <summary>
    /// Get all monitor specs in a given state
    /// </summary>
    Task<IReadOnlyList<MonitorSpec>> GetByStateAsync(
        MonitorState state, 
        CancellationToken ct = default);
    
    /// <summary>
    /// Get all active monitor specs (State == Active)
    /// </summary>
    Task<IReadOnlyList<MonitorSpec>> GetActiveAsync(CancellationToken ct = default);
    
    /// <summary>
    /// Get all monitor specs regardless of state
    /// </summary>
    Task<IReadOnlyList<MonitorSpec>> GetAllAsync(CancellationToken ct = default);
    
    /// <summary>
    /// Create a new monitor spec
    /// </summary>
    /// <param name="spec">The monitor spec to create</param>
    /// <param name="ct">Cancellation token</param>
    /// <returns>The created monitor spec with generated ID</returns>
    Task<MonitorSpec> CreateAsync(MonitorSpec spec, CancellationToken ct = default);
    
    /// <summary>
    /// Update an existing monitor spec
    /// </summary>
    /// <param name="spec">The monitor spec to update</param>
    /// <param name="ct">Cancellation token</param>
    /// <returns>The updated monitor spec</returns>
    Task<MonitorSpec> UpdateAsync(MonitorSpec spec, CancellationToken ct = default);
    
    /// <summary>
    /// Update the last run timestamp for a monitor spec
    /// </summary>
    Task UpdateLastRunAsync(Guid id, DateTimeOffset lastRunAt, CancellationToken ct = default);
    
    /// <summary>
    /// Transition a monitor spec to a new state
    /// </summary>
    Task SetStateAsync(Guid id, MonitorState state, CancellationToken ct = default);
    
    /// <summary>
    /// Delete a monitor spec
    /// </summary>
    /// <returns>True if deleted, false if not found</returns>
    Task<bool> DeleteAsync(Guid id, CancellationToken ct = default);
    
    /// <summary>
    /// Check if a monitor spec with the given name already exists
    /// </summary>
    Task<bool> ExistsByNameAsync(string name, CancellationToken ct = default);
}
```

## Interface Design Rationale

### Why Kds.Ai.Data?

The repository interface belongs in the Data project because:

- It operates on `MonitorSpec` entities that are defined in the same project
- It depends only on types from the Data project (`MonitorSpec`, `MonitorState`, `KdsAiDbContext`)
- Any project that references `Kds.Ai.Data` can consume `IMonitorSpecRepository` without taking a dependency on `Kds.Ai.AnomalyDetector`
- The EF Core implementation (TASK 3.2) naturally lives alongside the DbContext it uses

### Query Methods

- `GetByIdAsync`: Standard lookup by primary key
- `GetByNameAsync`: Lookup by unique name (since MonitorSpec no longer has StoreGuid/MonitorType, name is the human identifier)
- `GetActiveAsync`: For scheduler to find monitors to run
- `GetByStateAsync`: For management/filtering by lifecycle state
- `GetAllAsync`: For listing all monitors

### Command Methods

- `CreateAsync`: Returns entity with generated ID
- `UpdateAsync`: Full entity update
- `UpdateLastRunAsync`: Partial update for run tracking (common operation)
- `SetStateAsync`: Transition between Draft/Active/Paused/Archived
- `DeleteAsync`: Returns bool for existence check

### Existence Check

- `ExistsByNameAsync`: Prevent duplicate monitor names

## Acceptance Criteria

- [ ] `IMonitorSpecRepository` interface created in `Kds.Ai.Data/Repositories/`
- [ ] Namespace is `Kds.Ai.Data.Repositories`
- [ ] All CRUD methods defined
- [ ] Query methods use `MonitorState` enum (not `bool IsEnabled`)
- [ ] No references to `StoreGuid` or `MonitorType` properties
- [ ] Async pattern with CancellationToken on all methods
- [ ] XML documentation complete
- [ ] Solution builds without errors

## Notes

- Implementation in TASK 3.2
- Consider adding pagination for `GetActiveAsync` if many monitors expected
- The interface doesn't include `Runs` navigation property loading - use explicit includes in implementation if needed
