using System.Text.Json.Serialization;

namespace Synor.Sdk.Database;

/// <summary>
/// Database configuration.
/// </summary>
public record DatabaseConfig
{
    public required string ApiKey { get; init; }
    public string Endpoint { get; init; } = "https://db.synor.io/v1";
    public TimeSpan Timeout { get; init; } = TimeSpan.FromSeconds(60);
    public int Retries { get; init; } = 3;
    public bool Debug { get; init; } = false;
}

/// <summary>
/// A key-value entry.
/// </summary>
public record KeyValue
{
    public required string Key { get; init; }
    public object? Value { get; init; }
    public int? Ttl { get; init; }
    public long? CreatedAt { get; init; }
    public long? UpdatedAt { get; init; }
}

/// <summary>
/// A document.
/// </summary>
public record Document
{
    public required string Id { get; init; }
    public required string Collection { get; init; }
    public required Dictionary<string, object> Data { get; init; }
    public long CreatedAt { get; init; }
    public long UpdatedAt { get; init; }
}

/// <summary>
/// Query parameters for documents.
/// </summary>
public record DocumentQuery
{
    public Dictionary<string, object>? Filter { get; init; }
    public Dictionary<string, int>? Sort { get; init; }
    public int? Limit { get; init; }
    public int? Offset { get; init; }
    public List<string>? Projection { get; init; }
}

/// <summary>
/// A vector entry.
/// </summary>
public record VectorEntry
{
    public required string Id { get; init; }
    public required double[] Vector { get; init; }
    public Dictionary<string, object>? Metadata { get; init; }
}

/// <summary>
/// A search result.
/// </summary>
public record SearchResult
{
    public required string Id { get; init; }
    public double Score { get; init; }
    public double[]? Vector { get; init; }
    public Dictionary<string, object>? Metadata { get; init; }
}

/// <summary>
/// A time series data point.
/// </summary>
public record DataPoint
{
    public long Timestamp { get; init; }
    public double Value { get; init; }
    public Dictionary<string, string>? Tags { get; init; }
}

/// <summary>
/// Time range for queries.
/// </summary>
public record TimeRange
{
    public long Start { get; init; }
    public long End { get; init; }
}

/// <summary>
/// Aggregation settings.
/// </summary>
public record Aggregation
{
    public required string Function { get; init; }  // avg, sum, min, max, count
    public required string Interval { get; init; }  // 1m, 5m, 1h, 1d
}

// Internal response types
internal record KvGetResponse
{
    public object? Value { get; init; }
}

internal record KvListResponse
{
    public List<KeyValue>? Items { get; init; }
}

internal record CreateDocumentResponse
{
    public required string Id { get; init; }
}

internal record DocumentListResponse
{
    public List<Document>? Documents { get; init; }
}

internal record SearchListResponse
{
    public List<SearchResult>? Results { get; init; }
}

internal record DataPointListResponse
{
    public List<DataPoint>? Points { get; init; }
}

internal record HealthResponse
{
    public required string Status { get; init; }
}

/// <summary>
/// Database exception.
/// </summary>
public class DatabaseException : Exception
{
    public string? Code { get; }
    public int StatusCode { get; }

    public DatabaseException(string message, string? code = null, int statusCode = 0)
        : base(message)
    {
        Code = code;
        StatusCode = statusCode;
    }
}
