-- IOM Database Schema
-- PostgreSQL + PostGIS

-- Enable PostGIS
CREATE EXTENSION IF NOT EXISTS postgis;

-- Core: Objects
CREATE TABLE iom_objects (
    id SERIAL PRIMARY KEY,
    goid VARCHAR(20) UNIQUE NOT NULL,
    domain VARCHAR(3) NOT NULL,
    system VARCHAR(3) NOT NULL,
    object_type VARCHAR(3) NOT NULL,
    component VARCHAR(3),
    sequence INTEGER,
    name VARCHAR(255),
    description TEXT,
    material VARCHAR(100),
    dimensions JSONB,
    installation_date DATE,
    expected_lifetime INTEGER, -- years
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

-- Observations
CREATE TABLE observations (
    id SERIAL PRIMARY KEY,
    goid VARCHAR(20) REFERENCES iom_objects(goid),
    observer_id VARCHAR(100),
    timestamp TIMESTAMP DEFAULT NOW(),
    latitude DECIMAL(10, 8),
    longitude DECIMAL(11, 8),
    geom GEOMETRY(Point, 4326),
    overall_condition INTEGER CHECK (overall_condition BETWEEN 1 AND 5),
    findings JSONB,
    media_urls JSONB,
    metadata JSONB,
    weather JSONB,
    ai_analysis JSONB
);

-- Defects
CREATE TABLE defect_logs (
    id SERIAL PRIMARY KEY,
    observation_id INTEGER REFERENCES observations(id),
    code VARCHAR(10) NOT NULL,
    type VARCHAR(100),
    severity INTEGER CHECK (severity BETWEEN 1 AND 5),
    description TEXT,
    ai_confidence DECIMAL(3, 2),
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Risk Assessments
CREATE TABLE risk_assessments (
    id SERIAL PRIMARY KEY,
    goid VARCHAR(20) REFERENCES iom_objects(goid),
    overall_risk DECIMAL(3, 2),
    risk_level VARCHAR(20),
    dimensions JSONB,
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Digital Twin
CREATE TABLE digital_twin_nodes (
    id SERIAL PRIMARY KEY,
    goid VARCHAR(20) REFERENCES iom_objects(goid),
    node_type VARCHAR(50),
    properties JSONB,
    geom GEOMETRY(Point, 4326),
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE digital_twin_edges (
    id SERIAL PRIMARY KEY,
    source_goid VARCHAR(20) REFERENCES iom_objects(goid),
    target_goid VARCHAR(20) REFERENCES iom_objects(goid),
    relation_type VARCHAR(50),
    properties JSONB,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Reality Signals
CREATE TABLE reality_signals (
    id SERIAL PRIMARY KEY,
    signal_type VARCHAR(100) NOT NULL,
    category VARCHAR(50) NOT NULL,
    value DECIMAL(10, 2),
    unit VARCHAR(50),
    confidence DECIMAL(3, 2),
    source VARCHAR(100),
    location_geom GEOMETRY(Point, 4326),
    metadata JSONB,
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Composite Indexes
CREATE TABLE composite_indexes (
    id SERIAL PRIMARY KEY,
    index_name VARCHAR(100) NOT NULL,
    category VARCHAR(50),
    score DECIMAL(10, 2),
    confidence DECIMAL(3, 2),
    signals_used INTEGER,
    total_signals_needed INTEGER,
    component_signals JSONB,
    interpretation TEXT,
    location_geom GEOMETRY(Point, 4326),
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Ledger Transactions
CREATE TABLE ledger_transactions (
    id SERIAL PRIMARY KEY,
    goid VARCHAR(20) REFERENCES iom_objects(goid),
    transaction_type VARCHAR(50), -- installation, maintenance, depreciation, impairment
    amount DECIMAL(15, 2),
    currency VARCHAR(3) DEFAULT 'USD',
    bas_account VARCHAR(10),
    description TEXT,
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Sync Log
CREATE TABLE sync_log (
    id SERIAL PRIMARY KEY,
    target_name VARCHAR(100),
    sync_type VARCHAR(50),
    payload_size INTEGER,
    status VARCHAR(20),
    error_message TEXT,
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Indexes
CREATE INDEX idx_observations_goid ON observations(goid);
CREATE INDEX idx_observations_geom ON observations USING GIST(geom);
CREATE INDEX idx_observations_timestamp ON observations(timestamp);
CREATE INDEX idx_signals_type ON reality_signals(signal_type);
CREATE INDEX idx_signals_category ON reality_signals(category);
CREATE INDEX idx_signals_geom ON reality_signals USING GIST(location_geom);
CREATE INDEX idx_composite_name ON composite_indexes(index_name);
CREATE INDEX idx_ledger_goid ON ledger_transactions(goid);

-- Trigger for updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_iom_objects_updated_at
    BEFORE UPDATE ON iom_objects
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_at_column();
