-- Migration: Trust Vector Calibration Schema
-- Sprint: 7100.0002.0002
-- Description: Creates schema and tables for trust vector calibration system

-- Create calibration schema
CREATE SCHEMA IF NOT EXISTS excititor_calibration;

-- Calibration manifests table
-- Stores signed manifests for each calibration epoch
CREATE TABLE IF NOT EXISTS excititor_calibration.calibration_manifests (
    manifest_id TEXT PRIMARY KEY,
    tenant_id TEXT NOT NULL,
    epoch_number INTEGER NOT NULL,
    epoch_start_utc TIMESTAMP NOT NULL,
    epoch_end_utc TIMESTAMP NOT NULL,
    sample_count INTEGER NOT NULL,
    learning_rate DOUBLE PRECISION NOT NULL,
    policy_hash TEXT,
    lattice_version TEXT NOT NULL,
    manifest_json JSONB NOT NULL,
    signature_envelope JSONB,
    created_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
    created_by TEXT NOT NULL,

    CONSTRAINT uq_calibration_manifest_tenant_epoch UNIQUE (tenant_id, epoch_number)
);

CREATE INDEX idx_calibration_manifests_tenant
    ON excititor_calibration.calibration_manifests(tenant_id);
CREATE INDEX idx_calibration_manifests_created
    ON excititor_calibration.calibration_manifests(created_at_utc DESC);

-- Trust vector adjustments table
-- Records each provider's trust vector changes per epoch
CREATE TABLE IF NOT EXISTS excititor_calibration.trust_vector_adjustments (
    adjustment_id BIGSERIAL PRIMARY KEY,
    manifest_id TEXT NOT NULL REFERENCES excititor_calibration.calibration_manifests(manifest_id),
    source_id TEXT NOT NULL,
    old_provenance DOUBLE PRECISION NOT NULL,
    old_coverage DOUBLE PRECISION NOT NULL,
    old_replayability DOUBLE PRECISION NOT NULL,
    new_provenance DOUBLE PRECISION NOT NULL,
    new_coverage DOUBLE PRECISION NOT NULL,
    new_replayability DOUBLE PRECISION NOT NULL,
    adjustment_magnitude DOUBLE PRECISION NOT NULL,
    confidence_in_adjustment DOUBLE PRECISION NOT NULL,
    sample_count_for_source INTEGER NOT NULL,
    created_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),

    CONSTRAINT chk_old_provenance_range CHECK (old_provenance >= 0 AND old_provenance <= 1),
    CONSTRAINT chk_old_coverage_range CHECK (old_coverage >= 0 AND old_coverage <= 1),
    CONSTRAINT chk_old_replayability_range CHECK (old_replayability >= 0 AND old_replayability <= 1),
    CONSTRAINT chk_new_provenance_range CHECK (new_provenance >= 0 AND new_provenance <= 1),
    CONSTRAINT chk_new_coverage_range CHECK (new_coverage >= 0 AND new_coverage <= 1),
    CONSTRAINT chk_new_replayability_range CHECK (new_replayability >= 0 AND new_replayability <= 1),
    CONSTRAINT chk_confidence_range CHECK (confidence_in_adjustment >= 0 AND confidence_in_adjustment <= 1)
);

CREATE INDEX idx_trust_adjustments_manifest
    ON excititor_calibration.trust_vector_adjustments(manifest_id);
CREATE INDEX idx_trust_adjustments_source
    ON excititor_calibration.trust_vector_adjustments(source_id);

