-- mock_location.sql
-- Populates deterministic wearable location data for demos and local development.
-- Requires schema from doc_chat/locations.sql and zhipao.sql (users/devices tables).

BEGIN;

-- Stable identifiers reused across the script to keep reruns idempotent.
CREATE TEMP TABLE __mock_actor AS
SELECT
    'eed3824b-bba1-4309-8048-19d17367c084'::UUID AS user_id,
    'b2d0aabd-4f7d-42c8-a7a8-9d5b4c67d222'::UUID AS device_id;

CREATE TEMP TABLE __mock_gateways AS
SELECT *
FROM (
    VALUES
        (
            '11111111-aaaa-bbbb-cccc-000000000001'::UUID,
            '北侧主楼网关',
            'MOCK-GW-NORTH',
            'active',
            'main',
            'north-zone',
            '教学楼A',
            '3F',
            '301',
            31.230900,
            121.473200,
            'WGS84',
            35.0,
            30,
            3.5,
            0.0,
            'Mock gateway providing northern coverage',
            -51.0,
            12.0
        ),
        (
            '11111111-aaaa-bbbb-cccc-000000000002'::UUID,
            '南侧体育馆网关',
            'MOCK-GW-SOUTH',
            'active',
            'main',
            'south-zone',
            '体育馆',
            '1F',
            '大厅',
            31.229700,
            121.473400,
            'WGS84',
            40.0,
            30,
            4.0,
            180.0,
            'Mock gateway covering southern sports hall',
            -56.0,
            11.5
        ),
        (
            '11111111-aaaa-bbbb-cccc-000000000003'::UUID,
            '东侧宿舍楼网关',
            'MOCK-GW-EAST',
            'active',
            'main',
            'east-zone',
            '宿舍楼C',
            '2F',
            '走廊',
            31.230100,
            121.474500,
            'WGS84',
            30.0,
            30,
            3.0,
            90.0,
            'Mock gateway for east dormitory coverage',
            -53.5,
            12.5
        )
) AS g(
    gateway_id,
    name,
    system_code,
    status,
    campus_code,
    area_name,
    building_name,
    floor_label,
    room_label,
    latitude,
    longitude,
    coordinate_system,
    coverage_radius_m,
    heartbeat_interval_s,
    install_height_m,
    orientation_deg,
    description,
    base_rssi_dbm,
    base_snr_db
);

-- Ensure the mock user exists.
INSERT INTO public.ak_users (id, username, email, password_hash, role, created_at, updated_at)
SELECT
    actor.user_id,
    'mock_location_user',
    'mock_location_user@example.com',
    crypt('Mock@123', gen_salt('bf')),
    'student',
    NOW(),
    NOW()
FROM __mock_actor actor
ON CONFLICT (id) DO UPDATE
SET
    username = EXCLUDED.username,
    email = EXCLUDED.email,
    password_hash = EXCLUDED.password_hash,
    updated_at = NOW();

-- Ensure the mock device exists.
INSERT INTO public.ak_devices (
    id,
    user_id,
    device_type,
    device_name,
    device_mac,
    bind_time,
    status,
    extra
)
SELECT
    actor.device_id,
    actor.user_id,
    'wristband',
    '模拟定位手环',
    'AA-BB-CC-11-22-33',
    NOW(),
    'active',
    jsonb_build_object(
        'firmware_version', 'mock-1.0',
        'hardware_revision', 'rev-A',
        'notes', 'Mocked location feed device for UI demos'
    )
FROM __mock_actor actor
ON CONFLICT (id) DO UPDATE
SET
    user_id = EXCLUDED.user_id,
    device_type = EXCLUDED.device_type,
    device_name = EXCLUDED.device_name,
    device_mac = EXCLUDED.device_mac,
    status = EXCLUDED.status,
    extra = EXCLUDED.extra,
    bind_time = EXCLUDED.bind_time;

