<?php
/**
 * File Path: includes/data/class-mbs-author-social-link-dao.php
 *
 * Author Social Link DAO
 *
 * Replaces the mbs_author_social_links term meta JSON blob (RF-012).
 * Table created by MBS_DB_Schema::author_social_links() / MBS_Migration_4_23.
 *
 * Each social link is stored as one row (term_id, platform, url, sort_order).
 * save_for_term() replaces all links for one author atomically.
 * get_for_term() returns links in the same [{platform, url}] format previously
 * decoded from the JSON blob, so MBS_Author_Social_Links::decode_social_links()
 * callers see no interface change.
 *
 * @package MyBookShowroom
 * @since   1.3.0
 */

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

/**
 * Class MBS_Author_Social_Link_DAO
 *
 * @since 1.3.0
 */
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- DAO/migration: table names via $wpdb->prefix are trusted server-controlled values, not user input
// phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter -- same reason: $wpdb->prefix table names are safe; $where_sql is built from sanitized server-controlled inputs
class MBS_Author_Social_Link_DAO { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedClassFound -- mbs_/MBS_ prefix is correct; scanner not configured with plugin prefix

	// ── Write operations ────────────────────────────────────────────────────

	/**
	 * Replace all social links for a given author term.
	 *
	 * Deletes every existing row for $term_id, then inserts each entry
	 * from $links. Each entry must have at minimum 'platform' and 'url';
	 * 'label' is carried through for custom platforms.
	 *
	 * @param  int   $term_id Author taxonomy term ID.
	 * @param  array $links   Sanitized social link entries: [{platform, url[, label]}].
	 * @return void
	 * @since  1.3.0
	 */
	public static function save_for_term( int $term_id, array $links ): void {
		global $wpdb;
		$table = $wpdb->prefix . 'mbs_author_social_links';
		$now   = current_time( 'mysql', true ); // UTC (A-005).

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$wpdb->delete( $table, array( 'term_id' => $term_id ), array( '%d' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery -- DAO layer -- direct DB access is intentional per MBS architecture

		foreach ( $links as $i => $link ) {
			if ( ! is_array( $link ) ) {
				continue;
			}
			$platform = sanitize_key( $link['platform'] ?? '' );
			$url      = esc_url_raw( $link['url'] ?? '' );
			if ( '' === $platform || '' === $url ) {
				continue;
			}
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
			$wpdb->insert(
				$table,
				array(
					'term_id'    => $term_id,
					'platform'   => $platform,
					'url'        => $url,
					'sort_order' => $i,
					'created_at' => $now,
					'updated_at' => $now,
				),
				array( '%d', '%s', '%s', '%d', '%s', '%s' )
			);
		}
	}

	// ── Read operations ─────────────────────────────────────────────────────

	/**
	 * Return all social links for a given author term, ordered by sort_order.
	 *
	 * Returns an array of associative arrays in the same format previously
	 * returned by MBS_Author_Social_Links::decode_social_links() (JSON blob
	 * decode): each element has 'platform' and 'url' keys (and optionally
	 * 'label' for custom platform types -- not currently stored; field
	 * included for interface compatibility).
	 *
	 * @param  int $term_id Author taxonomy term ID.
	 * @return array<int, array{platform: string, url: string}>
	 * @since  1.3.0
	 */
	public static function get_for_term( int $term_id ): array {
		global $wpdb;
		$table = $wpdb->prefix . 'mbs_author_social_links';

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.PreparedSQL.InterpolatedNotPrepared
		$rows = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.DirectQuery -- DAO layer -- direct DB access is intentional per MBS architecture
			$wpdb->prepare(
				"SELECT platform, url FROM `{$table}` WHERE term_id = %d ORDER BY sort_order ASC",
				$term_id
			),
			ARRAY_A
		);

		return is_array( $rows ) ? $rows : array();
	}
}
