CREATE SCHEMA IF NOT EXISTS fr24;

CREATE TABLE IF NOT EXISTS fr24.captures (
  capture_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  started_at TIMESTAMPTZ NOT NULL,
  ended_at TIMESTAMPTZ,
  source TEXT NOT NULL DEFAULT 'rtl-sdr',
  device_index INTEGER NOT NULL DEFAULT 0,
  center_frequency_hz BIGINT NOT NULL,
  sample_rate_hz INTEGER NOT NULL,
  gain_db NUMERIC(6,2),
  status TEXT NOT NULL DEFAULT 'active',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  notes TEXT
);

CREATE TABLE IF NOT EXISTS fr24.raw_packets (
  raw_packet_id BIGINT GENERATED ALWAYS AS IDENTITY,
  capture_id UUID NOT NULL REFERENCES fr24.captures(capture_id) ON DELETE CASCADE,
  observed_at TIMESTAMPTZ NOT NULL,
  partition_date DATE NOT NULL DEFAULT (CURRENT_DATE),
  frequency_hz BIGINT NOT NULL,
  rssi_dbm NUMERIC(8,3),
  snr_db NUMERIC(8,3),
  samplerate_hz INTEGER NOT NULL,
  payload_base64 TEXT NOT NULL,
  payload_bytes INTEGER,
  decoded_format TEXT,
  message_type TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  PRIMARY KEY (raw_packet_id, partition_date)
) PARTITION BY RANGE (partition_date);

CREATE TABLE IF NOT EXISTS fr24.raw_packets_default
  PARTITION OF fr24.raw_packets DEFAULT;

CREATE TABLE IF NOT EXISTS fr24.aircraft (
  aircraft_id BIGSERIAL PRIMARY KEY,
  icao24 TEXT NOT NULL UNIQUE,
  callsign TEXT,
  registration TEXT,
  aircraft_type TEXT,
  operator_name TEXT,
  first_seen_at TIMESTAMPTZ,
  last_seen_at TIMESTAMPTZ,
  metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS fr24.flights (
  flight_id BIGSERIAL PRIMARY KEY,
  aircraft_id BIGINT NOT NULL REFERENCES fr24.aircraft(aircraft_id) ON DELETE CASCADE,
  departure_airport TEXT,
  arrival_airport TEXT,
  callsign TEXT,
  flight_number TEXT,
  started_at TIMESTAMPTZ NOT NULL,
  ended_at TIMESTAMPTZ,
  status TEXT NOT NULL DEFAULT 'active',
  source TEXT NOT NULL DEFAULT 'rtl-sdr',
  metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS fr24.tracks (
  track_id BIGSERIAL PRIMARY KEY,
  flight_id BIGINT NOT NULL REFERENCES fr24.flights(flight_id) ON DELETE CASCADE,
  geometry GEOMETRY(LineString, 4326),
  point_count INTEGER NOT NULL DEFAULT 0,
  min_altitude_m NUMERIC(10,2),
  max_altitude_m NUMERIC(10,2),
  distance_m NUMERIC(14,2),
  duration_seconds INTEGER,
  last_point_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE IF NOT EXISTS fr24.track_points (
  track_point_id BIGSERIAL PRIMARY KEY,
  track_id BIGINT NOT NULL REFERENCES fr24.tracks(track_id) ON DELETE CASCADE,
  flight_id BIGINT NOT NULL REFERENCES fr24.flights(flight_id) ON DELETE CASCADE,
  observed_at TIMESTAMPTZ NOT NULL,
  point_order INTEGER NOT NULL,
  geom GEOMETRY(Point, 4326) NOT NULL,
  altitude_m NUMERIC(10,2),
  ground_speed_kt NUMERIC(10,2),
  vertical_rate_fpm NUMERIC(10,2),
  heading_deg NUMERIC(10,2),
  source_packet_id BIGINT,
  source_partition_date DATE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  UNIQUE (track_id, point_order)
);

CREATE TABLE IF NOT EXISTS fr24.processing_state (
  state_key TEXT PRIMARY KEY,
  state_value JSONB NOT NULL,
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  note TEXT
);

CREATE TABLE IF NOT EXISTS fr24.noise_results (
  noise_result_id BIGSERIAL PRIMARY KEY,
  flight_id BIGINT REFERENCES fr24.flights(flight_id) ON DELETE CASCADE,
  track_id BIGINT REFERENCES fr24.tracks(track_id) ON DELETE CASCADE,
  computed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  period_start TIMESTAMPTZ,
  period_end TIMESTAMPTZ,
  noise_model TEXT NOT NULL DEFAULT 'v1',
  geometry GEOMETRY(Polygon, 4326),
  summary JSONB NOT NULL DEFAULT '{}'::jsonb,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_raw_packets_capture_time ON fr24.raw_packets (capture_id, observed_at DESC);
CREATE INDEX IF NOT EXISTS idx_raw_packets_partition_date ON fr24.raw_packets (partition_date);
CREATE INDEX IF NOT EXISTS idx_aircraft_last_seen ON fr24.aircraft (last_seen_at DESC);
CREATE INDEX IF NOT EXISTS idx_flights_aircraft_started ON fr24.flights (aircraft_id, started_at DESC);
CREATE INDEX IF NOT EXISTS idx_track_points_track_time ON fr24.track_points (track_id, observed_at);
CREATE INDEX IF NOT EXISTS idx_track_points_flight_time ON fr24.track_points (flight_id, observed_at);
CREATE INDEX IF NOT EXISTS idx_tracks_flight ON fr24.tracks (flight_id);
CREATE INDEX IF NOT EXISTS idx_noise_results_computed_at ON fr24.noise_results (computed_at DESC);
