-- 010: 어구 연관성 추적 시스템
-- - correlation_param_models: 파라미터 모델 마스터
-- - gear_correlation_raw_metrics: raw 메트릭 (타임스탬프 파티셔닝, 7일 보존)
-- - gear_correlation_scores: 모델별 어피니티 점수 (상태 테이블)
-- - system_config: 런타임 설정 (파티션 보관기간 등)

SET search_path TO kcg, public;

-- ── 파라미터 모델 ──
CREATE TABLE IF NOT EXISTS kcg.correlation_param_models (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL UNIQUE,
    is_default BOOLEAN DEFAULT FALSE,
    is_active BOOLEAN DEFAULT TRUE,
    params JSONB NOT NULL,
    description TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

-- default 모델 삽입
INSERT INTO kcg.correlation_param_models (name, is_default, is_active, params, description)
VALUES ('default', TRUE, TRUE,
  '{"alpha_base":0.30,"alpha_min":0.08,"alpha_decay_per_streak":0.005,"track_threshold":0.50,"polygon_threshold":0.70,"w_proximity":0.45,"w_visit":0.35,"w_activity":0.20,"w_dtw":0.30,"w_sog_corr":0.20,"w_heading":0.25,"w_prox_vv":0.25,"w_prox_persist":0.50,"w_drift":0.30,"w_signal_sync":0.20,"group_quiet_ratio":0.30,"normal_gap_hours":1.0,"decay_slow":0.015,"decay_fast":0.08,"stale_hours":6.0,"shadow_stay_bonus":0.10,"shadow_return_bonus":0.15,"candidate_radius_factor":3.0,"proximity_threshold_nm":5.0,"visit_threshold_nm":5.0,"night_bonus":1.3,"long_decay_days":7.0}',
  '기본 추적 모델')
ON CONFLICT (name) DO NOTHING;

-- ── Raw 메트릭 (모델 독립, 5분마다 기록, 타임스탬프 파티셔닝) ──
CREATE TABLE IF NOT EXISTS kcg.gear_correlation_raw_metrics (
    id BIGSERIAL,
    observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    group_key VARCHAR(100) NOT NULL,
    target_mmsi VARCHAR(20) NOT NULL,
    target_type VARCHAR(10) NOT NULL,
    target_name VARCHAR(200),

    -- Raw 메트릭 (모든 모델이 공유)
    proximity_ratio DOUBLE PRECISION,
    visit_score DOUBLE PRECISION,
    activity_sync DOUBLE PRECISION,
    dtw_similarity DOUBLE PRECISION,
    speed_correlation DOUBLE PRECISION,
    heading_coherence DOUBLE PRECISION,
    drift_similarity DOUBLE PRECISION,

    -- Shadow
    shadow_stay BOOLEAN DEFAULT FALSE,
    shadow_return BOOLEAN DEFAULT FALSE,

    -- 상태
    gear_group_active_ratio DOUBLE PRECISION,

    PRIMARY KEY (id, observed_at)
) PARTITION BY RANGE (observed_at);

-- 일별 파티션 생성 함수
CREATE OR REPLACE FUNCTION kcg.create_raw_metric_partitions(days_ahead INT DEFAULT 3)
RETURNS void AS $$
DECLARE
    d DATE;
    partition_name TEXT;
BEGIN
    FOR i IN 0..days_ahead LOOP
        d := CURRENT_DATE + i;
        partition_name := 'gear_correlation_raw_metrics_' || TO_CHAR(d, 'YYYYMMDD');
        IF NOT EXISTS (
            SELECT 1 FROM pg_class c
            JOIN pg_namespace n ON n.oid = c.relnamespace
            WHERE c.relname = partition_name AND n.nspname = 'kcg'
        ) THEN
            EXECUTE format(
                'CREATE TABLE IF NOT EXISTS kcg.%I PARTITION OF kcg.gear_correlation_raw_metrics
                 FOR VALUES FROM (%L) TO (%L)',
                partition_name, d, d + 1
            );
        END IF;
    END LOOP;
END;
$$ LANGUAGE plpgsql;

-- 초기 파티션 생성 (오늘 + 3일)
SELECT kcg.create_raw_metric_partitions(3);

-- raw_metrics 인덱스
CREATE INDEX IF NOT EXISTS idx_raw_metrics_group_time
    ON kcg.gear_correlation_raw_metrics (group_key, observed_at DESC);
CREATE INDEX IF NOT EXISTS idx_raw_metrics_target
    ON kcg.gear_correlation_raw_metrics (target_mmsi, observed_at DESC);

-- ── 어피니티 점수 (모델별 독립, 상태 테이블) ──
CREATE TABLE IF NOT EXISTS kcg.gear_correlation_scores (
    id BIGSERIAL PRIMARY KEY,
    model_id INT NOT NULL REFERENCES kcg.correlation_param_models(id) ON DELETE CASCADE,

    group_key VARCHAR(100) NOT NULL,
    target_mmsi VARCHAR(20) NOT NULL,
    target_type VARCHAR(10) NOT NULL,
    target_name VARCHAR(200),

    -- 모델별 점수 (EMA 결과)
    current_score DOUBLE PRECISION DEFAULT 0,
    streak_count INT DEFAULT 0,
    observation_count INT DEFAULT 0,

    -- Shadow 축적
    shadow_bonus_total DOUBLE PRECISION DEFAULT 0,
    shadow_stay_count INT DEFAULT 0,
    shadow_return_count INT DEFAULT 0,

    -- 상태
    freeze_state VARCHAR(20) DEFAULT 'ACTIVE',

    -- 시간
    first_observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    last_observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    UNIQUE (model_id, group_key, target_mmsi)
);

CREATE INDEX IF NOT EXISTS idx_gc_model_group
    ON kcg.gear_correlation_scores (model_id, group_key, current_score DESC);
CREATE INDEX IF NOT EXISTS idx_gc_active
    ON kcg.gear_correlation_scores (current_score DESC)
    WHERE current_score >= 0.5;

-- ── 시스템 설정 (런타임 변경 가능, 재시작 불필요) ──
CREATE TABLE IF NOT EXISTS kcg.system_config (
    key VARCHAR(100) PRIMARY KEY,
    value JSONB NOT NULL,
    description TEXT,
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    updated_by VARCHAR(100) DEFAULT 'system'
);

INSERT INTO kcg.system_config (key, value, description) VALUES
    ('partition.raw_metrics.retention_days', '7',
     'raw_metrics 파티션 보관 기간 (일). 초과 시 파티션 DROP.'),
    ('partition.raw_metrics.create_ahead_days', '3',
     '미래 파티션 미리 생성 일수.'),
    ('partition.scores.cleanup_days', '30',
     '미관측 점수 레코드 정리 기간 (일).'),
    ('correlation.max_active_models', '5',
     '동시 활성 모델 최대 수.')
ON CONFLICT (key) DO NOTHING;