-- Ensure reference gateways are present (upsert by primary key).
INSERT INTO location_gateways (
    id,
    name,
    system_code,
    status,
    campus_code,
    area_name,
    building_name,
    floor_label,
    room_label,
    latitude,
    longitude,
    coordinate_system,
    coverage_radius_m,
    heartbeat_interval_s,
    install_height_m,
    orientation_deg,
    description
)
SELECT
    gateway_id,
    name,
    system_code,
    status,
    campus_code,
    area_name,
    building_name,
    floor_label,
    room_label,
    latitude,
    longitude,
    coordinate_system,
    coverage_radius_m,
    heartbeat_interval_s,
    install_height_m,
    orientation_deg,
    description
FROM __mock_gateways g
ON CONFLICT (id) DO UPDATE
SET
    name = EXCLUDED.name,
    system_code = EXCLUDED.system_code,
    status = EXCLUDED.status,
    campus_code = EXCLUDED.campus_code,
    area_name = EXCLUDED.area_name,
    building_name = EXCLUDED.building_name,
    floor_label = EXCLUDED.floor_label,
    room_label = EXCLUDED.room_label,
    latitude = EXCLUDED.latitude,
    longitude = EXCLUDED.longitude,
    coordinate_system = EXCLUDED.coordinate_system,
    coverage_radius_m = EXCLUDED.coverage_radius_m,
    heartbeat_interval_s = EXCLUDED.heartbeat_interval_s,
    install_height_m = EXCLUDED.install_height_m,
    orientation_deg = EXCLUDED.orientation_deg,
    description = EXCLUDED.description,
    updated_at = NOW();

-- Clear any previous mock data for the device to keep reruns idempotent.
WITH actor AS (SELECT device_id FROM __mock_actor)
DELETE FROM wearable_location_snapshots s
WHERE s.device_id = (SELECT device_id FROM actor);