-- Calibration feedback samples table
-- Stores empirical evidence used for calibration
CREATE TABLE IF NOT EXISTS excititor_calibration.calibration_samples (
    sample_id BIGSERIAL PRIMARY KEY,
    tenant_id TEXT NOT NULL,
    source_id TEXT NOT NULL,
    cve_id TEXT NOT NULL,
    purl TEXT NOT NULL,
    expected_status TEXT NOT NULL,
    actual_status TEXT NOT NULL,
    verdict_confidence DOUBLE PRECISION NOT NULL,
    is_match BOOLEAN NOT NULL,
    feedback_source TEXT NOT NULL, -- 'reachability', 'customer_feedback', 'integration_tests'
    feedback_weight DOUBLE PRECISION NOT NULL DEFAULT 1.0,
    scan_id TEXT,
    collected_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),
    processed BOOLEAN NOT NULL DEFAULT FALSE,
    processed_in_manifest_id TEXT REFERENCES excititor_calibration.calibration_manifests(manifest_id),

    CONSTRAINT chk_verdict_confidence_range CHECK (verdict_confidence >= 0 AND verdict_confidence <= 1),
    CONSTRAINT chk_feedback_weight_range CHECK (feedback_weight >= 0 AND feedback_weight <= 1)
);

CREATE INDEX idx_calibration_samples_tenant
    ON excititor_calibration.calibration_samples(tenant_id);
CREATE INDEX idx_calibration_samples_source
    ON excititor_calibration.calibration_samples(source_id);
CREATE INDEX idx_calibration_samples_collected
    ON excititor_calibration.calibration_samples(collected_at_utc DESC);
CREATE INDEX idx_calibration_samples_processed
    ON excititor_calibration.calibration_samples(processed) WHERE NOT processed;

-- Calibration metrics table
-- Tracks performance metrics per source/severity/status
CREATE TABLE IF NOT EXISTS excititor_calibration.calibration_metrics (
    metric_id BIGSERIAL PRIMARY KEY,
    manifest_id TEXT NOT NULL REFERENCES excititor_calibration.calibration_manifests(manifest_id),
    source_id TEXT,
    severity TEXT,
    status TEXT,
    precision DOUBLE PRECISION NOT NULL,
    recall DOUBLE PRECISION NOT NULL,
    f1_score DOUBLE PRECISION NOT NULL,
    false_positive_rate DOUBLE PRECISION NOT NULL,
    false_negative_rate DOUBLE PRECISION NOT NULL,
    sample_count INTEGER NOT NULL,
    created_at_utc TIMESTAMP NOT NULL DEFAULT (NOW() AT TIME ZONE 'UTC'),

    CONSTRAINT chk_precision_range CHECK (precision >= 0 AND precision <= 1),
    CONSTRAINT chk_recall_range CHECK (recall >= 0 AND recall <= 1),
    CONSTRAINT chk_f1_range CHECK (f1_score >= 0 AND f1_score <= 1),
    CONSTRAINT chk_fpr_range CHECK (false_positive_rate >= 0 AND false_positive_rate <= 1),
    CONSTRAINT chk_fnr_range CHECK (false_negative_rate >= 0 AND false_negative_rate <= 1)
);

CREATE INDEX idx_calibration_metrics_manifest
    ON excititor_calibration.calibration_metrics(manifest_id);
CREATE INDEX idx_calibration_metrics_source
    ON excititor_calibration.calibration_metrics(source_id) WHERE source_id IS NOT NULL;

-- Grant permissions to excititor service role
DO $$
BEGIN
    IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'excititor_service') THEN
        GRANT USAGE ON SCHEMA excititor_calibration TO excititor_service;
        GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA excititor_calibration TO excititor_service;
        GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA excititor_calibration TO excititor_service;
        ALTER DEFAULT PRIVILEGES IN SCHEMA excititor_calibration
            GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO excititor_service;
        ALTER DEFAULT PRIVILEGES IN SCHEMA excititor_calibration
            GRANT USAGE, SELECT ON SEQUENCES TO excititor_service;
    END IF;
END $$;

-- Comments for documentation
COMMENT ON SCHEMA excititor_calibration IS 'Trust vector calibration data for VEX source scoring';
COMMENT ON TABLE excititor_calibration.calibration_manifests IS 'Signed calibration epoch results';
COMMENT ON TABLE excititor_calibration.trust_vector_adjustments IS 'Per-source trust vector changes per epoch';
COMMENT ON TABLE excititor_calibration.calibration_samples IS 'Empirical feedback samples for calibration';
COMMENT ON TABLE excititor_calibration.calibration_metrics IS 'Performance metrics per calibration epoch';
