package io.synor.database;

import java.util.Map;

/**
 * Database SDK Types for Java.
 */
public class Types {
    // This class exists for organizational purposes.
    // Individual types are defined below.
}

// ==================== Config ====================

class DatabaseConfig {
    private final String apiKey;
    private final String endpoint;
    private final int timeoutSecs;
    private final int retries;
    private final boolean debug;

    public DatabaseConfig(String apiKey) {
        this(apiKey, "https://db.synor.io/v1", 60, 3, false);
    }

    public DatabaseConfig(String apiKey, String endpoint, int timeoutSecs, int retries, boolean debug) {
        this.apiKey = apiKey;
        this.endpoint = endpoint;
        this.timeoutSecs = timeoutSecs;
        this.retries = retries;
        this.debug = debug;
    }

    public String getApiKey() { return apiKey; }
    public String getEndpoint() { return endpoint; }
    public int getTimeoutSecs() { return timeoutSecs; }
    public int getRetries() { return retries; }
    public boolean isDebug() { return debug; }
}

// ==================== Key-Value Types ====================

class KeyValue {
    private String key;
    private Object value;
    private Long ttl;
    private Long createdAt;
    private Long updatedAt;

    public String getKey() { return key; }
    public Object getValue() { return value; }
    public Long getTtl() { return ttl; }
    public Long getCreatedAt() { return createdAt; }
    public Long getUpdatedAt() { return updatedAt; }
}

// ==================== Document Types ====================

class Document {
    private String id;
    private String collection;
    private Map<String, Object> data;
    private Long createdAt;
    private Long updatedAt;

    public String getId() { return id; }
    public String getCollection() { return collection; }
    public Map<String, Object> getData() { return data; }
    public Long getCreatedAt() { return createdAt; }
    public Long getUpdatedAt() { return updatedAt; }
}

class Query {
    private Map<String, Object> filter;
    private Map<String, Integer> sort;
    private Integer limit;
    private Integer offset;
    private String[] projection;

    public Query filter(Map<String, Object> filter) {
        this.filter = filter;
        return this;
    }

    public Query sort(Map<String, Integer> sort) {
        this.sort = sort;
        return this;
    }

    public Query limit(int limit) {
        this.limit = limit;
        return this;
    }

    public Query offset(int offset) {
        this.offset = offset;
        return this;
    }

    public Query projection(String... fields) {
        this.projection = fields;
        return this;
    }
}

// ==================== Vector Types ====================

class VectorEntry {
    private String id;
    private double[] vector;
    private Map<String, Object> metadata;

    public VectorEntry(String id, double[] vector) {
        this.id = id;
        this.vector = vector;
    }

    public VectorEntry(String id, double[] vector, Map<String, Object> metadata) {
        this.id = id;
        this.vector = vector;
        this.metadata = metadata;
    }

    public String getId() { return id; }
    public double[] getVector() { return vector; }
    public Map<String, Object> getMetadata() { return metadata; }
}

class SearchResult {
    private String id;
    private double score;
    private double[] vector;
    private Map<String, Object> metadata;

    public String getId() { return id; }
    public double getScore() { return score; }
    public double[] getVector() { return vector; }
    public Map<String, Object> getMetadata() { return metadata; }
}

// ==================== Time Series Types ====================

class DataPoint {
    private long timestamp;
    private double value;
    private Map<String, String> tags;

    public DataPoint(long timestamp, double value) {
        this.timestamp = timestamp;
        this.value = value;
    }

    public DataPoint(long timestamp, double value, Map<String, String> tags) {
        this.timestamp = timestamp;
        this.value = value;
        this.tags = tags;
    }

    public long getTimestamp() { return timestamp; }
    public double getValue() { return value; }
    public Map<String, String> getTags() { return tags; }
}

class TimeRange {
    private long start;
    private long end;

    public TimeRange(long start, long end) {
        this.start = start;
        this.end = end;
    }

    public long getStart() { return start; }
    public long getEnd() { return end; }
}

class Aggregation {
    private String function; // sum, avg, min, max, count
    private String interval; // 1m, 5m, 1h, 1d

    public Aggregation(String function, String interval) {
        this.function = function;
        this.interval = interval;
    }

    public String getFunction() { return function; }
    public String getInterval() { return interval; }
}

// ==================== Error Types ====================

class DatabaseException extends RuntimeException {
    private final String code;
    private final int statusCode;

    public DatabaseException(String message) {
        super(message);
        this.code = null;
        this.statusCode = 0;
    }

    public DatabaseException(String message, String code, int statusCode) {
        super(message);
        this.code = code;
        this.statusCode = statusCode;
    }

    public String getCode() { return code; }
    public int getStatusCode() { return statusCode; }
}
