<?php

namespace Phox\core\admin\panel\wdes_options;

use Phox\core\admin\DB_Proxy;
use Phox\core\admin\panel\wdes_options\pages\Abstract_Page;
use Phox\core\admin\panel\wdes_options\pages\elements\actions\Fetch_Whmcs_Data;
use Phox\core\admin\panel\wdes_options\pages\Page_404;
use Phox\core\admin\panel\wdes_options\pages\Page_Blog;
use Phox\core\admin\panel\wdes_options\pages\Page_Color;
use Phox\core\admin\panel\wdes_options\pages\Page_Custom_Fonts;
use Phox\core\admin\panel\wdes_options\pages\Page_Footer;
use Phox\core\admin\panel\wdes_options\pages\Page_General;
use Phox\core\admin\panel\wdes_options\pages\Page_Header;
use Phox\core\admin\panel\wdes_options\pages\Page_Import_Export;
use Phox\core\admin\panel\wdes_options\pages\Page_Integrations;
use Phox\core\admin\panel\wdes_options\pages\Page_JS_CSS;
use Phox\core\admin\panel\wdes_options\pages\Page_Miscellaneous;
use Phox\core\admin\panel\wdes_options\pages\Page_Sidebar;
use Phox\core\admin\panel\wdes_options\pages\Page_Single;
use Phox\core\admin\panel\wdes_options\pages\Page_Social_Media;
use Phox\core\admin\panel\wdes_options\pages\Page_ToTop;
use Phox\core\admin\panel\wdes_options\pages\Page_Typography;

class Panel_Controller
{
    /**
     * The Singleton's instance is stored in a static field. This field is an
     * array, because we'll allow our Singleton to have subclasses. Each item in
     * this array will be an instance of a specific Singleton's subclass. You'll
     * see how this works in a moment.
     */
    private static $instances = [];

    /**
     * DataBase Proxy
     *
     * @since 2.3.6
     * @var DB_Proxy
     */
    private DB_Proxy $db_source;


    public static function getInstance(): Panel_Controller
    {
        $cls = static::class;
        if (!isset(self::$instances[$cls])) {
            self::$instances[$cls] = new static();
        }

        return self::$instances[$cls];
    }

    protected function __construct()
    {
        $this->db_stream();
        $this->ajax_action();
        add_action( 'admin_enqueue_scripts', [$this, 'add_inline_scripts'] );
    }

    public function ajax_action():void
    {
        add_action('wp_ajax_wdes_panel_general', [$this , 'general_page']);
        add_action('wp_ajax_wdes_panel_header', [$this , 'header_page']);
        add_action('wp_ajax_wdes_panel_sidebar', [$this , 'sidebar_page']);
        add_action('wp_ajax_wdes_panel_footer', [$this , 'footer_page']);
        add_action('wp_ajax_wdes_panel_blog', [$this , 'blog_page']);
        add_action('wp_ajax_wdes_panel_not-found', [$this , 'notfound_page']);
        add_action('wp_ajax_wdes_panel_social-media', [$this , 'social_media_page']);
        add_action('wp_ajax_wdes_panel_single', [$this , 'single_page']);
        add_action('wp_ajax_wdes_panel_color', [$this , 'color_page']);
        add_action('wp_ajax_wdes_panel_typo-general', [$this , 'typography_page']);
        add_action('wp_ajax_wdes_panel_custom-fonts', [$this , 'custom_page']);
        add_action('wp_ajax_wdes_panel_integrations', [$this , 'integration_page']);
        add_action('wp_ajax_wdes_panel_totop', [$this , 'totop_page']);
        add_action('wp_ajax_wdes_panel_miscellaneous', [$this , 'miscellaneous_page']);
        add_action('wp_ajax_wdes_panel_custom-css-js', [$this , 'custom_css_js']);
        add_action('wp_ajax_wdes_panel_export-import', [$this , 'import_export_page']);
    }

    public function add_inline_scripts(): void
    {
        wp_add_inline_script('wdes-panel-script', 'const wdesAdminAjaxPanelNonce = "'.wp_create_nonce( 'wdes-panel-get-options-url-nonce' ).'";', 'before');
        wp_add_inline_script('wdes-panel-script', 'const wdesAdminPanelURI = "'.WDES_ADMIN_URI.'";', 'before');
        wp_add_inline_script('wdes-panel-script', 'const wdesAdminPanelExportSecret = "'.md5( AUTH_KEY . SECURE_AUTH_KEY ).'";', 'before');

    }

