<?php

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Pixelmole_Followup_Email_Store {
	const TABLE = 'pixelmole_followup_emails';

	/** @var bool|null */
	private $table_exists_cache = null;

	public function maybe_create_table() {
		if ( $this->table_exists() ) {
			return;
		}

		self::create_table();
		$this->table_exists_cache = true;
	}

	public static function create_table() {
		global $wpdb;

		$table_name = self::get_table_name();
		if ( empty( $table_name ) ) {
			return;
		}

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';

		$charset_collate = $wpdb->get_charset_collate();
		$sql             = "CREATE TABLE {$table_name} (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			enabled tinyint(1) NOT NULL DEFAULT 0,
			from_name varchar(255) NOT NULL DEFAULT '',
			from_email varchar(255) NOT NULL DEFAULT '',
			subject text NOT NULL,
			body longtext NOT NULL,
			delay_amount int(10) unsigned NOT NULL DEFAULT 0,
			delay_unit varchar(20) NOT NULL DEFAULT 'days',
			position int(10) unsigned NOT NULL DEFAULT 0,
			created_at datetime NOT NULL,
			updated_at datetime NOT NULL,
			PRIMARY KEY  (id),
			KEY enabled (enabled),
			KEY position (position)
		) {$charset_collate};";

		dbDelta( $sql );
	}

	public static function drop_table() {
		global $wpdb;

		$table_name = self::get_table_name();
		if ( empty( $table_name ) ) {
			return;
		}

		// Table name is not user input; esc_sql() for extra safety.
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.SchemaChange -- need to drop plugin table on uninstall.
		$wpdb->query( 'DROP TABLE IF EXISTS `' . esc_sql( $table_name ) . '`' );
	}

	public function table_exists() {
		if ( null !== $this->table_exists_cache ) {
			return (bool) $this->table_exists_cache;
		}

		global $wpdb;
		$table_name = self::get_table_name();
		if ( empty( $table_name ) ) {
			return false;
		}

		$like   = $wpdb->esc_like( $table_name );
		$result = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $like ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching

		$this->table_exists_cache = ( $result === $table_name );

		return (bool) $this->table_exists_cache;
	}

	public function get_primary_email() {
		if ( ! $this->table_exists() ) {
			return [];
		}

		global $wpdb;
		$table_name = self::get_table_name();

		$row = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
			'SELECT id, enabled, from_name, from_email, subject, body, delay_amount, delay_unit FROM `' . esc_sql( $table_name ) . '` ORDER BY position ASC, id ASC LIMIT 1',
			ARRAY_A
		);

		if ( empty( $row ) ) {
			return [];
		}

		return [
			'enabled'      => (int) $row['enabled'],
			'from_name'    => (string) $row['from_name'],
			'from_email'   => (string) $row['from_email'],
			'subject'      => (string) $row['subject'],
			'body'         => (string) $row['body'],
			'delay_amount' => (int) $row['delay_amount'],
			'delay_unit'   => (string) $row['delay_unit'],
		];
	}

	public function upsert_primary_email( array $settings ) {
		if ( ! $this->table_exists() ) {
			$this->maybe_create_table();
		}

		global $wpdb;
		$table_name = self::get_table_name();
		if ( empty( $table_name ) ) {
			return 0;
		}

		$existing = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
			'SELECT id FROM `' . esc_sql( $table_name ) . '` ORDER BY position ASC, id ASC LIMIT 1',
			ARRAY_A
		);

		$data = [
			'enabled'      => ! empty( $settings['enabled'] ) ? 1 : 0,
			'from_name'    => isset( $settings['from_name'] ) ? (string) $settings['from_name'] : '',
			'from_email'   => isset( $settings['from_email'] ) ? (string) $settings['from_email'] : '',
			'subject'      => isset( $settings['subject'] ) ? (string) $settings['subject'] : '',
			'body'         => isset( $settings['body'] ) ? (string) $settings['body'] : '',
			'delay_amount' => isset( $settings['delay_amount'] ) ? absint( $settings['delay_amount'] ) : 0,
			'delay_unit'   => isset( $settings['delay_unit'] ) ? (string) $settings['delay_unit'] : 'days',
			'updated_at'   => current_time( 'mysql', true ),
		];

		if ( ! empty( $existing['id'] ) ) {
			$wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
				$table_name,
				$data,
				[ 'id' => absint( $existing['id'] ) ],
				[ '%d', '%s', '%s', '%s', '%s', '%d', '%s', '%s' ],
				[ '%d' ]
			);

			return (int) $existing['id'];
		}

		$data['position']   = 0;
		$data['created_at'] = current_time( 'mysql', true );

		$wpdb->insert( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
			$table_name,
			$data,
			[ '%d', '%s', '%s', '%s', '%s', '%d', '%s', '%s', '%d', '%s' ]
		);

		return (int) $wpdb->insert_id;
	}

	public function maybe_migrate_from_option( $option_key, array $defaults ) {
		if ( ! $this->table_exists() ) {
			$this->maybe_create_table();
		}

		if ( ! $this->table_exists() ) {
			return;
		}

		global $wpdb;
		$table_name = self::get_table_name();

		$existing = (int) $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
			'SELECT COUNT(*) FROM `' . esc_sql( $table_name ) . '`'
		);

		if ( $existing > 0 ) {
			return;
		}

		$option = get_option( $option_key, [] );
		if ( empty( $option ) || ! is_array( $option ) ) {
			return;
		}

		$settings = wp_parse_args( $option, $defaults );
		$inserted = $this->upsert_primary_email( $settings );

		if ( $inserted ) {
			delete_option( $option_key );
		}
	}

	private static function get_table_name() {
		global $wpdb;

		if ( empty( $wpdb->prefix ) ) {
			return '';
		}

		return $wpdb->prefix . self::TABLE;
	}
}
