<?php

namespace BitApps\PiPro\src\Integrations\Acpt;

use BitApps\Pi\Deps\BitApps\WPValidator\Validator;
use BitApps\Pi\Helpers\Utility;

// Prevent direct script access
if (!\defined('ABSPATH')) {
    exit;
}

class AcptActionHelper
{
    /**
     * Check if ACPT Free is active.
     */
    public static function isACPTFreeActive(): bool
    {
        return class_exists('Acpt_Lite');
    }

    /**
     * Get class prefix.
     */
    public static function getClassPrefix(): string
    {
        return self::isACPTFreeActive() ? 'ACPT_Lite' : 'ACPT';
    }

    /**
     * Get the custom post type repository class name.
     */
    public static function getCustomPostTypeRepoClassName(): string
    {
        return self::getClassPrefix() . '\Core\Repository\CustomPostTypeRepository';
    }

    /**
     * Get the custom post type model class name.
     */
    public static function getCustomPostTypeModelClassName(): string
    {
        return self::getClassPrefix() . '\Core\Models\CustomPostType\CustomPostTypeModel';
    }

    /**
     * Get the meta repository class name.
     */
    public static function getMetaRepoClassName(): string
    {
        return self::getClassPrefix() . '\Core\Repository\MetaRepository';
    }

    /**
     * Get the taxonomy repository class name.
     */
    public static function getTaxonomyRepoClassName(): string
    {
        return self::getClassPrefix() . '\Core\Repository\TaxonomyRepository';
    }

    /**
     * Get the taxonomy model class name.
     */
    public static function getTaxonomyModelClassName(): string
    {
        return self::getClassPrefix() . '\Core\Models\Taxonomy\TaxonomyModel';
    }

    /**
     * Get the uuid class name.
     */
    public static function getUuidClassName(): string
    {
        return self::getClassPrefix() . '\Core\Helper\Uuid';
    }

    /**
     * Get the Form repository class name.
     */
    public static function getFormRepoClassName(): string
    {
        return self::getClassPrefix() . '\Core\Repository\FormRepository';
    }

    /**
     * Get the dynamic block class name.
     */
    public static function getDynamicBlockRepoClassName(): string
    {
        return self::getClassPrefix() . '\Core\Repository\DynamicBlockRepository';
    }

    /**
     * Get the acpt db class name.
     */
    public static function getAcptDBClassName(): string
    {
        return self::isACPTFreeActive() ? 'ACPT_Lite\Includes\ACPT_Lite_DB' : 'ACPT\Includes\ACPT_DB';
    }

    /**
     * Get field groups.
     *
     * @param array $args
     */
    public static function getFieldGroups($args = []): array
    {
        $metaRepoClass = self::getMetaRepoClassName();

        return Utility::jsonEncodeDecode($metaRepoClass::get($args));
    }

    /**
     * Get the registered taxonomies.
     *
     * @param array $args
     */
    public static function getTaxonomies($args = []): array
    {
        $taxonomyRepoClass = self::getTaxonomyRepoClassName();

        return Utility::jsonEncodeDecode($taxonomyRepoClass::get($args));
    }

    /**
     * Get Forms.
     *
     * @param array $args
     */
    public static function getForms($args = []): array
    {
        $formRepoClassName = self::getFormRepoClassName();

        return Utility::jsonEncodeDecode($formRepoClassName::get($args));
    }

    /**
     * Prepare post type fields.
     *
     * @param array $fieldsMap
     */
    public static function preparePostTypeData($fieldsMap): array
    {
        $uuidClass = self::getUuidClassName();

        $fieldsMap['id'] = $uuidClass::v4();
        $fieldsMap['native'] = false;
        $fieldsMap['icon'] = $fieldsMap['icon'] ?? 'dashicons-admin-site-alt3';
        $fieldsMap['supports'] = $fieldsMap['supports'] ?? [];
        $fieldsMap['settings'] = empty($fieldsMap['settings']) ? [] : array_filter($fieldsMap['settings']);

        return $fieldsMap;
    }

    /**
     * Prepare taxonomy fields.
     *
     * @param array $fieldsMap
     */
    public static function prepareTaxonomyData($fieldsMap)
    {
        if (!empty($fieldsMap['rewrite']) && !empty($fieldMappings['settings']['custom_rewrite'])) {
            $settings['rewrite'] = ['slug' => $fieldMappings['settings']['custom_rewrite'] ?? null];
        }

        unset($fieldsMap['rewrite']);

        $uuidClass = self::getUuidClassName();
        $taxonomyModelClass = self::getTaxonomyModelClassName();

        $fieldsMap['id'] = $uuidClass::v4();
        $fieldsMap['native'] = false;
        $fieldsMap['settings'] = empty($fieldsMap['settings']) ? [] : array_filter($fieldsMap['settings']);

        return $taxonomyModelClass::hydrateFromArray($fieldsMap);
    }