    private function db_stream ()
    {
        $this->db_source = new DB_Proxy();
    }

    /**
     * Set Data Source
     *
     * @since 2.3.6
     * @param array $data
     * @return DB_Proxy
     */
    private function set_data_source (array $data):void
    {
        $this->db_source->set_panel_options($data);
    }

    /**
     * Get Data Source
     *
     * @since 2.3.6
     * @return DB_Proxy
     */
    public function get_db_source(): DB_Proxy
    {
        return $this->db_source;
    }

    /**
     * Verify Nonce
     *
     * It must check after handel any request
     *
     * @since 2.3.6
     * @return void
     */
    private function verify_nonce():void
    {

        if ( ! wp_verify_nonce( $_GET['nonce'], 'wdes-panel-get-options-url-nonce' )){
            wp_send_json(array(
                'error'  => [
                    'message' => 'Nonce check failed'
                ]
            ), 422);
        };

    }

    private function request_handler(Abstract_Page $page)
    {
        if( $_SERVER['REQUEST_METHOD'] === 'GET' ){
            //Set data
            $this->set_data_source(get_option(DB_Proxy::PANEL_COLUMN_NAME, []));

            if(isset($_GET['button_action'])){
                define('WDES_PANEL_BUTTON_ACTION', $_GET['button_action']);
                $page->build_pages();
            }

            $page->build_pages();
            wp_send_json($page->render(), 200);
        }

        if( $_SERVER['REQUEST_METHOD'] === 'POST' ){
            //Button action
            if(isset($_GET['button_action'])){
                define('WDES_PANEL_BUTTON_ACTION', $_GET['button_action']);
                $page->build_pages();
            }
            //Set data
            if( ! empty($_POST) ){
                $this->set_data_source($_POST);
                $page->build_pages();
                $save_result = $page->save();
                $status_code = empty($save_result) ? 200 : 422;
                wp_send_json($save_result, $status_code);
            }else{

                wp_send_json(array(
                    'error'  => [
                        'message' => 'No data send'
                    ]
                ), 422);
            }

        }


    }

    public function general_page():void
    {
        $this->verify_nonce();

        $page_general = new Page_General('General');

        $this->request_handler($page_general);

    }

    public function header_page():void
    {
        $this->verify_nonce();

        $page_header = new Page_Header('Header');

        $this->request_handler($page_header);

    }

    public function sidebar_page():void
    {
        $this->verify_nonce();

        $page_sidebar = new Page_Sidebar('Sidebar');

        $this->request_handler($page_sidebar);

    }

    public function footer_page():void
    {
        $this->verify_nonce();

        $page_footer = new Page_Footer('Footer');

        $this->request_handler($page_footer);

    }

    public function blog_page():void
    {
        $this->verify_nonce();

        $page_blog = new Page_Blog('Blog');

        $this->request_handler($page_blog);

    }

    public function notfound_page():void
    {
        $this->verify_nonce();

        $page_404 = new Page_404('404');

        $this->request_handler($page_404);
    }

    public function social_media_page():void
    {
        $this->verify_nonce();

        $page_social_media = new Page_Social_Media('Social Media');

        $this->request_handler($page_social_media);
    }

    public function single_page():void
    {
        $this->verify_nonce();

        $page_single = new Page_Single('Single');

        $this->request_handler($page_single);
    }

    public function color_page():void
    {
        $this->verify_nonce();

        $page_color = new Page_Color('Color');

        $this->request_handler($page_color);
    }

    public function typography_page():void
    {
        $this->verify_nonce();

        $page_typography = new Page_Typography('Typography');

        $this->request_handler($page_typography);

    }

    public function custom_page():void
    {
        $this->verify_nonce();

        $page_custom = new Page_Custom_Fonts('Custom Fonts');

        $this->request_handler($page_custom);
    }

    public function integration_page():void
    {
       $this->verify_nonce();

       $page_integration = new Page_Integrations('Integrations');

       $this->request_handler($page_integration);
    }

    public function custom_css_js()
    {
        $this->verify_nonce();

        $page_css_js = new Page_JS_CSS('Custom Style - Script');

        $this->request_handler($page_css_js);
    }

