BEGIN;

ALTER TABLE users
  ADD COLUMN IF NOT EXISTS allowed_modules TEXT[] NOT NULL DEFAULT ARRAY['SCF']::TEXT[];

CREATE TABLE IF NOT EXISTS tracking_devices (
  id SERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  device_name VARCHAR(200) NOT NULL,
  login_username VARCHAR(100) NOT NULL UNIQUE,
  login_password_hash VARCHAR(255) NOT NULL,
  owner_name VARCHAR(200) NOT NULL,
  owner_phone VARCHAR(50),
  owner_department VARCHAR(200),
  device_os VARCHAR(50),
  device_model VARCHAR(200),
  app_version VARCHAR(20),
  is_online BOOLEAN DEFAULT false,
  last_seen TIMESTAMP,
  last_lat DECIMAL(10,7),
  last_lng DECIMAL(10,7),
  last_accuracy DECIMAL(8,2),
  last_speed DECIMAL(8,2),
  last_battery INTEGER,
  last_address TEXT,
  tracking_interval_seconds INTEGER DEFAULT 30,
  is_tracking_enabled BOOLEAN DEFAULT true,
  is_active BOOLEAN DEFAULT true,
  mobile_token VARCHAR(500),
  mobile_token_expires TIMESTAMP,
  freekiosk_enabled BOOLEAN NOT NULL DEFAULT false,
  freekiosk_base_url VARCHAR(500),
  freekiosk_api_key VARCHAR(500),
  freekiosk_mqtt_device VARCHAR(200),
  notes TEXT,
  created_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

ALTER TABLE tracking_devices
  ADD COLUMN IF NOT EXISTS freekiosk_enabled BOOLEAN NOT NULL DEFAULT false;

ALTER TABLE tracking_devices
  ADD COLUMN IF NOT EXISTS freekiosk_base_url VARCHAR(500);

ALTER TABLE tracking_devices
  ADD COLUMN IF NOT EXISTS freekiosk_api_key VARCHAR(500);

ALTER TABLE tracking_devices
  ADD COLUMN IF NOT EXISTS freekiosk_mqtt_device VARCHAR(200);

CREATE TABLE IF NOT EXISTS tracking_locations (
  id BIGSERIAL PRIMARY KEY,
  device_id INTEGER REFERENCES tracking_devices(id) ON DELETE CASCADE,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  latitude DECIMAL(10,7) NOT NULL,
  longitude DECIMAL(10,7) NOT NULL,
  accuracy DECIMAL(8,2),
  altitude DECIMAL(10,2),
  speed DECIMAL(8,2),
  heading DECIMAL(6,2),
  battery_level INTEGER,
  network_type VARCHAR(20),
  address TEXT,
  device_timestamp TIMESTAMP NOT NULL,
  server_timestamp TIMESTAMP DEFAULT NOW(),
  is_moving BOOLEAN DEFAULT false,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_tracking_locations_device_id
  ON tracking_locations(device_id);

CREATE INDEX IF NOT EXISTS idx_tracking_locations_device_time
  ON tracking_locations(device_id, device_timestamp DESC);

CREATE INDEX IF NOT EXISTS idx_tracking_locations_company
  ON tracking_locations(company_id);

CREATE INDEX IF NOT EXISTS idx_tracking_locations_timestamp
  ON tracking_locations(device_timestamp DESC);

CREATE INDEX IF NOT EXISTS idx_tracking_locations_date
  ON tracking_locations((device_timestamp::DATE));

CREATE TABLE IF NOT EXISTS tracking_geofences (
  id SERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  name VARCHAR(200) NOT NULL,
  center_lat DECIMAL(10,7) NOT NULL,
  center_lng DECIMAL(10,7) NOT NULL,
  radius_meters INTEGER NOT NULL DEFAULT 500,
  color VARCHAR(7) DEFAULT '#3B82F6',
  alert_on_enter BOOLEAN DEFAULT false,
  alert_on_exit BOOLEAN DEFAULT true,
  is_active BOOLEAN DEFAULT true,
  created_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS tracking_geofence_devices (
  id SERIAL PRIMARY KEY,
  geofence_id INTEGER REFERENCES tracking_geofences(id) ON DELETE CASCADE,
  device_id INTEGER REFERENCES tracking_devices(id) ON DELETE CASCADE,
  is_active BOOLEAN DEFAULT true,
  UNIQUE (geofence_id, device_id)
);

CREATE TABLE IF NOT EXISTS tracking_geofence_states (
  id SERIAL PRIMARY KEY,
  geofence_id INTEGER REFERENCES tracking_geofences(id) ON DELETE CASCADE,
  device_id INTEGER REFERENCES tracking_devices(id) ON DELETE CASCADE,
  is_inside BOOLEAN DEFAULT false,
  last_transition_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW(),
  UNIQUE (geofence_id, device_id)
);

CREATE TABLE IF NOT EXISTS tracking_alerts (
  id SERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  device_id INTEGER REFERENCES tracking_devices(id) ON DELETE CASCADE,
  alert_type VARCHAR(30),
  title VARCHAR(200),
  message TEXT,
  geofence_id INTEGER REFERENCES tracking_geofences(id) ON DELETE SET NULL,
  lat DECIMAL(10,7),
  lng DECIMAL(10,7),
  status VARCHAR(20) DEFAULT 'active',
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS tracking_settings (
  company_id BIGINT PRIMARY KEY REFERENCES companies(id) ON DELETE CASCADE,
  default_tracking_interval_seconds INTEGER NOT NULL DEFAULT 30,
  offline_threshold_minutes INTEGER NOT NULL DEFAULT 5,
  retention_days INTEGER,
  alert_offline_enabled BOOLEAN NOT NULL DEFAULT true,
  alert_offline_threshold_minutes INTEGER NOT NULL DEFAULT 5,
  alert_low_battery_enabled BOOLEAN NOT NULL DEFAULT true,
  alert_low_battery_threshold INTEGER NOT NULL DEFAULT 15,
  alert_speed_enabled BOOLEAN NOT NULL DEFAULT false,
  alert_speed_threshold_kmh INTEGER NOT NULL DEFAULT 120,
  alert_geofence_enabled BOOLEAN NOT NULL DEFAULT true,
  save_locations_enabled BOOLEAN NOT NULL DEFAULT true,
  save_locations_start_time TIME,
  save_locations_end_time TIME,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

ALTER TABLE tracking_settings
  ADD COLUMN IF NOT EXISTS save_locations_enabled BOOLEAN NOT NULL DEFAULT true;

ALTER TABLE tracking_settings
  ADD COLUMN IF NOT EXISTS save_locations_start_time TIME;

ALTER TABLE tracking_settings
  ADD COLUMN IF NOT EXISTS save_locations_end_time TIME;

CREATE TABLE IF NOT EXISTS tracking_device_commands (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  device_id INTEGER REFERENCES tracking_devices(id) ON DELETE CASCADE,
  command_type VARCHAR(50) NOT NULL,
  payload JSONB,
  status VARCHAR(20) NOT NULL DEFAULT 'pending',
  created_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
  created_at TIMESTAMP DEFAULT NOW(),
  delivered_at TIMESTAMP,
  acked_at TIMESTAMP,
  result JSONB
);

CREATE TABLE IF NOT EXISTS tracking_screen_sessions (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  device_id INTEGER REFERENCES tracking_devices(id) ON DELETE CASCADE,
  status VARCHAR(30) NOT NULL DEFAULT 'requested',
  requested_by BIGINT REFERENCES users(id) ON DELETE SET NULL,
  requested_at TIMESTAMP DEFAULT NOW(),
  started_at TIMESTAMP,
  stopped_at TIMESTAMP,
  last_frame_at TIMESTAMP,
  viewer_connected_at TIMESTAMP,
  width INTEGER,
  height INTEGER,
  latest_frame_url TEXT,
  stop_reason TEXT
);

CREATE TABLE IF NOT EXISTS tracking_audit_log (
  id BIGSERIAL PRIMARY KEY,
  company_id BIGINT REFERENCES companies(id) ON DELETE CASCADE,
  user_id BIGINT REFERENCES users(id) ON DELETE SET NULL,
  action VARCHAR(100),
  entity_type VARCHAR(100),
  entity_id INTEGER,
  details JSONB,
  ip_address INET,
  created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_tracking_devices_company ON tracking_devices(company_id);
CREATE INDEX IF NOT EXISTS idx_tracking_devices_online ON tracking_devices(company_id, is_online, is_active);
CREATE INDEX IF NOT EXISTS idx_tracking_geofences_company ON tracking_geofences(company_id);
CREATE INDEX IF NOT EXISTS idx_tracking_geofence_devices_device ON tracking_geofence_devices(device_id, is_active);
CREATE INDEX IF NOT EXISTS idx_tracking_geofence_states_device ON tracking_geofence_states(device_id);
CREATE INDEX IF NOT EXISTS idx_tracking_alerts_company ON tracking_alerts(company_id, status, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_tracking_alerts_device ON tracking_alerts(device_id, status, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_tracking_settings_company ON tracking_settings(company_id);
CREATE INDEX IF NOT EXISTS idx_tracking_device_commands_device_status
  ON tracking_device_commands(device_id, status, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_tracking_screen_sessions_device_status
  ON tracking_screen_sessions(device_id, status, requested_at DESC);
CREATE INDEX IF NOT EXISTS idx_tracking_audit_company ON tracking_audit_log(company_id, created_at DESC);

COMMIT;