    /**
     * Validate post type fields.
     *
     * @param array $fieldMappings
     * @param array $rules
     * @param array $payload
     * @param bool $checkPostTypeExists
     * @param null|string $postType
     */
    public static function validatePostTypeFields(
        $fieldMappings,
        $rules,
        $payload = null,
        $checkPostTypeExists = false,
        $postType = null
    ): array {
        $validationErrors = self::validateFieldMap($fieldMappings, $rules, $payload);

        if (!empty($validationErrors)) {
            return $validationErrors;
        }

        if ($checkPostTypeExists && self::isPostTypeExists($postType)) {
            return [
                'response'    => __('Post type already exists', 'bit-pi'),
                'payload'     => $payload,
                'status_code' => 422
            ];
        }

        if (!$checkPostTypeExists && !self::isPostTypeExists($postType)) {
            return [
                'response'    => __('Post type not found', 'bit-pi'),
                'payload'     => $payload,
                'status_code' => 400
            ];
        }

        return [];
    }

    /**
     * Validate field map.
     *
     * @param array $fieldMappings
     * @param array $validationRules
     * @param null|array $payload
     */
    public static function validateFieldMap($fieldMappings, $validationRules, $payload = null)
    {
        $validator = new Validator();

        $validation = $validator->make($fieldMappings, $validationRules);

        if ($validation->fails()) {
            return [
                'response'    => $validation->errors(),
                'payload'     => $payload ?? $fieldMappings,
                'status_code' => 422
            ];
        }
    }

    /**
     * Validate required modules and their corresponding classes.
     *
     * @param array $requiredModules
     * @param array $payload
     *
     * @return array|void
     */
    public static function validateRequiredModules($requiredModules = [], $payload = [])
    {
        $moduleClasses = [
            'postTypeRepository' => [
                'className'    => self::getCustomPostTypeRepoClassName(),
                'errorMessage' => __('Custom post type repository class not found', 'bit-pi')
            ],
            'customPostTypeModel' => [
                'className'    => self::getCustomPostTypeModelClassName(),
                'errorMessage' => __('Custom post type model class not found', 'bit-pi')
            ],
            'metaRepository' => [
                'className'    => self::getMetaRepoClassName(),
                'errorMessage' => __('Meta Repository class not found', 'bit-pi')
            ],
            'taxonomyRepository' => [
                'className'    => self::getMetaRepoClassName(),
                'errorMessage' => __('Taxonomy Repository class not found', 'bit-pi')
            ],
            'TaxonomyModel' => [
                'className'    => self::getTaxonomyModelClassName(),
                'errorMessage' => __('Taxonomy Model class not found', 'bit-pi')
            ],
            'uuid' => [
                'className'    => self::getUuidClassName(),
                'errorMessage' => __('Uuid class not found', 'bit-pi')
            ],
            'acptDb' => [
                'className'    => self::getAcptDBClassName(),
                'errorMessage' => __('Acpt db class not found', 'bit-pi')
            ],
            'DynamicBlockRepository' => [
                'className'    => self::getDynamicBlockRepoClassName(),
                'errorMessage' => __('Acpt dynamic block repository class not found', 'bit-pi')
            ],
            'FormRepository' => [
                'className'    => self::getFormRepoClassName(),
                'errorMessage' => __('Acpt form repository class not found', 'bit-pi')
            ]
        ];

        // Loop through each requested module to check its class existence
        foreach ($requiredModules as $module) {
            $moduleInfo = $moduleClasses[$module];

            if (!class_exists($moduleInfo['className'])) {
                // Return the error response immediately if the class does not exist
                return [
                    'response'    => $moduleInfo['errorMessage'],
                    'payload'     => $payload,
                    'status_code' => 400
                ];
            }
        }
    }

    /**
     * Check if post type exists.
     *
     * @param string $postType
     */
    public static function isPostTypeExists($postType): bool
    {
        $customPostTypeRepoClass = self::getCustomPostTypeRepoClassName();

        if (!$customPostTypeRepoClass) {
            return false;
        }

        return $customPostTypeRepoClass::exists($postType);
    }

    /**
     * Check custom post type is valid or not.
     *
     * @param string $postType
     *
     * @return bool
     */
    public static function isValidCustomPostType($postType)
    {
        $notAllowed = [
            'post',
            'page',
            'attachment',
            'revision',
            'nav_menu_item',
            'custom_css',
            'customize_changeset',
            'oembed_cache',
            'user_request',
            'wp_block',
            'wp_template',
        ];

        // exclude WooCommerce CPT
        if (class_exists('woocommerce')) {
            $notAllowed = array_merge(
                $notAllowed,
                [
                    'shop_order',
                    'shop_coupon',
                    'product_variation',
                    'shop_order_refund',
                ]
            );
        }

        return !\in_array($postType, $notAllowed);
    }

    /**
     * Register related taxonomies for the custom post type.
     *
     * @param string $postType
     */
    public static function registerRelatedTaxonomies($postType)
    {
        $args = ['public' => true, '_builtin' => false];
        $taxonomies = get_taxonomies($args, 'objects');

        if (empty($taxonomies)) {
            return;
        }

        foreach ($taxonomies as $taxonomy) {
            if (
                \is_array($taxonomy->object_type)
                && !empty($taxonomy->object_type)
                && reset($taxonomy->object_type) === $postType
            ) {
                $taxonomyRepoClass = self::getTaxonomyRepoClassName();

                $taxonomyRepoClass::createCustomTaxonomy($taxonomy->name);
            }
        }
    }
}