-- Configuration and synthetic data generation (5-second cadence for 10 minutes).
WITH params AS (
    SELECT
        NOW() - INTERVAL '10 minutes' AS window_start,
        INTERVAL '5 seconds' AS cadence_interval,
        120 AS sample_count,
        22.0 AS base_radius_m,
        0.92 AS base_confidence
),
 timeline AS (
    SELECT
        actor.device_id,
        actor.user_id,
        params.window_start + params.cadence_interval * seq AS estimated_at,
        seq
    FROM __mock_actor actor,
         params,
         generate_series(0, (SELECT sample_count FROM params) - 1) AS seq
),
 path AS (
    SELECT
        t.device_id,
        t.user_id,
        t.estimated_at,
        t.seq,
        31.230300 + 0.00025 * SIN(2 * PI() * t.seq / 40.0) AS latitude,
        121.473800 + 0.00035 * COS(2 * PI() * t.seq / 40.0) AS longitude,
        6.5 + 0.2 * SIN(2 * PI() * t.seq / 20.0) AS altitude_m,
        (SELECT base_radius_m FROM params) + 1.5 * RANDOM() AS uncertainty_radius_m,
        LEAST(0.99, (SELECT base_confidence FROM params) + 0.05 * RANDOM()) AS confidence
    FROM timeline t
),
 observation_samples AS (
    SELECT
        p.device_id,
        p.user_id,
        p.estimated_at,
        g.gateway_id,
        g.name AS gateway_name,
        g.system_code,
        g.latitude,
        g.longitude,
        g.orientation_deg,
        g.description,
        (g.base_rssi_dbm + (-3 + RANDOM() * 6))::NUMERIC(5, 2) AS rssi_dbm,
        (g.base_snr_db + (-0.5 + RANDOM()))::NUMERIC(5, 2) AS snr_db,
        (18 + RANDOM() * 6)::NUMERIC(7, 2) AS distance_m,
    (11 + (RANDOM() * 2))::INT AS channel,
    ROUND((2402 + RANDOM() * 4)::NUMERIC, 2) AS frequency_mhz,
        (1000 + FLOOR(RANDOM() * 2000))::INT AS packet_sequence,
        (5 + FLOOR(RANDOM() * 8))::INT AS latency_ms,
        'gw-firmware-mock-1.0' AS firmware_version,
        (3.75 + RANDOM() * 0.05)::NUMERIC(6, 3) AS battery_voltage,
        (25.5 + RANDOM() * 1.5)::NUMERIC(4, 1) AS temperature_c
    FROM path p
    CROSS JOIN __mock_gateways g
),
 snapshot_payload AS (
    SELECT
        p.device_id,
        p.user_id,
        p.estimated_at,
        p.latitude,
        p.longitude,
        p.altitude_m,
        p.uncertainty_radius_m,
        p.confidence,
        p.seq,
        COUNT(os.gateway_id)::INT AS observation_count,
        jsonb_agg(
            jsonb_build_object(
                'gateway_id', os.gateway_id,
                'name', os.gateway_name,
                'system_code', os.system_code,
                'rssi_dbm', os.rssi_dbm,
                'snr_db', os.snr_db,
                'distance_m', os.distance_m,
                'battery_voltage', os.battery_voltage,
                'temperature_c', os.temperature_c
            ) ORDER BY os.gateway_id
        ) AS observations_json,
        jsonb_build_object(
            'path_index', p.seq,
            'source', 'mock_location.sql',
            'mean_distance_m', ROUND(AVG(os.distance_m)::NUMERIC, 2),
            'mean_snr_db', ROUND(AVG(os.snr_db)::NUMERIC, 2)
        ) AS diagnostics_json
    FROM path p
    JOIN observation_samples os
      ON os.device_id = p.device_id
     AND os.user_id = p.user_id
     AND os.estimated_at = p.estimated_at
    GROUP BY
        p.device_id,
        p.user_id,
        p.estimated_at,
        p.latitude,
        p.longitude,
        p.altitude_m,
        p.uncertainty_radius_m,
        p.confidence,
        p.seq
),
 inserted_snapshots AS (
    INSERT INTO wearable_location_snapshots (
        device_id,
        user_id,
        estimated_at,
        window_started_at,
        window_ended_at,
        latitude,
        longitude,
        altitude_m,
        coordinate_system,
        uncertainty_radius_m,
        confidence,
        method,
        algorithm_version,
        observation_count,
        campus_code,
        area_name,
        building_name,
        floor_label,
        room_label,
        observations,
        diagnostics,
        created_at,
        updated_at
    )
    SELECT
        sp.device_id,
        sp.user_id,
        sp.estimated_at,
        sp.estimated_at - INTERVAL '2 seconds',
        sp.estimated_at + INTERVAL '2 seconds',
        sp.latitude,
        sp.longitude,
        sp.altitude_m,
        'WGS84',
        sp.uncertainty_radius_m,
        sp.confidence,
        'trilateration',
        'mock-v1',
        sp.observation_count,
        'main',
        'demo-zone',
        '演示大楼',
        '3F',
        '走廊',
        sp.observations_json,
        sp.diagnostics_json,
        NOW(),
        NOW()
    FROM snapshot_payload sp
    RETURNING id, device_id, user_id, estimated_at
)
INSERT INTO wearable_location_observations (
    snapshot_id,
    gateway_id,
    received_at,
    gateway_time,
    rssi_dbm,
    snr_db,
    distance_m,
    channel,
    frequency_mhz,
    packet_sequence,
    latency_ms,
    firmware_version,
    payload,
    created_at
)
SELECT
    s.id,
    os.gateway_id,
    os.estimated_at,
    os.estimated_at,
    os.rssi_dbm,
    os.snr_db,
    os.distance_m,
    os.channel,
    os.frequency_mhz,
    os.packet_sequence,
    os.latency_ms,
    os.firmware_version,
    jsonb_build_object(
        'device_id', os.device_id,
        'user_id', os.user_id,
        'gateway_name', os.gateway_name,
        'system_code', os.system_code,
        'battery_voltage', os.battery_voltage,
        'temperature_c', os.temperature_c,
        'latitude', os.latitude,
        'longitude', os.longitude,
        'orientation_deg', os.orientation_deg,
        'description', os.description
    ),
    NOW()
FROM inserted_snapshots s
JOIN observation_samples os
  ON os.device_id = s.device_id
 AND os.user_id = s.user_id
 AND os.estimated_at = s.estimated_at;

COMMIT;