    public function import_export_page():void
    {
        $this->verify_nonce();

        $page_import_export = new Page_Import_Export('Import - Export - Reset');

        $this->request_handler($page_import_export);
    }

    public function totop_page():void
    {
        $this->verify_nonce();

        $page_totop = new Page_ToTop('Back To Top');

        $this->request_handler($page_totop);

    }

    public function miscellaneous_page():void
    {
        $this->verify_nonce();

        $page_load_screen = new Page_Miscellaneous('Miscellaneous');

        $this->request_handler($page_load_screen);
    }

    public function export_process()
    {

        $this->verify_nonce();

        if( $_SERVER['REQUEST_METHOD'] === 'GET' ) {

            if ( ! defined( 'AUTH_KEY' ) ) {
                define( 'AUTH_KEY', '' );
            }
            if ( ! defined( 'SECURE_AUTH_KEY' ) ) {
                define( 'SECURE_AUTH_KEY', '' );
            }

            if (! isset( $_GET['secret'] ) || $_GET['secret'] === md5( AUTH_KEY . SECURE_AUTH_KEY )) {

                //Get data
                $options = $this->get_db_source()->get_options();

                if (!empty($options)) {

                    header( 'Content-Description: File Transfer' );
                    header( 'Content-type: application/txt' );

                    header( 'Content-Disposition: attachment; filename="' . 'phox_backup_' . date( 'd-m-Y' ) . '.json"' );

                    header( 'Content-Transfer-Encoding: binary' );
                    header( 'Expires: 0' );
                    header( 'Cache-Control: must-revalidate' );
                    header( 'Pragma: public' );

                    echo json_encode( $options );
                    exit;

                } else {

                    wp_send_json(array(
                        'error' => [
                            'message' => 'No data send'
                        ],
                    ), 422);

                }

            } else {
                wp_send_json(array(
                    'error'  => [
                        'message' => 'Invalid Secret for options use'
                    ]
                ), 422);
            }
        }
    }

    public function reset_process() {
        $this->verify_nonce();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $this->handle_post_request('reset', []);
        }
    }

    public function import_process(): void {
        $this->verify_nonce();

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {

            $user_import_data_raw =  stripslashes($_POST['data'] ?? '');
            $user_import_data = json_decode($user_import_data_raw, true);
            if(!is_null($user_import_data)) {

                $this->handle_post_request('import', $user_import_data);

            }else{

                wp_send_json([
                    'error' => [
                        'message' => 'Data is not valid'
                    ]
                ], 422);
            }

        }
    }

    private function handle_post_request(string $action, array $user_import_data) {
        if (!empty($_POST) && $_POST['do'] === $action) {
            if ($action === 'reset' || ($action === 'import' && !is_null($user_import_data))) {
                $imported_data = $this->process_pages($user_import_data);

                if (isset($imported_data['error'])) {
                    wp_send_json($imported_data, 422);
                } else {
                    $this->get_db_source()->update_options($imported_data);
                    wp_send_json([], 200);
                }
            } else {
                wp_send_json([
                    'error' => [
                        'message' => $action === 'import' ? 'Data is not valid' : 'No data sent'
                    ]
                ], 422);
            }
        } else {
            wp_send_json([
                'error' => [
                    'message' => 'No data sent'
                ]
            ], 422);
        }
    }

    private function process_pages(array $user_import_data): array {
        $imported_data = [];
        $pages = [
            new Page_General('General'),
            new Page_Sidebar('Sidebar'),
            new Page_Header('Header'),
            new Page_Footer('Footer'),
            new Page_Blog('Blog'),
            new Page_404('404'),
            new Page_Social_Media('Social Media'),
            new Page_Single('Single'),
            new Page_Color('Color'),
            new Page_Typography('Typography'),
            new Page_Custom_Fonts('Custom Fonts'),
            new Page_Integrations('Integrations'),
            new Page_Miscellaneous('Miscellaneous'),
            new Page_ToTop('Back To Top')
        ];

        foreach ($pages as $page) {
            $this->set_data_source($user_import_data);
            $page->build_pages();
            $data_result = $page->import($user_import_data);

            if (isset($data_result['error'])) {
                return $data_result;
            }
            $imported_data = array_merge($data_result, $imported_data);
        }

        return $imported_data;
    }

}