-- topology_api/migrations/002_tables.sql
-- 8 core tables with temporal constraints

-- 1. bases
CREATE TABLE topology.bases (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    code text NOT NULL,
    name text NOT NULL,
    description text,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT uq_bases_code UNIQUE (code)
);

-- 2. missions
CREATE TABLE topology.missions (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    base_id uuid NOT NULL REFERENCES topology.bases(id),
    code citext NOT NULL,
    title text NOT NULL,
    occurrence_status text NOT NULL DEFAULT 'occurred'
        CHECK (occurrence_status IN ('occurred', 'planned')),
    description text,
    source_ref text,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT uq_missions_base_code UNIQUE (base_id, code)
);

-- 3. mission_events
CREATE TABLE topology.mission_events (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    mission_id uuid NOT NULL REFERENCES topology.missions(id),
    effective_at timestamptz NOT NULL,
    event_order integer NOT NULL DEFAULT 0,
    event_type text NOT NULL,
    title text NOT NULL,
    details jsonb,
    source_ref text,
    recorded_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT uq_mission_event_time UNIQUE (mission_id, effective_at, event_order)
);

-- 4. components
CREATE TABLE topology.components (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    base_id uuid NOT NULL REFERENCES topology.bases(id),
    component_key text NOT NULL,
    component_type text NOT NULL
        CHECK (component_type IN ('module', 'node', 'vehicle', 'equipment')),
    introduced_by_event_id uuid NOT NULL REFERENCES topology.mission_events(id),
    retired_by_event_id uuid REFERENCES topology.mission_events(id),
    metadata jsonb,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT uq_components_base_key UNIQUE (base_id, component_key)
);

-- 5. component_versions
CREATE TABLE topology.component_versions (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    component_id uuid NOT NULL REFERENCES topology.components(id),
    display_name text NOT NULL,
    summary text,
    description text,
    length_m numeric(10,3),
    width_m numeric(10,3),
    height_m numeric(10,3),
    diameter_m numeric(10,3),
    mass_t numeric(12,3),
    detail_url text,
    properties jsonb,
    valid_from timestamptz NOT NULL,
    valid_to timestamptz,
    started_by_event_id uuid NOT NULL REFERENCES topology.mission_events(id),
    ended_by_event_id uuid REFERENCES topology.mission_events(id),
    valid_period tstzrange GENERATED ALWAYS AS (
        tstzrange(valid_from, valid_to, '[)')
    ) STORED,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT ck_version_valid_range CHECK (valid_from < valid_to OR valid_to IS NULL)
);

-- 6. component_states
CREATE TABLE topology.component_states (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    component_id uuid NOT NULL REFERENCES topology.components(id),
    state_kind text NOT NULL,
    state_value text NOT NULL,
    details jsonb,
    valid_from timestamptz NOT NULL,
    valid_to timestamptz,
    started_by_event_id uuid NOT NULL REFERENCES topology.mission_events(id),
    ended_by_event_id uuid REFERENCES topology.mission_events(id),
    valid_period tstzrange GENERATED ALWAYS AS (
        tstzrange(valid_from, valid_to, '[)')
    ) STORED,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT ck_state_valid_range CHECK (valid_from < valid_to OR valid_to IS NULL)
);

-- 7. ports
CREATE TABLE topology.ports (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    component_id uuid NOT NULL REFERENCES topology.components(id),
    port_key text NOT NULL,
    display_name text NOT NULL,
    direction text,
    interface_type text NOT NULL DEFAULT 'structural',
    properties jsonb,
    created_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT uq_ports_component_key UNIQUE (component_id, port_key)
);

-- 8. topology_connections
CREATE TABLE topology.topology_connections (
    id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
    base_id uuid NOT NULL REFERENCES topology.bases(id),
    port_a_id uuid NOT NULL REFERENCES topology.ports(id),
    port_b_id uuid NOT NULL REFERENCES topology.ports(id),
    connection_type text NOT NULL
        CHECK (connection_type IN (
            'structural_mount', 'pressurized_passage', 'docking',
            'power', 'fuel', 'cooling'
        )),
    properties jsonb,
    valid_from timestamptz NOT NULL,
    valid_to timestamptz,
    established_by_event_id uuid NOT NULL REFERENCES topology.mission_events(id),
    ended_by_event_id uuid REFERENCES topology.mission_events(id),
    valid_period tstzrange GENERATED ALWAYS AS (
        tstzrange(valid_from, valid_to, '[)')
    ) STORED,
    created_at timestamptz NOT NULL DEFAULT now(),
    updated_at timestamptz NOT NULL DEFAULT now(),
    CONSTRAINT ck_connection_valid_range CHECK (valid_from < valid_to OR valid_to IS NULL),
    CONSTRAINT ck_different_ports CHECK (port_a_id <> port_b_id)
);

-- Temporal exclusion constraints
ALTER TABLE topology.component_versions
    ADD CONSTRAINT ex_version_no_overlap
    EXCLUDE USING gist (component_id WITH =, valid_period WITH &&);

ALTER TABLE topology.component_states
    ADD CONSTRAINT ex_state_no_overlap
    EXCLUDE USING gist (component_id WITH =, state_kind WITH =, valid_period WITH &&);
