<?php
namespace SabaiApps\Directories\Component\WordPressUser\EntityType;

use SabaiApps\Directories\Component\User\EntityType\AbstractUserEntityType;
use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Exception;
use SabaiApps\Framework\User\AbstractIdentity;

class UserEntityType extends AbstractUserEntityType {

	protected function _getEntityTypeInfo() {
		return array(
			'table_name' => $GLOBALS['wpdb']->users,
			'properties' => array(
				'id'        => array(
					'type'        => 'entity_id',
					'column_type' => Application::COLUMN_INTEGER,
					'column'      => 'ID',
				),
				'author'    => array(
					'type'        => 'entity_id',
					'column_type' => Application::COLUMN_INTEGER,
					'column'      => 'ID',
				),
				'title'     => array(
					'type'       => 'user_name',
					'column'     => 'display_name',
					'field_name' => 'user_name',
				),
				'slug'      => array(
					'type'        => 'entity_slug',
					'column_type' => Application::COLUMN_VARCHAR,
					'column'      => 'user_slug',
				),
				'email'     => array(
					'type'        => 'user_email',
					'column_type' => Application::COLUMN_VARCHAR,
					'column'      => 'user_email',
				),
				'url'       => array(
					'type'        => 'user_url',
					'column_type' => Application::COLUMN_VARCHAR,
					'column'      => 'user_url',
				),
				'published' => array(
					'type'        => 'entity_published',
					'column_type' => Application::COLUMN_VARCHAR,
					'column'      => 'user_registered',
				),
			),
		);
	}

	public function entityTypeEntityById( $entityId ) {
		return ( $user = get_user_by( 'ID', $entityId ) ) ? new UserEntity( $user ) : false;
	}

	public function entityTypeEntityBySlug( $bundleName, $slug ) {
		return ( $user = get_user_by( 'slug', $slug ) ) ? new UserEntity( $user ) : false;
	}

	public function entityTypeEntityByTitle( $bundleName, $title ) {
		global $wpdb;
		if ( ! $user = $wpdb->get_row( $wpdb->prepare( 'SELECT * FROM $wpdb->users WHERE `display_name` = %s', $title ) ) ) {
			return false;
		}

		return new UserEntity( $user );
	}

	public function entityTypeEntitiesByIds( array $entityIds, $bundleName = null, $lang = null ) {
		return $this->_getEntities(
			array(
				'include' => $entityIds,
			)
		);
	}

	public function entityTypeEntitiesBySlugs( $bundleName, array $slugs, $lang = null ) {
		global $wpdb;
		$users    = $wpdb->get_results(
			sprintf(
				'SELECT * FROM %s WHERE user_slug IN (`%s`)',
				$wpdb->users,
				implode( '`, `', array_map( 'esc_sql', $slugs ) )
			)
		);
		$entities = array();
		foreach ( $users as $user ) {
			$entities[ $user->ID ] = new UserEntity( $user );
		}
		return $entities;
	}

	protected function _getEntities( array $args ) {
		$entities = array();
		foreach ( get_users( $args ) as $user ) {
			$entities[ $user->ID ] = new UserEntity( $user );
		}
		return $entities;
	}

	public function entityTypeUpdateEntity( IEntity $entity, Bundle $bundle, array $properties ) {
		$data = array();
		foreach ( array_keys( $properties ) as $property ) {
			switch ( $property ) {
				case 'title':
					$data['display_name'] = $properties[ $property ]['display_name'];
					$data['first_name']   = $properties[ $property ]['first_name'];
					$data['last_name']    = $properties[ $property ]['last_name'];
					break;
				case 'email':
					$data['user_email'] = $properties[ $property ];
					break;
				case 'url':
					$data['user_url'] = $properties[ $property ];
					break;
			}
		}
		if ( ! empty( $data ) ) {
			$data['ID'] = $entity->getId();
			$result     = wp_update_user( $data );
			if ( is_wp_error( $result ) ) {
				throw new Exception\RuntimeException( $result->get_error_message() );
			}
			if ( $entity->isFieldsLoaded() ) {
				$entity->initFields( $entity->getFieldValues(), $entity->getFieldTypes() );
			}
		}

		return $entity;
	}

	public function entityTypeRandomEntityIds( $bundleName, $num ) {
		$args = array(
			'orderby' => 'rand',
			'number'  => $num,
			'offset'  => 0,
			'field'   => 'ID',
		);
		return (array) ( new WP_User_Query( $args ) )->get_results();
	}

	public function entityTypeCreateEntity( Bundle $bundle, array $properties, ?AbstractIdentity $identity = null ) {
		$data = array(
			'user_login' => isset( $properties['slug'] ) ? $properties['slug'] : '',
			'user_pass'  => wp_generate_password(),
			'first_name' => '',
			'last_name'  => '',
			'user_email' => isset( $properties['email'] ) ? $properties['email'] : '',
			'user_url'   => isset( $properties['url'] ) ? $properties['url'] : '',
		);
		if ( isset( $properties['title'] ) ) {
			if ( is_string( $properties['title'] ) ) {
				if ( empty( $data['user_login'] ) ) {
					$data['user_login'] = $properties['title'];
				}
			} elseif ( is_array( $properties['title'] ) ) {
				if ( isset( $properties['title']['first_name'] ) ) {
					$data['first_name'] = $properties['title']['first_name'];
				}
				if ( isset( $properties['title']['last_name'] ) ) {
					$data['last_name'] = $properties['title']['last_name'];
				}
				if ( empty( $data['user_login'] ) ) {
					$data['user_login'] = apply_filters( 'drts_wordpress_user_username', $data['first_name'] . ' ' . $data['last_name'], $data['first_name'], $data['last_name'] );
				}
			}
		}

		$user_id = wp_insert_user( $data );
		if ( is_wp_error( $user_id ) ) {
			throw new Exception\RuntimeException( $user_id->get_error_message() );
		}
		if ( ! $entity = $this->entityTypeEntityById( $user_id ) ) {
			throw new Exception\RuntimeException( 'Failed fetching user by ID: ' . $user_id );
		}

		return $entity;
	}
}
