<?php

/**
 * Handles storage of Hub Accounts in WP posts table.
 *
 * @package northmill-online-shared
 */
declare (strict_types=1);
namespace Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstracts\Hub_API\Hub_Accounts;

use Northmill_Online_Shared_Sync\Northmill_Online_Shared\Abstracts\Hub_API\Hub_Accounts\Models\Hub_Account_Model;
use WP_Error;
defined('ABSPATH') || exit;
/**
 * Class Hub_Account_Repository
 */
class WP_Repository
{
    public const CPT_KEY = 'nm_hub_accounts';
    /**
     * Get the main account.
     *
     * @param string $env The environment to get the accounts for. Can be 'prod' or 'test'.
     *
     * @return Hub_Account_Model|null Returns the main account for the given environment or null if none exists.
     */
    public static function get_main_account(string $env): ?Hub_Account_Model
    {
        $env = Envs::validate_env($env);
        $accounts = self::get_accounts(array('posts_per_page' => 1), array('type' => 'main', 'env' => $env));
        return !empty($accounts) ? reset($accounts) : null;
    }
    /**
     * Get the current main Hub account.
     *
     * @return Hub_Account_Model|null Returns the main account for the current environment or null if none exists.
     */
    public static function get_current_main_account(): ?Hub_Account_Model
    {
        $env = Envs::get_current_env();
        return self::get_main_account($env);
    }
    /**
     * Get all stock accounts.
     *
     * @param null|string $env The environment to get the accounts for. Can be 'prod' or 'test'. If null, all accounts are returned.
     * @param bool        $include_disabled Whether to include disabled accounts.
     *
     * @return Hub_Account_Model[] Array of stock Hub accounts
     */
    public static function get_stock_accounts(?string $env = null, bool $include_disabled = \false): array
    {
        $env = Envs::validate_env($env);
        return self::get_accounts(array(), array('type' => 'stock', 'env' => $env), $include_disabled);
    }
    /**
     * Get all accounts for the current environment.
     *
     * @return Hub_Account_Model[]
     */
    public static function get_all_current_accounts(): array
    {
        $accounts = array_merge(array(self::get_current_main_account()), self::get_stock_accounts('current'));
        return array_filter($accounts);
    }
    /**
     * Get Hub Accounts.
     *
     * @return Hub_Account_Model[] Array of all Hub accounts
     */
    public static function get_all(): array
    {
        return self::get_accounts(array(), array(), \true, \false);
    }
    /**
     * Get current stock Hub accounts.
     *
     * @param array $get_post_args    Arguments to pass to get_posts().
     * @param array $custom_args      Custom arguments to pass to get_posts().
     * @param bool  $include_disabled Include disabled accounts.
     * @param bool  $only_unique      Only get unique accounts. There should only be unique accounts, but this is a failsafe used to delete duplicates.
     *
     * @return Hub_Account_Model[] Array of stock Hub accounts
     */
    private static function get_accounts(array $get_post_args = array(), array $custom_args = array(), bool $include_disabled = \false, bool $only_unique = \true): array
    {
        $get_post_args = array_merge(array('post_type' => self::CPT_KEY, 'posts_per_page' => -1, 'post_status' => 'publish', 'orderby' => 'id', 'order' => 'ASC'), $get_post_args);
        $custom_args = array_merge(array('type' => \false, 'env' => \false), $custom_args);
        $meta_query = array();
        if ($custom_args['type']) {
            $meta_query[] = array('key' => WP_Repository_Metas::CPT_META_PREFIX . 'type', 'value' => $custom_args['type'], 'compare' => '=');
        }
        if ($custom_args['env']) {
            $meta_query[] = array('key' => WP_Repository_Metas::CPT_META_PREFIX . 'env', 'value' => $custom_args['env'], 'compare' => '=');
        }
        if (!empty($meta_query)) {
            $get_post_args['meta_query'] = $meta_query;
        }
        $posts = get_posts($get_post_args);
        $accounts = array();
        if (!empty($posts)) {
            foreach ($posts as $post) {
                $account_model = Factory::create_from_wp_post($post);
                if ($include_disabled || $account_model->is_enabled()) {
                    if ($only_unique) {
                        $accounts[$account_model->url . $account_model->user] = $account_model;
                    } else {
                        $accounts[] = $account_model;
                    }
                }
            }
        }
        return $accounts;
    }
    /**
     * Get a Hub account from a post-ID.
     *
     * @param int|string $backoffice_account_post_id Hub account WP post ID.
     */
    public static function get_account_by_post_id(int|string $backoffice_account_post_id): ?Hub_Account_Model
    {
        $backoffice_account_post = get_post((int) $backoffice_account_post_id);
        if (!$backoffice_account_post) {
            return null;
        }
        if (self::CPT_KEY !== $backoffice_account_post->post_type) {
            return null;
        }
        return Factory::create_from_wp_post($backoffice_account_post);
    }
    /**
     * Create a Hub account from a Hub model, and save it to the database as CPT.
     *
     * @param Hub_Account_Model $account Hub account to create.
     *
     * @return Hub_Account_Model|false The created Hub account, or false on failure.
     */
    public static function create_from_model(Hub_Account_Model $account): false|Hub_Account_Model
    {
        $post_id = wp_insert_post(array('post_title' => $account->get_title(), 'post_type' => self::CPT_KEY, 'post_status' => 'publish'));
        if (!$post_id) {
            return \false;
        }
        $account->wp_id = $post_id;
        WP_Repository_Metas::update($account);
        return $account;
    }
    /**
     * Update Hub account CPT from a Hub model.
     *
     * @param Hub_Account_Model $account Hub account to update.
     *
     * @return int|WP_Error Post ID on success. The value 0 or WP_Error on failure.
     */
    public static function update_from_model(Hub_Account_Model $account): WP_Error|int
    {
        WP_Repository_Metas::update($account);
        $post = array('ID' => $account->wp_id, 'post_title' => $account->get_title());
        return wp_update_post($post);
    }
    /**
     * Disconnect duplicate Hub accounts.
     *
     * @return Hub_Account_Model[] With duplicates removed, keyed by URL and user.
     */
    public static function disconnect_duplicates(): array
    {
        $existing_accounts = self::get_all();
        if (empty($existing_accounts)) {
            return array();
        }
        $unique_accounts = array();
        foreach ($existing_accounts as $account) {
            if (!isset($unique_accounts[$account->url . $account->user])) {
                $unique_accounts[$account->url . $account->user] = $account;
            } else {
                $account->disconnect();
            }
        }
        return $unique_accounts;
    }
}
