<?php
/**
 * Feed CRUD against rbfb_feeds.
 *
 * @package RewindBrevoFormBridge
 */

namespace RewindBrevoFormBridge\Feeds;

defined( 'ABSPATH' ) || exit;

/*
 * Every query below reads or writes this plugin's own custom table. There is
 * no WordPress API for these rows, so a direct $wpdb call is the only option.
 * The table holds a handful of feeds and is read on the admin screen, so an
 * object cache would add an invalidation path for no measurable gain. Table
 * names are passed to $wpdb->prepare() as %i identifier placeholders (WP 6.2+;
 * this plugin requires 6.6), so every query goes through prepare().
 */
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter

/**
 * All database access for feeds. Every query goes through $wpdb->prepare();
 * the table name is interpolated from $wpdb->prefix only.
 *
 * @since 0.3.0
 */
class Repository {

	/**
	 * Fully-prefixed table name.
	 *
	 * @since 0.3.0
	 * @return string
	 */
	private function table(): string {
		global $wpdb;

		return $wpdb->prefix . 'rbfb_feeds';
	}

	/**
	 * One feed by id.
	 *
	 * @since 0.3.0
	 * @param int $id Feed id.
	 * @return Feed|null
	 */
	public function find( int $id ): ?Feed {
		global $wpdb;

		$table = $this->table();
		$row   = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM %i WHERE id = %d', $table, $id ) );

		return $row ? Feed::from_row( $row ) : null;
	}

	/**
	 * Every feed, newest first.
	 *
	 * @since 0.3.0
	 * @param int $limit  Max rows.
	 * @param int $offset Offset.
	 * @return Feed[]
	 */
	public function all( int $limit = 100, int $offset = 0 ): array {
		global $wpdb;

		$table = $this->table();
		$rows  = $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT %d OFFSET %d', $table, $limit, $offset ) );

		return array_map( array( Feed::class, 'from_row' ), $rows ? $rows : array() );
	}

	/**
	 * Total feed count.
	 *
	 * @since 0.3.0
	 * @return int
	 */
	public function count(): int {
		global $wpdb;

		$table = $this->table();

		return (int) $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(*) FROM %i', $table ) );
	}

	/**
	 * All ACTIVE feeds for one (adapter, form) pair. Multiple feeds per form
	 * is a requirement, not a nice-to-have.
	 *
	 * @since 0.3.0
	 * @param string $adapter Adapter slug.
	 * @param string $form_id Form id.
	 * @return Feed[]
	 */
	public function find_for( string $adapter, string $form_id ): array {
		global $wpdb;

		$table = $this->table();
		$rows  = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT * FROM %i WHERE adapter = %s AND form_id = %s AND status = 'active' ORDER BY id ASC",
				$table,
				$adapter,
				$form_id
			)
		);

		return array_map( array( Feed::class, 'from_row' ), $rows ? $rows : array() );
	}

	/**
	 * Insert a feed.
	 *
	 * @since 0.3.0
	 * @param string $adapter Adapter slug.
	 * @param string $form_id Form id.
	 * @param string $title   Title.
	 * @param string $status  'active' | 'paused'.
	 * @param array  $config  Config to JSON-encode.
	 * @return int New feed id, 0 on failure.
	 */
	public function insert( string $adapter, string $form_id, string $title, string $status, array $config ): int {
		global $wpdb;

		$now = current_time( 'mysql', true );

		$ok = $wpdb->insert(
			$this->table(),
			array(
				'adapter'    => $adapter,
				'form_id'    => $form_id,
				'title'      => $title,
				'status'     => $status,
				'config'     => wp_json_encode( $config ),
				'created_at' => $now,
				'updated_at' => $now,
			),
			array( '%s', '%s', '%s', '%s', '%s', '%s', '%s' )
		);

		return $ok ? (int) $wpdb->insert_id : 0;
	}

	/**
	 * Update a feed.
	 *
	 * @since 0.3.0
	 * @param int    $id      Feed id.
	 * @param string $adapter Adapter slug.
	 * @param string $form_id Form id.
	 * @param string $title   Title.
	 * @param string $status  'active' | 'paused'.
	 * @param array  $config  Config to JSON-encode.
	 * @return bool
	 */
	public function update( int $id, string $adapter, string $form_id, string $title, string $status, array $config ): bool {
		global $wpdb;

		$ok = $wpdb->update(
			$this->table(),
			array(
				'adapter'    => $adapter,
				'form_id'    => $form_id,
				'title'      => $title,
				'status'     => $status,
				'config'     => wp_json_encode( $config ),
				'updated_at' => current_time( 'mysql', true ),
			),
			array( 'id' => $id ),
			array( '%s', '%s', '%s', '%s', '%s', '%s' ),
			array( '%d' )
		);

		return false !== $ok;
	}

	/**
	 * Delete a feed.
	 *
	 * @since 0.3.0
	 * @param int $id Feed id.
	 * @return bool
	 */
	public function delete( int $id ): bool {
		global $wpdb;

		return (bool) $wpdb->delete( $this->table(), array( 'id' => $id ), array( '%d' ) );
	}
}

// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
