<?php

namespace Yoast\WP\SEO\Tests\Unit\Helpers;

use Brain\Monkey;
use Mockery;
use Yoast\WP\SEO\Helpers\Options_Helper;
use Yoast\WP\SEO\Helpers\Social_Profiles_Helper;
use Yoast\WP\SEO\Tests\Unit\TestCase;

/**
 * Social_Profiles_Helper_Test
 *
 * @coversDefaultClass \Yoast\WP\SEO\Helpers\Social_Profiles_Helper
 */
final class Social_Profiles_Helper_Test extends TestCase {

	/**
	 * The Social_Profiles_Helper instance to be tested.
	 *
	 * @var Social_Profiles_Helper
	 */
	protected $instance;

	/**
	 * The option helper.
	 *
	 * @var Mockery\MockInterface|Options_Helper
	 */
	protected $options_helper;

	/**
	 * Set up the test fixtures.
	 *
	 * @return void
	 */
	public function set_up() {
		parent::set_up();

		$this->options_helper = Mockery::mock( Options_Helper::class );
		$this->instance       = new Social_Profiles_Helper( $this->options_helper );
	}

	/**
	 * Checks storing the values for the person's social profiles.
	 *
	 * @covers ::set_person_social_profiles
	 * @covers ::get_non_valid_url
	 * @covers ::get_non_valid_twitter
	 *
	 * @dataProvider set_person_social_profiles
	 *
	 * @param array $social_profiles             The array of the person's social profiles to be set.
	 * @param array $validate_social_url_results The results from validating social urls.
	 * @param int   $validate_social_url_times   The times we're gonna validate social urls.
	 * @param array $validate_twitter_id_results The results from validating twitter ids.
	 * @param int   $validate_twitter_id_times   The times we're gonna validate twitter ids.
	 * @param int   $update_user_meta_times      The times we're gonna set the the social profiles.
	 * @param array $expected                    The expected field names which failed to be saved in the db.
	 *
	 * @return void
	 */
	public function test_set_person_social_profiles( $social_profiles, $validate_social_url_results, $validate_social_url_times, $validate_twitter_id_results, $validate_twitter_id_times, $update_user_meta_times, $expected ) {
		$person_id = 123;
		$fields    = [
			'facebook',
			'instagram',
			'linkedin',
			'myspace',
			'pinterest',
			'soundcloud',
			'tumblr',
			'twitter',
			'youtube',
			'wikipedia',
		];

		$this->options_helper
			->expects( 'is_social_url_valid' )
			->times( $validate_social_url_times )
			->andReturn( ...$validate_social_url_results );

		$this->options_helper
			->expects( 'is_twitter_id_valid' )
			->times( $validate_twitter_id_times )
			->andReturn( ...$validate_twitter_id_results );

		foreach ( $fields as $field ) {
			Monkey\Functions\expect( 'update_user_meta' )
				->with( $person_id, $field, $social_profiles[ $field ] )
				->times( $update_user_meta_times );
		}

		$actual = $this->instance->set_person_social_profiles( $person_id, $social_profiles );
		$this->assertEquals( $expected, $actual );
	}

