<?php
/**
 * DB initialization and migrations.
 *
 * @package Vachr Short-Term Rental Reservations
 * @license GPLv2 or later
 */
if (!defined('ABSPATH')) exit;

class VSTRB_DB {
	// DB bootstrap/migrations intentionally use direct SQL (custom tables, schema updates).
	// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value, PluginCheck.Security.DirectDB.UnescapedDBParameter
	public static function tables() {
		global $wpdb;
		$p = $wpdb->prefix;
		return [
			'services' => $p . 'vstrb_services',
			'unit_services' => $p . 'vstrb_unit_services',
			'rates' => $p . 'vstrb_rates',
			'bookings' => $p . 'vstrb_bookings',
			'booking_services' => $p . 'vstrb_booking_services',
			'booking_days' => $p . 'vstrb_booking_days',
			'ical_feeds' => $p . 'vstrb_ical_feeds',
			'service_meta' => $p . 'vstrb_service_meta',
			'amenities' => $p . 'vstrb_amenities',
			'amenity_meta' => $p . 'vstrb_amenity_meta',
			'unit_amenities' => $p . 'vstrb_unit_amenities',
			'contact_fields' => $p . 'vstrb_contact_fields',
			'contact_field_meta' => $p . 'vstrb_contact_field_meta',
			'unit_contact_fields' => $p . 'vstrb_unit_contact_fields',
			'booking_meta' => $p . 'vstrb_booking_meta',
			'guest_registrations' => $p . 'vstrb_guest_registrations',
			'invoices' => $p . 'vstrb_invoices',
			'payments' => $p . 'vstrb_payments',
			'ai_processed_sources' => $p . 'vstrb_ai_processed_sources',
		];
	}

	public static function activate() {
		self::perform_migration();
		self::migrate();
		self::schedule_cron();
	}

	public static function deactivate() {
		wp_clear_scheduled_hook('vstrb_ical_import_cron');
		wp_clear_scheduled_hook('vstrb_arrival_instructions_cron');
		wp_clear_scheduled_hook('vstrb_staff_departure_notifications_cron');
		wp_clear_scheduled_hook('vstrb_staff_task_notifications_cron');
		if (class_exists('VSTRB_Content_Generator')) {
			VSTRB_Content_Generator::clear_scheduled_profiles();
		}
	}

	public static function schedule_cron() {
		if (!wp_next_scheduled('vstrb_ical_import_cron')) {
			wp_schedule_event(time() + 300, 'hourly', 'vstrb_ical_import_cron');
		}
		if (!wp_next_scheduled('vstrb_arrival_instructions_cron')) {
			wp_schedule_event(time() + 600, 'daily', 'vstrb_arrival_instructions_cron');
		}
		if (!wp_next_scheduled('vstrb_staff_departure_notifications_cron')) {
			wp_schedule_event(time() + 900, 'daily', 'vstrb_staff_departure_notifications_cron');
		}
		if (!wp_next_scheduled('vstrb_staff_task_notifications_cron')) {
			wp_schedule_event(time() + 960, 'hourly', 'vstrb_staff_task_notifications_cron');
		}
		if (class_exists('VSTRB_Content_Generator')) {
			VSTRB_Content_Generator::reschedule_all_profiles();
		}
	}

	public static function perform_migration() {
		if (class_exists('VSTRB_Staff_Tasks') && get_option(VSTRB_Staff_Tasks::OPTION, null) === null) {
			$legacy_rules = trim((string) get_option('vstrb_staff_notification_rules', ''));
			$legacy_emails = trim((string) get_option('vstrb_staff_notification_emails', ''));
			if ($legacy_rules !== '' || $legacy_emails !== '') {
				VSTRB_Staff_Tasks::save_config(VSTRB_Staff_Tasks::from_legacy_rules());
			}
		}
	}

