-- QUIXZOOM PostgreSQL + PostGIS Schema
--
-- Ansvarsområden:
-- - Observationer
-- - GPS
-- - Tidsserier
-- - Uppdrag
-- - Zoomers
-- - Videor
-- - Sensorloggar
-- - Spatiala frågor

-- Aktivera PostGIS
CREATE EXTENSION IF NOT EXISTS postgis;

-- ============================================================
-- ZOOMERS
-- ============================================================

CREATE TABLE zoomers (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE,
    phone VARCHAR(50),
    status VARCHAR(50) DEFAULT 'active', -- active, inactive, suspended
    capabilities JSONB DEFAULT '[]', -- ["video", "photo", "lidar"]
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- ============================================================
-- AREAS
-- ============================================================

CREATE TABLE areas (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    name VARCHAR(255) NOT NULL,
    bounds GEOMETRY(POLYGON, 4326), -- PostGIS
    country VARCHAR(100),
    city VARCHAR(100),
    priority FLOAT DEFAULT 0.5,
    status VARCHAR(50) DEFAULT 'active',
    metadata JSONB DEFAULT '{}',
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- ============================================================
-- OBSERVATIONS
-- ============================================================

CREATE TABLE observations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    observation_id VARCHAR(255) UNIQUE NOT NULL, -- Extern ID (obs_xxx)

    -- Källa
    source_type VARCHAR(50) NOT NULL, -- quixzoom, youtube_cc, inspector
    source_id VARCHAR(255),
    zoomer_id UUID REFERENCES zoomers(id),

    -- Media
    media_type VARCHAR(50), -- video, image
    media_url TEXT,
    frame_number INTEGER,
    media_timestamp TIMESTAMP WITH TIME ZONE,

    -- Plats
    location GEOMETRY(POINT, 4326), -- PostGIS
    gps_accuracy FLOAT,
    altitude FLOAT,

    -- Kvalitet
    quality JSONB DEFAULT '{}', -- {resolution, sharpness, exposure}

    -- AI-analys
    ai_analysis JSONB DEFAULT '{}', -- {objectDetection, sceneClassification}

    -- Metadata
    metadata JSONB DEFAULT '{}',

    -- Status
    status VARCHAR(50) DEFAULT 'pending', -- pending, validated, rejected
    validated_by VARCHAR(255),
    validated_at TIMESTAMP WITH TIME ZONE,

    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Spatialt index
CREATE INDEX idx_observations_location ON observations USING GIST(location);
CREATE INDEX idx_observations_created_at ON observations(created_at);
CREATE INDEX idx_observations_source ON observations(source_type, source_id);

-- ============================================================
-- OBJECTS (Urban Objects)
-- ============================================================

CREATE TABLE objects (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    object_id VARCHAR(255) UNIQUE NOT NULL, -- Extern ID (street_lamp_xxx)

    -- Typ
    type VARCHAR(100) NOT NULL, -- street_lamp, pothole, crosswalk
    subtype VARCHAR(100),

    -- Plats
    location GEOMETRY(POINT, 4326), -- PostGIS
    location_accuracy FLOAT,

    -- Attribut (kan ändras över tid)
    attributes JSONB DEFAULT '{}',

    -- Status
    status VARCHAR(50) DEFAULT 'active', -- active, removed, modified
    verification_status VARCHAR(50) DEFAULT 'unverified', -- unverified, verified, disputed

    -- Konfidens
    confidence FLOAT DEFAULT 0,
    uncertainty FLOAT DEFAULT 1.0,

    -- Metadata
    first_seen_at TIMESTAMP WITH TIME ZONE,
    last_seen_at TIMESTAMP WITH TIME ZONE,
    observation_count INTEGER DEFAULT 0,
    metadata JSONB DEFAULT '{}',

    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Spatialt index
CREATE INDEX idx_objects_location ON objects USING GIST(location);
CREATE INDEX idx_objects_type ON objects(type);
CREATE INDEX idx_objects_verification ON objects(verification_status);

-- ============================================================
-- EVIDENCE
-- ============================================================

CREATE TABLE evidence (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    evidence_id VARCHAR(255) UNIQUE NOT NULL, -- Extern ID (ev_xxx)

    -- Referenser
    object_id UUID REFERENCES objects(id),
    observation_id UUID REFERENCES observations(id),

    -- Bevis
    proof_type VARCHAR(50), -- video, image, lidar, manual_inspection
    proof_url TEXT,
    frame_number INTEGER,

    -- Källa
    source_type VARCHAR(50),
    source_id VARCHAR(255),
    operator VARCHAR(255),

    -- Kvalitet
    quality JSONB DEFAULT '{}',
    reliability FLOAT DEFAULT 0,

    -- Metadata
    timestamp TIMESTAMP WITH TIME ZONE,
    metadata JSONB DEFAULT '{}',

    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE INDEX idx_evidence_object ON evidence(object_id);
CREATE INDEX idx_evidence_observation ON evidence(observation_id);

-- ============================================================
-- TEMPORAL (Object History)
-- ============================================================

CREATE TABLE temporal_records (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    temporal_id VARCHAR(255) UNIQUE NOT NULL, -- Extern ID (tmp_xxx)

    -- Referens
    object_id UUID REFERENCES objects(id),

    -- Tillstånd
    state JSONB NOT NULL, -- {attributes, verificationStatus, confidence}

    -- Ändringar
    changes JSONB DEFAULT '[]', -- ["lean: 0 -> 2"]

    -- Orsak
    reason VARCHAR(255),
    source VARCHAR(255),

    -- Tid
    recorded_at TIMESTAMP WITH TIME ZONE NOT NULL,

    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE INDEX idx_temporal_object ON temporal_records(object_id);
CREATE INDEX idx_temporal_recorded_at ON temporal_records(recorded_at);

-- ============================================================
-- MISSIONS
-- ============================================================

CREATE TABLE missions (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    mission_id VARCHAR(255) UNIQUE NOT NULL, -- Extern ID (mission_xxx)

    -- Typ
    type VARCHAR(50) NOT NULL, -- verify, explore, document, diversify

    -- Område
    area_id UUID REFERENCES areas(id),

    -- Mål
    target_location GEOMETRY(POINT, 4326), -- PostGIS
    target_object_id UUID REFERENCES objects(id),

    -- Tilldelning
    assigned_to UUID REFERENCES zoomers(id),
    assigned_at TIMESTAMP WITH TIME ZONE,

    -- Status
    status VARCHAR(50) DEFAULT 'pending', -- pending, assigned, active, completed, failed

    -- Resultat
    result JSONB DEFAULT '{}',
    completed_at TIMESTAMP WITH TIME ZONE,
    failed_at TIMESTAMP WITH TIME ZONE,
    failure_reason TEXT,

    -- Prioritet
    priority FLOAT DEFAULT 0.5,

    -- Metadata
    instructions JSONB DEFAULT '[]',
    metadata JSONB DEFAULT '{}',

    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE INDEX idx_missions_area ON missions(area_id);
CREATE INDEX idx_missions_status ON missions(status);
CREATE INDEX idx_missions_assigned ON missions(assigned_to);

-- ============================================================
-- EVENTS (Event Sourcing)
-- ============================================================

CREATE TABLE events (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    sequence_number BIGINT NOT NULL UNIQUE,

    -- Event-typ
    type VARCHAR(100) NOT NULL,

    -- Stream
    stream_id VARCHAR(255) NOT NULL,
    aggregate_id VARCHAR(255) NOT NULL,

    -- Payload
    payload JSONB NOT NULL,

    -- Metadata
    metadata JSONB DEFAULT '{}',

    -- Tid
    timestamp TIMESTAMP WITH TIME ZONE NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE INDEX idx_events_stream ON events(stream_id);
CREATE INDEX idx_events_type ON events(type);
CREATE INDEX idx_events_timestamp ON events(timestamp);
CREATE INDEX idx_events_sequence ON events(sequence_number);

-- ============================================================
-- SENSOR LOGS
-- ============================================================

CREATE TABLE sensor_logs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

    -- Källa
    zoomer_id UUID REFERENCES zoomers(id),
    observation_id UUID REFERENCES observations(id),

    -- Sensorer
    gps_location GEOMETRY(POINT, 4326), -- PostGIS
    gps_accuracy FLOAT,
    altitude FLOAT,

    imu_accelerometer JSONB, -- {x, y, z}
    imu_gyroscope JSONB, -- {x, y, z}
    imu_magnetometer JSONB, -- {x, y, z}

    compass FLOAT,

    -- Tid
    recorded_at TIMESTAMP WITH TIME ZONE NOT NULL,

    created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

CREATE INDEX idx_sensor_logs_zoomer ON sensor_logs(zoomer_id);
CREATE INDEX idx_sensor_logs_observation ON sensor_logs(observation_id);
CREATE INDEX idx_sensor_logs_recorded_at ON sensor_logs(recorded_at);

-- ============================================================
-- VIEWS (För snabb läsning)
-- ============================================================

CREATE VIEW object_summary AS
SELECT
    o.id,
    o.object_id,
    o.type,
    o.subtype,
    ST_X(o.location::geometry) as longitude,
    ST_Y(o.location::geometry) as latitude,
    o.verification_status,
    o.confidence,
    o.observation_count,
    o.first_seen_at,
    o.last_seen_at,
    COUNT(e.id) as evidence_count,
    COUNT(t.id) as temporal_records_count
FROM objects o
LEFT JOIN evidence e ON e.object_id = o.id
LEFT JOIN temporal_records t ON t.object_id = o.id
GROUP BY o.id;

CREATE VIEW mission_summary AS
SELECT
    m.id,
    m.mission_id,
    m.type,
    m.status,
    m.priority,
    a.name as area_name,
    z.name as assigned_to_name,
    m.created_at,
    m.completed_at
FROM missions m
LEFT JOIN areas a ON a.id = m.area_id
LEFT JOIN zoomers z ON z.id = m.assigned_to;

-- ============================================================
-- TRIGGERS (Uppdatera 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_zoomers_updated_at BEFORE UPDATE ON zoomers
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_areas_updated_at BEFORE UPDATE ON areas
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_objects_updated_at BEFORE UPDATE ON objects
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_missions_updated_at BEFORE UPDATE ON missions
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