	/**
	 * Dataprovider for test_set_person_social_profiles function.
	 *
	 * @return array Data for test_set_person_social_profiles function.
	 */
	public static function set_person_social_profiles() {
		$success_all = [
			'social_profiles'             => [
				'facebook'   => 'https://facebook.com/janedoe',
				'instagram'  => 'https://instagram.com/janedoe',
				'linkedin'   => 'https://linkedin.com/janedoe',
				'myspace'    => 'https://myspace.com/janedoe',
				'pinterest'  => 'https://pinterest.com/janedoe',
				'soundcloud' => 'https://soundcloud.com/janedoe',
				'tumblr'     => 'https://tumblr.com/janedoe',
				'twitter'    => 'https://twitter.com/janedoe',
				'youtube'    => 'https://youtube.com/janedoe',
				'wikipedia'  => 'https://wikipedia.com/janedoe',
			],
			'validate_social_url_results' => [ true ],
			'validate_social_url_times'   => 9,
			'validate_twitter_id_results' => [ true ],
			'validate_twitter_id_times'   => 1,
			'update_user_meta_times'      => 1,
			'expected'                    => [],
		];

		$failure_some = [
			'social_profiles'             => [
				'facebook'   => 'https://facebook.com/janedoe',
				'instagram'  => 'https://instagram.com/janedoe',
				'linkedin'   => 'https://linkedin.com/janedoe',
				'myspace'    => 'https://myspace.com/janedoe',
				'pinterest'  => 'https://pinterest.com/janedoe',
				'soundcloud' => 'https://soundcloud.com/janedoe',
				'tumblr'     => 'https://tumblr.com/janedoe',
				'twitter'    => '@janedoe',
				'youtube'    => 'https://youtube.com/janedoe',
				'wikipedia'  => 'https://wikipedia.com/janedoe',
			],
			'validate_social_url_results' => [ true, true, true, true, true, true, true, true, true ],
			'validate_social_url_times'   => 9,
			'validate_twitter_id_results' => [ false ],
			'validate_twitter_id_times'   => 1,
			'update_user_meta_times'      => 0,
			'expected'                    => [ 'twitter' ],
		];

		$failure_twitter = [
			'social_profiles'             => [
				'facebook'   => 'https://facebook.com/janedoe',
				'instagram'  => 'test',
				'linkedin'   => 'https://linkedin.com/janedoe',
				'myspace'    => 'https://myspace.com/janedoe',
				'pinterest'  => 'https://pinterest.com/janedoe',
				'soundcloud' => 'https://soundcloud.com/janedoe',
				'tumblr'     => 'https://tumblr.com/janedoe',
				'twitter'    => 'https://twitter.com/janedoe',
				'youtube'    => 'https://youtube.com/janedoe',
				'wikipedia'  => 'https://wikipedia.com/janedoe',
			],
			'validate_social_url_results' => [ true, false, true, true, true, true, true, true, true ],
			'validate_social_url_times'   => 9,
			'validate_twitter_id_results' => [ true ],
			'validate_twitter_id_times'   => 1,
			'update_user_meta_times'      => 0,
			'expected'                    => [ 'instagram' ],
		];

		$failure_all = [
			'social_profiles'             => [
				'facebook'   => 'test',
				'instagram'  => 'test',
				'linkedin'   => 'test',
				'myspace'    => 'test',
				'pinterest'  => 'test',
				'soundcloud' => 'test',
				'tumblr'     => 'test',
				'twitter'    => 'test',
				'youtube'    => 'test',
				'wikipedia'  => 'test',
			],
			'validate_social_url_results' => [ false, false, false, false, false, false, false, false, false ],
			'validate_social_url_times'   => 9,
			'validate_twitter_id_results' => [ false ],
			'validate_twitter_id_times'   => 1,
			'update_user_meta_times'      => 0,
			'expected'                    => [ 'facebook', 'instagram', 'linkedin', 'myspace', 'pinterest', 'soundcloud', 'tumblr', 'twitter', 'youtube', 'wikipedia' ],
		];

		return [
			'Successful set with all valid values'      => $success_all,
			'Failed set with some non-valid values'     => $failure_some,
			'Failed set with a twitter non-valid value' => $failure_twitter,
			'Failed set with all non-valid value'       => $failure_all,
		];
	}

	/**
	 * Checks storing the values for the organization's social profiles.
	 *
	 * @covers ::set_organization_social_profiles
	 * @covers ::get_non_valid_url
	 * @covers ::get_non_valid_url_array
	 * @covers ::get_non_valid_twitter
	 *
	 * @dataProvider set_organization_social_profiles
	 *
	 * @param array $social_profiles             The array of the person's social profiles to be set.
	 * @param array $validate_social_url_results The results from validating social urls.
	 * @param int   $validate_social_url_times   The times we're gonna validate social urls.
	 * @param array $validate_twitter_id_results The results from validating twitter ids.
	 * @param int   $validate_twitter_id_times   The times we're gonna validate twitter ids.
	 * @param int   $set_option_times            The times we're gonna set the social profiles.
	 * @param array $expected                    The expected field names which failed to be saved in the db.
	 *
	 * @return void
	 */
	public function test_set_organization_social_profiles( $social_profiles, $validate_social_url_results, $validate_social_url_times, $validate_twitter_id_results, $validate_twitter_id_times, $set_option_times, $expected ) {
		$fields = [
			'facebook_site',
			'twitter_site',
			'other_social_urls',
		];

		$this->options_helper
			->expects( 'is_social_url_valid' )
			->times( $validate_social_url_times )
			->andReturn( ...$validate_social_url_results );

		$this->options_helper
			->expects( 'is_twitter_id_valid' )
			->times( $validate_twitter_id_times )
			->andReturn( ...$validate_twitter_id_results );

		foreach ( $fields as $field ) {
			if ( $field === 'other_social_urls' ) {
				$social_profiles[ $field ] = \array_filter(
					$social_profiles[ $field ],
					static function ( $other_social_url ) {
						return $other_social_url !== '';
					}
				);
			}

			$this->options_helper
				->expects( 'set' )
				->with( $field, $social_profiles[ $field ] )
				->times( $set_option_times )
				->andReturn( true );
		}

		$this->options_helper
			->expects( 'get' )
			->never();

		$actual = $this->instance->set_organization_social_profiles( $social_profiles );
		$this->assertEquals( $expected, $actual );
	}