	public static function migrate() {
		global $wpdb;
		require_once ABSPATH . 'wp-admin/includes/upgrade.php';

		$charset = $wpdb->get_charset_collate();
		$t = self::tables();

		$sql = [];

		$sql[] = "CREATE TABLE {$t['services']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			name VARCHAR(190) NOT NULL,
			code VARCHAR(64) NOT NULL,
			pricing_type ENUM('per_stay','per_night','per_person','per_person_night','free') NOT NULL DEFAULT 'per_stay',
			price DECIMAL(10,2) NOT NULL DEFAULT 0,
			description TEXT NULL,
			is_active TINYINT(1) NOT NULL DEFAULT 1,
			is_optional TINYINT(1) NOT NULL DEFAULT 1,
			sort_order INT NOT NULL DEFAULT 0,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			UNIQUE KEY code (code)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['service_meta']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			service_id BIGINT UNSIGNED NOT NULL,
			meta_key VARCHAR(190) NOT NULL,
			meta_value LONGTEXT NULL,
			locale VARCHAR(10) NULL,
			PRIMARY KEY (id),
			KEY service_id (service_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['amenities']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			name VARCHAR(190) NOT NULL,
			code VARCHAR(64) NOT NULL,
			category VARCHAR(64) NOT NULL DEFAULT 'general',
			description TEXT NULL,
			is_active TINYINT(1) NOT NULL DEFAULT 1,
			sort_order INT NOT NULL DEFAULT 0,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			UNIQUE KEY code (code),
			KEY category (category),
			KEY is_active (is_active)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['amenity_meta']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			amenity_id BIGINT UNSIGNED NOT NULL,
			meta_key VARCHAR(190) NOT NULL,
			meta_value LONGTEXT NULL,
			locale VARCHAR(10) NULL,
			PRIMARY KEY (id),
			KEY amenity_id (amenity_id),
			KEY meta_locale (meta_key, locale)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['contact_fields']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			field_key VARCHAR(64) NOT NULL,
			is_active TINYINT(1) NOT NULL DEFAULT 1,
			sort_order INT NOT NULL DEFAULT 0,
			PRIMARY KEY (id),
			UNIQUE KEY field_key (field_key)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['unit_contact_fields']} (
			unit_id BIGINT UNSIGNED NOT NULL,
			field_id BIGINT UNSIGNED NOT NULL,
			PRIMARY KEY (unit_id, field_id),
			KEY field_id (field_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['contact_field_meta']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			field_id BIGINT UNSIGNED NOT NULL,
			meta_key VARCHAR(190) NOT NULL,
			meta_value LONGTEXT NULL,
			locale VARCHAR(10) NULL,
			PRIMARY KEY (id),
			KEY field_id (field_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['booking_meta']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			booking_id BIGINT UNSIGNED NOT NULL,
			meta_key VARCHAR(190) NOT NULL,
			meta_value LONGTEXT NULL,
			PRIMARY KEY (id),
			KEY booking_id (booking_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['unit_services']} (
			unit_id BIGINT UNSIGNED NOT NULL,
			service_id BIGINT UNSIGNED NOT NULL,
			currency CHAR(3) NOT NULL DEFAULT 'EUR',
			is_optional TINYINT(1) NOT NULL DEFAULT 1,
			price_override DECIMAL(10,2) NULL,
			pricing_type ENUM('per_stay','per_night','per_person','per_person_night','free') NULL,
			PRIMARY KEY (unit_id, service_id, currency),
			KEY service_id (service_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['unit_amenities']} (
			unit_id BIGINT UNSIGNED NOT NULL,
			amenity_id BIGINT UNSIGNED NOT NULL,
			PRIMARY KEY (unit_id, amenity_id),
			KEY amenity_id (amenity_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['rates']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			unit_id BIGINT UNSIGNED NOT NULL,
			name VARCHAR(190) NOT NULL,
			date_from DATE NOT NULL,
			date_to DATE NOT NULL,
			apply_mode ENUM('always','date_range','months_of_year','weekdays','annual_dates','days_of_year') NOT NULL DEFAULT 'date_range',
			months_mask VARCHAR(255) NOT NULL DEFAULT '',
			day_of_year_from SMALLINT UNSIGNED NULL,
			day_of_year_to SMALLINT UNSIGNED NULL,
			rule ENUM('per_person_night','per_unit_night','weekend','workday','christmas','new_year','winter','summer','off_season','fixed','single_night') NOT NULL DEFAULT 'per_unit_night',
			operation ENUM('replace','discount_percent','discount_amount','discount_amount_stay','discount_percent_stay','surcharge_percent','surcharge_amount','surcharge_amount_stay','surcharge_percent_stay') NOT NULL DEFAULT 'replace',
			price DECIMAL(10,2) NOT NULL DEFAULT 0,
			currency CHAR(3) NOT NULL DEFAULT 'EUR',
			min_nights INT NULL,
			priority INT NOT NULL DEFAULT 100,
			highlight_in_calendar TINYINT(1) NOT NULL DEFAULT 0,
			is_active TINYINT(1) NOT NULL DEFAULT 1,
			show_name_in_breakdown TINYINT(1) NOT NULL DEFAULT 0,
			breakdown_label_i18n LONGTEXT NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			KEY unit_id (unit_id),
			KEY date_range (date_from, date_to),
			KEY priority (priority)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['bookings']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			unit_id BIGINT UNSIGNED NOT NULL,
			status ENUM('pending','confirmed','cancelled','blocked') NOT NULL DEFAULT 'pending',
			source VARCHAR(50) NOT NULL DEFAULT 'direct',
			date_from DATE NOT NULL,
			date_to DATE NOT NULL,
			guests INT NOT NULL DEFAULT 1,
			adults INT NOT NULL DEFAULT 1,
			children INT NOT NULL DEFAULT 0,
			customer_name VARCHAR(190) NULL,
			customer_lastname VARCHAR(190) NULL,
			customer_gender VARCHAR(20) NULL,
			customer_country CHAR(2) NOT NULL DEFAULT '',
			customer_email VARCHAR(190) NULL,
			customer_phone VARCHAR(64) NULL,
			note TEXT NULL,
			discount_type ENUM('none','percent','amount') NOT NULL DEFAULT 'none',
			discount_value DECIMAL(10,2) NOT NULL DEFAULT 0,
			total_price DECIMAL(10,2) NULL,
			currency CHAR(3) NOT NULL DEFAULT 'EUR',
			ical_uid VARCHAR(255) NULL,
			ical_summary VARCHAR(500) NULL,
			ical_description TEXT NULL,
			external_booking_id VARCHAR(100) NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			KEY unit_id (unit_id),
			KEY status (status),
			KEY date_range (date_from, date_to),
			KEY external_booking_id (external_booking_id),
			KEY ical_uid (ical_uid)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['booking_services']} (
			booking_id BIGINT UNSIGNED NOT NULL,
			service_id BIGINT UNSIGNED NOT NULL,
			qty DECIMAL(10,2) NOT NULL DEFAULT 1,
			price DECIMAL(10,2) NOT NULL DEFAULT 0,
			PRIMARY KEY (booking_id, service_id),
			KEY service_id (service_id)
		) $charset;";

		// "Lock" table: one row per day per unit
		$sql[] = "CREATE TABLE {$t['booking_days']} (
			unit_id BIGINT UNSIGNED NOT NULL,
			day DATE NOT NULL,
			booking_id BIGINT UNSIGNED NOT NULL,
			PRIMARY KEY (unit_id, day),
			KEY booking_id (booking_id)
		) $charset;";

		// iCal feeds per unit (imports)
		$sql[] = "CREATE TABLE {$t['ical_feeds']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			unit_id BIGINT UNSIGNED NOT NULL,
			provider VARCHAR(50) NOT NULL DEFAULT 'other',
			url TEXT NOT NULL,
			is_active TINYINT(1) NOT NULL DEFAULT 1,
			last_import_at DATETIME NULL,
			last_error TEXT NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			KEY unit_id (unit_id),
			KEY is_active (is_active)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['guest_registrations']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			unit_id BIGINT UNSIGNED NOT NULL,
			booking_id BIGINT UNSIGNED NULL,
			first_name VARCHAR(190) NOT NULL,
			last_name VARCHAR(190) NOT NULL,
			date_of_birth DATE NOT NULL,
			street VARCHAR(190) NOT NULL DEFAULT '',
			city VARCHAR(100) NOT NULL DEFAULT '',
			state VARCHAR(100) NOT NULL DEFAULT '',
			document_type VARCHAR(64) NOT NULL,
			document_number VARCHAR(64) NOT NULL,
			nationality VARCHAR(100) NOT NULL,
			date_from DATE NOT NULL,
			date_to DATE NOT NULL,
			email VARCHAR(190) NOT NULL,
			source VARCHAR(100) NOT NULL DEFAULT '',
			booking_reference VARCHAR(100) NOT NULL DEFAULT '',
			billing_enabled TINYINT(1) NOT NULL DEFAULT 0,
			billing_name VARCHAR(190) NOT NULL DEFAULT '',
			billing_company_id VARCHAR(64) NOT NULL DEFAULT '',
			billing_vat_id VARCHAR(64) NOT NULL DEFAULT '',
			billing_street VARCHAR(190) NOT NULL DEFAULT '',
			billing_city VARCHAR(100) NOT NULL DEFAULT '',
			billing_zip VARCHAR(32) NOT NULL DEFAULT '',
			billing_country VARCHAR(100) NOT NULL DEFAULT '',
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			KEY unit_id (unit_id),
			KEY booking_id (booking_id),
			KEY date_range (date_from, date_to)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['invoices']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			booking_id BIGINT UNSIGNED NOT NULL,
			invoice_number VARCHAR(120) NOT NULL,
			status ENUM('issued','paid','cancelled') NOT NULL DEFAULT 'issued',
			invoice_language VARCHAR(10) NOT NULL DEFAULT '',
			total_amount DECIMAL(10,2) NOT NULL DEFAULT 0,
			currency CHAR(3) NOT NULL DEFAULT 'EUR',
			billing_enabled TINYINT(1) NOT NULL DEFAULT 0,
			billing_name VARCHAR(190) NOT NULL DEFAULT '',
			billing_company_id VARCHAR(64) NOT NULL DEFAULT '',
			billing_vat_id VARCHAR(64) NOT NULL DEFAULT '',
			billing_street VARCHAR(190) NOT NULL DEFAULT '',
			billing_city VARCHAR(100) NOT NULL DEFAULT '',
			billing_zip VARCHAR(32) NOT NULL DEFAULT '',
			billing_country VARCHAR(100) NOT NULL DEFAULT '',
			issued_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			paid_at DATETIME NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			UNIQUE KEY invoice_number (invoice_number),
			KEY booking_id (booking_id),
			KEY status (status)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['payments']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			booking_id BIGINT UNSIGNED NOT NULL,
			invoice_id BIGINT UNSIGNED NULL,
			method ENUM('card','bank_transfer','cash','manual') NOT NULL DEFAULT 'manual',
			provider VARCHAR(64) NOT NULL DEFAULT '',
			status ENUM('pending','paid','failed','refunded','cancelled') NOT NULL DEFAULT 'pending',
			amount DECIMAL(10,2) NULL,
			currency CHAR(3) NOT NULL DEFAULT 'EUR',
			provider_reference VARCHAR(190) NOT NULL DEFAULT '',
			gateway_session_id VARCHAR(190) NOT NULL DEFAULT '',
			gateway_status VARCHAR(64) NOT NULL DEFAULT '',
			gateway_payment_status VARCHAR(64) NOT NULL DEFAULT '',
			payment_method_type VARCHAR(64) NOT NULL DEFAULT '',
			card_brand VARCHAR(64) NOT NULL DEFAULT '',
			card_last4 VARCHAR(4) NOT NULL DEFAULT '',
			card_country VARCHAR(2) NOT NULL DEFAULT '',
			gateway_created_at DATETIME NULL,
			gateway_paid_at DATETIME NULL,
			paid_at DATETIME NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			KEY booking_id (booking_id),
			KEY invoice_id (invoice_id),
			KEY status (status),
			KEY provider_reference (provider_reference),
			KEY gateway_session_id (gateway_session_id)
		) $charset;";

		$sql[] = "CREATE TABLE {$t['ai_processed_sources']} (
			id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
			source_hash CHAR(64) NOT NULL,
			source_type VARCHAR(20) NOT NULL DEFAULT '',
			source_ref TEXT NULL,
			language VARCHAR(10) NOT NULL DEFAULT '',
			post_id BIGINT UNSIGNED NULL,
			post_title VARCHAR(255) NOT NULL DEFAULT '',
			status VARCHAR(20) NOT NULL DEFAULT 'processed',
			error_message TEXT NULL,
			created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
			updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY (id),
			UNIQUE KEY source_hash (source_hash),
			KEY post_id (post_id),
			KEY language (language),
			KEY status (status)
		) $charset;";

		$bookings_table_exists = $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $t['bookings'])) === $t['bookings'];
		$needs_guest_split_migration = !$bookings_table_exists || !$wpdb->get_var("SHOW COLUMNS FROM {$t['bookings']} LIKE 'adults'");
		foreach ($sql as $q) {
			dbDelta($q);
		}

		// Split total guests into adults and children while keeping guests as the total.
		if ($needs_guest_split_migration) {
			$wpdb->query("UPDATE {$t['bookings']} SET adults = GREATEST(1, guests)");
		}
		$wpdb->query(
			"UPDATE {$t['bookings']} b
			 INNER JOIN {$t['booking_meta']} m ON m.booking_id = b.id AND m.meta_key = 'customer_country'
			 SET b.customer_country = UPPER(m.meta_value)
			 WHERE b.customer_country = '' AND CHAR_LENGTH(m.meta_value) = 2"
		);

		// Add source/booking_reference to guest_registrations if missing (migration for existing installs)
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS source VARCHAR(100) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS booking_reference VARCHAR(100) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS booking_id BIGINT UNSIGNED NULL");
		// Add street/city/state columns (migration from single address field)
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS street VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS city VARCHAR(100) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS state VARCHAR(100) NOT NULL DEFAULT ''");
		// Add billing columns (optional invoice data)
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_enabled TINYINT(1) NOT NULL DEFAULT 0");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_name VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_company_id VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_vat_id VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_street VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_city VARCHAR(100) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_zip VARCHAR(32) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD COLUMN IF NOT EXISTS billing_country VARCHAR(100) NOT NULL DEFAULT ''");
		$booking_id_idx = $wpdb->get_results("SHOW INDEX FROM {$t['guest_registrations']} WHERE Key_name = 'booking_id'");
		if (empty($booking_id_idx)) {
			$wpdb->query("ALTER TABLE {$t['guest_registrations']} ADD INDEX booking_id (booking_id)");
		}

		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS booking_id BIGINT UNSIGNED NOT NULL");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS invoice_number VARCHAR(120) NOT NULL");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS status ENUM('issued','paid','cancelled') NOT NULL DEFAULT 'issued'");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS invoice_language VARCHAR(10) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS total_amount DECIMAL(10,2) NOT NULL DEFAULT 0");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS currency CHAR(3) NOT NULL DEFAULT 'EUR'");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_enabled TINYINT(1) NOT NULL DEFAULT 0");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_name VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_company_id VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_vat_id VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_street VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_city VARCHAR(100) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_zip VARCHAR(32) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS billing_country VARCHAR(100) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS issued_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
		$wpdb->query("ALTER TABLE {$t['invoices']} ADD COLUMN IF NOT EXISTS paid_at DATETIME NULL");
		$invoice_booking_idx = $wpdb->get_results("SHOW INDEX FROM {$t['invoices']} WHERE Key_name = 'booking_id'");
		if (empty($invoice_booking_idx)) {
			$wpdb->query("ALTER TABLE {$t['invoices']} ADD INDEX booking_id (booking_id)");
		}
		$invoice_status_idx = $wpdb->get_results("SHOW INDEX FROM {$t['invoices']} WHERE Key_name = 'status'");
		if (empty($invoice_status_idx)) {
			$wpdb->query("ALTER TABLE {$t['invoices']} ADD INDEX status (status)");
		}
		$invoice_number_idx = $wpdb->get_results("SHOW INDEX FROM {$t['invoices']} WHERE Key_name = 'invoice_number'");
		if (empty($invoice_number_idx)) {
			$wpdb->query("ALTER TABLE {$t['invoices']} ADD UNIQUE KEY invoice_number (invoice_number)");
		}

		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS booking_id BIGINT UNSIGNED NOT NULL");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS invoice_id BIGINT UNSIGNED NULL");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS method ENUM('card','bank_transfer','cash','manual') NOT NULL DEFAULT 'manual'");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS provider VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS status ENUM('pending','paid','failed','refunded','cancelled') NOT NULL DEFAULT 'pending'");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS amount DECIMAL(10,2) NULL");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS currency CHAR(3) NOT NULL DEFAULT 'EUR'");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS provider_reference VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS gateway_session_id VARCHAR(190) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS gateway_status VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS gateway_payment_status VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS payment_method_type VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS card_brand VARCHAR(64) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS card_last4 VARCHAR(4) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS card_country VARCHAR(2) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS gateway_created_at DATETIME NULL");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS gateway_paid_at DATETIME NULL");
		$wpdb->query("ALTER TABLE {$t['payments']} ADD COLUMN IF NOT EXISTS paid_at DATETIME NULL");
		$payment_booking_idx = $wpdb->get_results("SHOW INDEX FROM {$t['payments']} WHERE Key_name = 'booking_id'");
		if (empty($payment_booking_idx)) {
			$wpdb->query("ALTER TABLE {$t['payments']} ADD INDEX booking_id (booking_id)");
		}
		$payment_invoice_idx = $wpdb->get_results("SHOW INDEX FROM {$t['payments']} WHERE Key_name = 'invoice_id'");
		if (empty($payment_invoice_idx)) {
			$wpdb->query("ALTER TABLE {$t['payments']} ADD INDEX invoice_id (invoice_id)");
		}
		$payment_status_idx = $wpdb->get_results("SHOW INDEX FROM {$t['payments']} WHERE Key_name = 'status'");
		if (empty($payment_status_idx)) {
			$wpdb->query("ALTER TABLE {$t['payments']} ADD INDEX status (status)");
		}
		$payment_provider_ref_idx = $wpdb->get_results("SHOW INDEX FROM {$t['payments']} WHERE Key_name = 'provider_reference'");
		if (empty($payment_provider_ref_idx)) {
			$wpdb->query("ALTER TABLE {$t['payments']} ADD INDEX provider_reference (provider_reference)");
		}
		$payment_gateway_idx = $wpdb->get_results("SHOW INDEX FROM {$t['payments']} WHERE Key_name = 'gateway_session_id'");
		if (empty($payment_gateway_idx)) {
			$wpdb->query("ALTER TABLE {$t['payments']} ADD INDEX gateway_session_id (gateway_session_id)");
		}

		// Ensure provider/source columns are VARCHAR(50)
		$wpdb->query("ALTER TABLE {$t['ical_feeds']} MODIFY provider VARCHAR(50) NOT NULL DEFAULT 'other'");
		$wpdb->query("ALTER TABLE {$t['bookings']} MODIFY source VARCHAR(50) NOT NULL DEFAULT 'direct'");
		$wpdb->query("ALTER TABLE {$t['rates']} MODIFY rule ENUM('per_person_night','per_unit_night','weekend','workday','christmas','new_year','winter','summer','off_season','fixed','single_night') NOT NULL DEFAULT 'per_unit_night'");
		$wpdb->query("ALTER TABLE {$t['rates']} MODIFY operation ENUM('replace','discount_percent','discount_amount','discount_amount_stay','discount_percent_stay','surcharge_percent','surcharge_amount','surcharge_amount_stay','surcharge_percent_stay') NOT NULL DEFAULT 'replace'");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS apply_mode ENUM('date_range','months_of_year','days_of_year') NOT NULL DEFAULT 'date_range'");
		$wpdb->query("ALTER TABLE {$t['rates']} MODIFY apply_mode ENUM('always','date_range','months_of_year','weekdays','annual_dates','days_of_year') NOT NULL DEFAULT 'date_range'");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS months_mask VARCHAR(255) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['rates']} MODIFY months_mask VARCHAR(255) NOT NULL DEFAULT ''");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS day_of_year_from SMALLINT UNSIGNED NULL");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS day_of_year_to SMALLINT UNSIGNED NULL");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS highlight_in_calendar TINYINT(1) NOT NULL DEFAULT 0");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS is_active TINYINT(1) NOT NULL DEFAULT 1");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS show_name_in_breakdown TINYINT(1) NOT NULL DEFAULT 0");
		$wpdb->query("ALTER TABLE {$t['rates']} ADD COLUMN IF NOT EXISTS breakdown_label_i18n LONGTEXT NULL");

		// Seed a couple of common services if empty
		$count = (int) $wpdb->get_var("SELECT COUNT(*) FROM {$t['services']}");
		if ($count === 0) {
			$wpdb->insert($t['services'], ['name'=>'Cleaning', 'code'=>'CLEANING', 'pricing_type'=>'per_stay', 'price'=>0]);
			$wpdb->insert($t['services'], ['name'=>'Bed Linen', 'code'=>'LINEN', 'pricing_type'=>'per_stay', 'price'=>0]);
			$wpdb->insert($t['services'], ['name'=>'Parking', 'code'=>'PARKING', 'pricing_type'=>'per_stay', 'price'=>0]);
			$wpdb->insert($t['services'], ['name'=>'Extra Bed', 'code'=>'EXTRA_BED', 'pricing_type'=>'per_night', 'price'=>0]);
			$wpdb->insert($t['services'], ['name'=>'Tourist Tax', 'code'=>'TOURIST_TAX', 'pricing_type'=>'per_person_night', 'price'=>0]);
			$wpdb->insert($t['services'], ['name'=>'Air Conditioning', 'code'=>'AIR_CONDITIONING', 'pricing_type'=>'per_stay', 'price'=>0]);
			$wpdb->insert($t['services'], ['name'=>'WIFI', 'code'=>'WIFI', 'pricing_type'=>'per_stay', 'price'=>0]);
		}

		self::seed_common_amenities();
	}

	private static function seed_common_amenities() {
		global $wpdb;
		$t = self::tables();
		$amenities = [
			['Wi-Fi', 'WIFI', 'connectivity', 'Wi-Fi'],
			['High-speed internet', 'HIGH_SPEED_INTERNET', 'connectivity', 'Vysokorychlostní internet'],
			['Fiber internet', 'FIBER_INTERNET', 'connectivity', 'Optický internet'],
			['Ethernet connection', 'ETHERNET', 'connectivity', 'Ethernet připojení'],
			['Dedicated workspace', 'WORKSPACE', 'connectivity', 'Pracovní místo'],
			['Desk', 'DESK', 'connectivity', 'Psací stůl'],
			['Office chair', 'OFFICE_CHAIR', 'connectivity', 'Kancelářská židle'],
			['Monitor', 'MONITOR', 'connectivity', 'Monitor'],
			['Printer', 'PRINTER', 'connectivity', 'Tiskárna'],
			['USB charger', 'USB_CHARGER', 'connectivity', 'USB nabíječka'],
			['International power adapter', 'POWER_ADAPTER', 'connectivity', 'Mezinárodní adaptér'],
			['TV', 'TV', 'entertainment', 'TV'],
			['Smart TV', 'SMART_TV', 'entertainment', 'Smart TV'],
			['Cable TV', 'CABLE_TV', 'entertainment', 'Kabelová TV'],
			['Satellite TV', 'SATELLITE_TV', 'entertainment', 'Satelitní TV'],
			['Netflix', 'NETFLIX', 'entertainment', 'Netflix'],
			['HBO Max', 'HBO_MAX', 'entertainment', 'HBO Max'],
			['Disney+', 'DISNEY_PLUS', 'entertainment', 'Disney+'],
			['Amazon Prime Video', 'PRIME_VIDEO', 'entertainment', 'Amazon Prime Video'],
			['Apple TV+', 'APPLE_TV_PLUS', 'entertainment', 'Apple TV+'],
			['YouTube Premium', 'YOUTUBE_PREMIUM', 'entertainment', 'YouTube Premium'],
			['Streaming services', 'STREAMING_SERVICES', 'entertainment', 'Streamovací služby'],
			['Game console', 'GAME_CONSOLE', 'entertainment', 'Herní konzole'],
			['PlayStation', 'PLAYSTATION', 'entertainment', 'PlayStation'],
			['Xbox', 'XBOX', 'entertainment', 'Xbox'],
			['Nintendo Switch', 'NINTENDO_SWITCH', 'entertainment', 'Nintendo Switch'],
			['Board games', 'BOARD_GAMES', 'entertainment', 'Stolní hry'],
			['Books', 'BOOKS', 'entertainment', 'Knihy'],
			['Sound system', 'SOUND_SYSTEM', 'entertainment', 'Audiosystém'],
			['Bluetooth speaker', 'BLUETOOTH_SPEAKER', 'entertainment', 'Bluetooth reproduktor'],
			['Air conditioning', 'AIR_CONDITIONING', 'comfort', 'Klimatizace'],
			['Heating', 'HEATING', 'comfort', 'Topení'],
			['Underfloor heating', 'UNDERFLOOR_HEATING', 'comfort', 'Podlahové vytápění'],
			['Portable heater', 'PORTABLE_HEATER', 'comfort', 'Přenosné topení'],
			['Fireplace', 'FIREPLACE', 'comfort', 'Krb'],
			['Wood stove', 'WOOD_STOVE', 'comfort', 'Kamna na dřevo'],
			['Ceiling fan', 'CEILING_FAN', 'comfort', 'Stropní ventilátor'],
			['Portable fan', 'PORTABLE_FAN', 'comfort', 'Přenosný ventilátor'],
			['Humidifier', 'HUMIDIFIER', 'comfort', 'Zvlhčovač vzduchu'],
			['Air purifier', 'AIR_PURIFIER', 'comfort', 'Čistička vzduchu'],
			['Mosquito nets', 'MOSQUITO_NETS', 'comfort', 'Sítě proti hmyzu'],
			['Blackout curtains', 'BLACKOUT_CURTAINS', 'comfort', 'Zatemňovací závěsy'],
			['Wardrobe', 'WARDROBE', 'bedroom', 'Skříň'],
			['Clothes hangers', 'HANGERS', 'bedroom', 'Ramínka'],
			['Bed linen', 'BED_LINEN', 'bedroom', 'Ložní prádlo'],
			['Extra pillows and blankets', 'EXTRA_PILLOWS_BLANKETS', 'bedroom', 'Polštáře a deky navíc'],
			['Safe', 'SAFE', 'bedroom', 'Trezor'],
			['Room-darkening shades', 'ROOM_DARKENING_SHADES', 'bedroom', 'Zatemnění pokoje'],
			['Baby cot', 'BABY_COT', 'family', 'Dětská postýlka'],
			['High chair', 'HIGH_CHAIR', 'family', 'Dětská židlička'],
			['Baby bath', 'BABY_BATH', 'family', 'Dětská vanička'],
			['Changing table', 'CHANGING_TABLE', 'family', 'Přebalovací pult'],
			['Children books and toys', 'CHILDREN_TOYS', 'family', 'Dětské knihy a hračky'],
			['Children dinnerware', 'CHILDREN_DINNERWARE', 'family', 'Dětské nádobí'],
			['Stair gate', 'STAIR_GATE', 'family', 'Dětská zábrana na schody'],
			['Outlet covers', 'OUTLET_COVERS', 'family', 'Krytky zásuvek'],
			['Kitchen', 'KITCHEN', 'kitchen', 'Kuchyně'],
			['Kitchenette', 'KITCHENETTE', 'kitchen', 'Kuchyňský kout'],
			['Refrigerator', 'REFRIGERATOR', 'kitchen', 'Lednice'],
			['Mini fridge', 'MINI_FRIDGE', 'kitchen', 'Mini lednice'],
			['Freezer', 'FREEZER', 'kitchen', 'Mrazák'],
			['Dishwasher', 'DISHWASHER', 'kitchen', 'Myčka nádobí'],
			['Microwave', 'MICROWAVE', 'kitchen', 'Mikrovlnná trouba'],
			['Oven', 'OVEN', 'kitchen', 'Trouba'],
			['Cooktop', 'COOKTOP', 'kitchen', 'Varná deska'],
			['Induction cooktop', 'INDUCTION_COOKTOP', 'kitchen', 'Indukční varná deska'],
			['Gas stove', 'GAS_STOVE', 'kitchen', 'Plynový sporák'],
			['Coffee maker', 'COFFEE_MAKER', 'kitchen', 'Kávovar'],
			['Espresso machine', 'ESPRESSO_MACHINE', 'kitchen', 'Espresso kávovar'],
			['Capsule coffee machine', 'CAPSULE_COFFEE_MACHINE', 'kitchen', 'Kapslový kávovar'],
			['French press', 'FRENCH_PRESS', 'kitchen', 'French press'],
			['Coffee grinder', 'COFFEE_GRINDER', 'kitchen', 'Mlýnek na kávu'],
			['Kettle', 'KETTLE', 'kitchen', 'Rychlovarná konvice'],
			['Toaster', 'TOASTER', 'kitchen', 'Toustovač'],
			['Blender', 'BLENDER', 'kitchen', 'Mixér'],
			['Rice cooker', 'RICE_COOKER', 'kitchen', 'Rýžovar'],
			['Air fryer', 'AIR_FRYER', 'kitchen', 'Horkovzdušná fritéza'],
			['Water filter', 'WATER_FILTER', 'kitchen', 'Vodní filtr'],
			['Wine glasses', 'WINE_GLASSES', 'kitchen', 'Sklenice na víno'],
			['Baking sheet', 'BAKING_SHEET', 'kitchen', 'Plech na pečení'],
			['Basic cooking essentials', 'COOKING_ESSENTIALS', 'kitchen', 'Základní suroviny na vaření'],
			['Salt and pepper', 'SALT_PEPPER', 'kitchen', 'Sůl a pepř'],
			['Basic cookware', 'COOKWARE', 'kitchen', 'Základní nádobí'],
			['Dishes and cutlery', 'DISHES_CUTLERY', 'kitchen', 'Nádobí a příbory'],
			['Dining table', 'DINING_TABLE', 'kitchen', 'Jídelní stůl'],
			['Dish soap', 'DISH_SOAP', 'kitchen', 'Prostředek na nádobí'],
			['Trash bags', 'TRASH_BAGS', 'kitchen', 'Odpadkové pytle'],
			['Private bathroom', 'PRIVATE_BATHROOM', 'bathroom', 'Vlastní koupelna'],
			['Shared bathroom', 'SHARED_BATHROOM', 'bathroom', 'Sdílená koupelna'],
			['Bathtub', 'BATHTUB', 'bathroom', 'Vana'],
			['Shower', 'SHOWER', 'bathroom', 'Sprcha'],
			['Walk-in shower', 'WALK_IN_SHOWER', 'bathroom', 'Sprchový kout bez vaničky'],
			['Bidet', 'BIDET', 'bathroom', 'Bidet'],
			['Hair dryer', 'HAIR_DRYER', 'bathroom', 'Fén'],
			['Towels', 'TOWELS', 'bathroom', 'Ručníky'],
			['Shampoo', 'SHAMPOO', 'bathroom', 'Šampon'],
			['Shower gel', 'SHOWER_GEL', 'bathroom', 'Sprchový gel'],
			['Conditioner', 'CONDITIONER', 'bathroom', 'Kondicionér'],
			['Soap', 'SOAP', 'bathroom', 'Mýdlo'],
			['Toilet paper', 'TOILET_PAPER', 'bathroom', 'Toaletní papír'],
			['Towel warmer', 'TOWEL_WARMER', 'bathroom', 'Vyhřívaný žebřík'],
			['Makeup mirror', 'MAKEUP_MIRROR', 'bathroom', 'Kosmetické zrcátko'],
			['Washing machine', 'WASHING_MACHINE', 'laundry', 'Pračka'],
			['Dryer', 'DRYER', 'laundry', 'Sušička'],
			['Iron', 'IRON', 'laundry', 'Žehlička'],
			['Ironing board', 'IRONING_BOARD', 'laundry', 'Žehlicí prkno'],
			['Drying rack', 'DRYING_RACK', 'laundry', 'Sušák na prádlo'],
			['Laundry detergent', 'LAUNDRY_DETERGENT', 'laundry', 'Prací prostředek'],
			['Vacuum cleaner', 'VACUUM_CLEANER', 'laundry', 'Vysavač'],
			['Cleaning supplies', 'CLEANING_SUPPLIES', 'laundry', 'Úklidové prostředky'],
			['Balcony', 'BALCONY', 'outdoor', 'Balkon'],
			['Private balcony', 'PRIVATE_BALCONY', 'outdoor', 'Soukromý balkon'],
			['Terrace', 'TERRACE', 'outdoor', 'Terasa'],
			['Private terrace', 'PRIVATE_TERRACE', 'outdoor', 'Soukromá terasa'],
			['Patio', 'PATIO', 'outdoor', 'Patio'],
			['Garden', 'GARDEN', 'outdoor', 'Zahrada'],
			['Private garden', 'PRIVATE_GARDEN', 'outdoor', 'Soukromá zahrada'],
			['Outdoor seating', 'OUTDOOR_SEATING', 'outdoor', 'Venkovní posezení'],
			['Outdoor dining area', 'OUTDOOR_DINING', 'outdoor', 'Venkovní stolování'],
			['Grill', 'GRILL', 'outdoor', 'Gril'],
			['Fire pit', 'FIRE_PIT', 'outdoor', 'Ohniště'],
			['Sun loungers', 'SUN_LOUNGERS', 'outdoor', 'Lehátka'],
			['Hammock', 'HAMMOCK', 'outdoor', 'Houpací síť'],
			['Outdoor shower', 'OUTDOOR_SHOWER', 'outdoor', 'Venkovní sprcha'],
			['Beach essentials', 'BEACH_ESSENTIALS', 'outdoor', 'Vybavení na pláž'],
			['Ski storage', 'SKI_STORAGE', 'outdoor', 'Úložiště lyží'],
			['Bike storage', 'BIKE_STORAGE', 'outdoor', 'Úložiště kol'],
			['Pool', 'POOL', 'wellness', 'Bazén'],
			['Private pool', 'PRIVATE_POOL', 'wellness', 'Soukromý bazén'],
			['Shared pool', 'SHARED_POOL', 'wellness', 'Sdílený bazén'],
			['Indoor pool', 'INDOOR_POOL', 'wellness', 'Vnitřní bazén'],
			['Heated pool', 'HEATED_POOL', 'wellness', 'Vyhřívaný bazén'],
			['Children pool', 'CHILDREN_POOL', 'wellness', 'Dětský bazén'],
			['Hot tub', 'HOT_TUB', 'wellness', 'Vířivka'],
			['Jacuzzi', 'JACUZZI', 'wellness', 'Jacuzzi'],
			['Sauna', 'SAUNA', 'wellness', 'Sauna'],
			['Private sauna', 'PRIVATE_SAUNA', 'wellness', 'Soukromá sauna'],
			['Infrared sauna', 'INFRARED_SAUNA', 'wellness', 'Infrasauna'],
			['Steam room', 'STEAM_ROOM', 'wellness', 'Parní lázeň'],
			['Gym', 'GYM', 'wellness', 'Fitness'],
			['Massage table', 'MASSAGE_TABLE', 'wellness', 'Masážní lehátko'],
			['Parking', 'PARKING', 'parking', 'Parkování'],
			['Free parking', 'FREE_PARKING', 'parking', 'Parkování zdarma'],
			['Paid parking', 'PAID_PARKING', 'parking', 'Placené parkování'],
			['Private parking', 'PRIVATE_PARKING', 'parking', 'Soukromé parkování'],
			['Street parking', 'STREET_PARKING', 'parking', 'Parkování na ulici'],
			['Garage', 'GARAGE', 'parking', 'Garáž'],
			['Carport', 'CARPORT', 'parking', 'Přístřešek pro auto'],
			['EV charger', 'EV_CHARGER', 'parking', 'Nabíječka pro elektromobil'],
			['Bike parking', 'BIKE_PARKING', 'parking', 'Parkování kol'],
			['Motorcycle parking', 'MOTORCYCLE_PARKING', 'parking', 'Parkování motorek'],
			['Self check-in', 'SELF_CHECKIN', 'access', 'Samoobslužný check-in'],
			['Smart lock', 'SMART_LOCK', 'access', 'Chytrý zámek'],
			['Keypad', 'KEYPAD', 'access', 'Číselný zámek'],
			['Lockbox', 'LOCKBOX', 'access', 'Schránka na klíče'],
			['Doorman', 'DOORMAN', 'access', 'Vrátný'],
			['Reception', 'RECEPTION', 'access', 'Recepce'],
			['Luggage drop-off allowed', 'LUGGAGE_DROPOFF', 'access', 'Možnost odložení zavazadel'],
			['Elevator', 'ELEVATOR', 'accessibility', 'Výtah'],
			['Step-free access', 'STEP_FREE_ACCESS', 'accessibility', 'Bezbariérový přístup'],
			['Wide doorway', 'WIDE_DOORWAY', 'accessibility', 'Široké dveře'],
			['Accessible-height bed', 'ACCESSIBLE_BED', 'accessibility', 'Bezbariérová výška postele'],
			['Accessible bathroom', 'ACCESSIBLE_BATHROOM', 'accessibility', 'Bezbariérová koupelna'],
			['Grab rails', 'GRAB_RAILS', 'accessibility', 'Madla'],
			['Shower chair', 'SHOWER_CHAIR', 'accessibility', 'Sprchová židle'],
			['Wheelchair accessible', 'WHEELCHAIR_ACCESSIBLE', 'accessibility', 'Vhodné pro vozíčkáře'],
			['Pets allowed', 'PETS_ALLOWED', 'rules', 'Domácí mazlíčci povoleni'],
			['Dogs allowed', 'DOGS_ALLOWED', 'rules', 'Psi povoleni'],
			['Cats allowed', 'CATS_ALLOWED', 'rules', 'Kočky povoleny'],
			['Smoking allowed', 'SMOKING_ALLOWED', 'rules', 'Kouření povoleno'],
			['No smoking', 'NO_SMOKING', 'rules', 'Zákaz kouření'],
			['Events allowed', 'EVENTS_ALLOWED', 'rules', 'Akce povoleny'],
			['Long-term stays allowed', 'LONG_TERM_STAYS', 'rules', 'Dlouhodobé pobyty povoleny'],
			['Smoke alarm', 'SMOKE_ALARM', 'safety', 'Detektor kouře'],
			['Carbon monoxide alarm', 'CO_ALARM', 'safety', 'Detektor oxidu uhelnatého'],
			['Fire extinguisher', 'FIRE_EXTINGUISHER', 'safety', 'Hasicí přístroj'],
			['First aid kit', 'FIRST_AID_KIT', 'safety', 'Lékárnička'],
			['Security cameras outside', 'SECURITY_CAMERAS_OUTSIDE', 'safety', 'Venkovní bezpečnostní kamery'],
			['Smart doorbell', 'SMART_DOORBELL', 'safety', 'Chytrý zvonek'],
			['Emergency lighting', 'EMERGENCY_LIGHTING', 'safety', 'Nouzové osvětlení'],
			['Safe deposit box', 'SAFE_DEPOSIT_BOX', 'safety', 'Bezpečnostní schránka'],
		];

		$existing_ids = [];
		$rows = $wpdb->get_results("SELECT id, code FROM {$t['amenities']}", ARRAY_A);
		foreach ((array) $rows as $row) {
			$existing_ids[(string) $row['code']] = (int) $row['id'];
		}

		foreach ($amenities as $idx => $amenity) {
			$code = (string) $amenity[1];
			$amenity_id = $existing_ids[$code] ?? 0;
			if ($amenity_id <= 0) {
				$wpdb->insert($t['amenities'], [
					'name' => $amenity[0],
					'code' => $code,
					'category' => $amenity[2],
					'sort_order' => ($idx + 1) * 10,
				]);
				$amenity_id = (int) $wpdb->insert_id;
				$existing_ids[$code] = $amenity_id;
			}
			if ($amenity_id > 0) {
				$cs_label = $wpdb->get_row($wpdb->prepare(
					"SELECT id, meta_value FROM {$t['amenity_meta']} WHERE amenity_id=%d AND meta_key=%s AND locale=%s LIMIT 1",
					$amenity_id,
					'label',
					'cs'
				), ARRAY_A);
				if (empty($cs_label['id'])) {
					$wpdb->insert($t['amenity_meta'], [
						'amenity_id' => $amenity_id,
						'meta_key' => 'label',
						'meta_value' => $amenity[3],
						'locale' => 'cs',
					]);
				} elseif ((string) $cs_label['meta_value'] !== (string) $amenity[3]) {
					$wpdb->update(
						$t['amenity_meta'],
						['meta_value' => $amenity[3]],
						['id' => (int) $cs_label['id']]
					);
				}
			}
		}
	}

	public static function unit_exists($unit_id) {
		$p = get_post($unit_id);
		return $p && $p->post_type === 'vstrb_unit' && $p->post_status !== 'trash';
	}
	// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.SchemaChange, WordPress.DB.SlowDBQuery.slow_db_query_meta_key, WordPress.DB.SlowDBQuery.slow_db_query_meta_value, PluginCheck.Security.DirectDB.UnescapedDBParameter
}