	/**
	 * Dataprovider for test_set_organization_social_profiles function.
	 *
	 * @return array Data for test_set_organization_social_profiles function.
	 */
	public static function set_organization_social_profiles() {
		$success_all = [
			'social_profiles'             => [
				'facebook_site'          => '',
				'twitter_site'           => 'https://twitter.com/janedoe',
				'other_social_urls'      => [
					'https://youtube.com/janedoe',
					'',
				],
			],
			'validate_social_url_results' => [ true ],
			'validate_social_url_times'   => 2,
			'validate_twitter_id_results' => [ true ],
			'validate_twitter_id_times'   => 1,
			'set_option_times'            => 1,
			'expected'                    => [],
		];

		$failure_fb = [
			'social_profiles'             => [
				'facebook_site'          => 'not valid',
				'twitter_site'           => 'https://twitter.com/janedoe',
				'other_social_urls'      => [
					'https://youtube.com/janedoe',
				],
			],
			'validate_social_url_results' => [ false, true ],
			'validate_social_url_times'   => 2,
			'validate_twitter_id_results' => [ true ],
			'validate_twitter_id_times'   => 1,
			'set_option_times'            => 0,
			'expected'                    => [ 'facebook_site' ],
		];

		$failure_twitter = [
			'social_profiles'             => [
				'facebook_site'          => 'https://facebook.com/janedoe',
				'twitter_site'           => 'not valid',
				'other_social_urls'      => [
					'https://youtube.com/janedoe',
					'https://instagram.com/janedoe',
				],
			],
			'validate_social_url_results' => [ true, true ],
			'validate_social_url_times'   => 3,
			'validate_twitter_id_results' => [ false ],
			'validate_twitter_id_times'   => 1,
			'set_option_times'            => 0,
			'expected'                    => [ 'twitter_site' ],
		];

		$failure_other_social = [
			'social_profiles'             => [
				'facebook_site'          => 'https://facebook.com/janedoe',
				'twitter_site'           => 'https://twitter.com/janedoe',
				'other_social_urls'      => [
					'not valid',
					'https://instagram.com/janedoe',
					'not valid again',
				],
			],
			'validate_social_url_results' => [ true, false, true, false ],
			'validate_social_url_times'   => 4,
			'validate_twitter_id_results' => [ true ],
			'validate_twitter_id_times'   => 1,
			'set_option_times'            => 0,
			'expected'                    => [ 'other_social_urls-0', 'other_social_urls-2' ],
		];

		return [
			'Successful set with all valid values'        => $success_all,
			'Failed set with not valid Facebook'          => $failure_fb,
			'Failed set with not valid Twitter'           => $failure_twitter,
			'Failed set with not valid other social urls' => $failure_other_social,
		];
	}

	/**
	 * Checks getting the values for the organization's social profiles.
	 *
	 * @covers ::get_organization_social_profiles
	 * @covers ::get_organization_social_profile_fields
	 *
	 * @dataProvider get_organization_social_profiles_provider
	 *
	 * @param array<string, string|array<string>>      $social_profiles The array of the organization's social profiles to be set.
	 * @param array<string, string|array<int, string>> $default_value   The default values for the social profiles.
	 * @param array<string, string|array<string>>      $expected        The expected field names which failed to be saved in the db.
	 *
	 * @return void
	 */
	public function test_get_organization_social_profiles( $social_profiles, $default_value, $expected ) {
		$fields = [
			'facebook_site',
			'twitter_site',
			'other_social_urls',
		];

		$organization_social_profile_fields = [
			'facebook_site'     => 'get_non_valid_url',
			'twitter_site'      => 'get_non_valid_twitter',
			'other_social_urls' => 'get_non_valid_url_array',
		];

		Monkey\Functions\expect( 'apply_filters' )
			->once()
			->with( 'wpseo_organization_social_profile_fields', $organization_social_profile_fields )
			->andReturn( $organization_social_profile_fields );

		foreach ( $fields as $field ) {
			$this->options_helper
				->expects( 'get' )
				->with( $field, $default_value[ $field ] )
				->andReturn( $social_profiles[ $field ] );
		}

		$actual = $this->instance->get_organization_social_profiles();
		$this->assertEquals( $expected, $actual );
	}

	/**
	 * Dataprovider for test_get_organization_social_profiles function.
	 *
	 * @return array<string, array<string, string|array<string, string>>> Data for test_get_organization_social_profiles function.
	 */
	public static function get_organization_social_profiles_provider() {
		yield 'Successful get with all valid values' => [
			'social_profiles' => [
				'facebook_site'     => 'https://facebook.com/janedoe',
				'twitter_site'      => 'janedoe',
				'other_social_urls' => [
					'https://youtube.com/janedoe',
					'https://instagram.com/janedoe',
				],
			],
			'default_value' => [
				'facebook_site'     => '',
				'twitter_site'      => '',
				'other_social_urls' => [],
			],
			'expected'        => [
				'facebook_site'     => 'https://facebook.com/janedoe',
				'twitter_site'      => 'https://x.com/janedoe',
				'other_social_urls' => [
					'https://youtube.com/janedoe',
					'https://instagram.com/janedoe',
				],
			],
		];

		yield 'Empty get with all empty values' => [
			'social_profiles' => [
				'facebook_site'     => '',
				'twitter_site'      => '',
				'other_social_urls' => [],
			],
			'default_value' => [
				'facebook_site'     => '',
				'twitter_site'      => '',
				'other_social_urls' => [],
			],
			'expected'        => [
				'facebook_site'     => '',
				'twitter_site'      => '',
				'other_social_urls' => [],
			],
		];
	}
}
