<?php

namespace PWH_DCFH\App\Admin\Cron;

use Exception;
use PWH_DCFH\App\Helpers\PWH_DCFH_Email_Helper;
use WP_Query;
use ZipArchive;

if (!defined('ABSPATH')) {
    exit;
}
if (!class_exists('PWH_DCFH_Entries_Auto_Backup')) {
    class PWH_DCFH_Entries_Auto_Backup
    {
        private static $email_to;

        private $hook;

        private $recurrence;

        /**
         * Initializer Of The Class
         * Add/Remove Necessary Actions/Filters
         */
        public function init()
        {
            if (pwh_dcfh_db()::is_setting_enabled('pwh_dcfh_backup_enabled')) {
                self::$email_to = pwh_dcfh_db()::get_setting('pwh_dcfh_backup_email');
                $schedule = pwh_dcfh_db()::get_setting('pwh_dcfh_backup_schedule');
                $this->hook = 'pwh_dcfh_backup_entries_'.$schedule;
                $this->recurrence = $schedule;
                add_action('init', [$this, 'maybe_schedule_event']);
                add_action($this->hook, [$this, 'maybe_process_cron']);
                add_action('wp_mail_failed', [$this, 'maybe_log_error'], 999);
            }
        }

        /**
         * Register Cron Event In WP
         */
        public function maybe_schedule_event()
        {
            if (!wp_next_scheduled($this->hook)) {
                wp_schedule_event(time(), $this->recurrence, $this->hook);
            }
        }

        /**
         * Cron Event Process To Perform
         * @throws Exception
         */
        public function maybe_process_cron()
        {
            $zipFileDir = $this->create_backup();
            if ($zipFileDir !== false && !empty($zipFileDir['path']) && !empty($zipFileDir['url'])) {
                $zipFile = $zipFileDir['path'];
                $emailTo = self::$email_to;
                $email = new PWH_DCFH_Email_Helper($emailTo);
                $remoteAddress = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field($_SERVER['REMOTE_ADDR']) : '';
                $emailFrom = 'noreply@localhost.com';
                if (!in_array($remoteAddress, ['127.0.0.1', '::1'])) {
                    $siteUrl = get_bloginfo('url');
                    $emailFrom = 'noreply@'.wp_parse_url($siteUrl, PHP_URL_HOST);
                }
                $emailSubject = wp_strip_all_tags(apply_filters('pwh_dcfh_f_auto_backup_email_subject', __('Divi Contact Form Helper Backup', 'pwh-dcfh')));
                $emailHeading = wp_strip_all_tags(apply_filters('pwh_dcfh_f_auto_backup_email_heading', __('Divi Contact Form Helper Backup', 'pwh-dcfh')));
                $email->set_email_from($emailFrom);
                $email->set_email_subject($emailSubject);
                $email->set_email_template(pwh_dcfh_wp_helpers()::plugin_dir('html-templates/tpl-auto-backup.html'));
                $emailBody = [
                    'heading' => $emailHeading,
                    'site_title' => htmlspecialchars_decode(get_bloginfo('name')),
                    'site_url' => get_bloginfo('url'),
                    'total_files' => $zipFileDir['total_files'],
                    'backup_date' => pwh_dcfh_wp_helpers()::datetime(date_i18n('Y-m-d H:i:s')),
                ];
                $email->set_email_body($emailBody);
                $email->set_email_attachments([$zipFile]);
                $email->set_wp_mail_filters();
                if ($email->send()) {
                    $message = [
                        'sent' => true,
                        'datetime' => current_time('mysql'),
                        'message' => __('Email sent successfully with attachment.', 'pwh-dcfh'),
                    ];

                } else {
                    $message = [
                        'sent' => false,
                        'datetime' => current_time('mysql'),
                        'message' => get_option('pwh_dcfh_auto_backup_mail_failed'),
                    ];
                }
                $this->log_message($message);
                $email->delete_attachment();
            }
        }

        /**
         * Add Email Error Log
         *
         * @param $wp_error
         *
         * @return void
         */
        public function maybe_log_error($wp_error)
        {
            if (empty($wp_error)) {
                return;
            }
            $error_data = $wp_error->get_error_data();
            $subject = $error_data['subject'];
            if (strtolower($subject) !== 'divi contact form helper backup') {
                return;
            }
            update_option('pwh_dcfh_auto_backup_mail_failed', $wp_error->get_error_message(), 'no');
        }

        /**
         * Create Backup
         * @return array|false
         */
        private function create_backup()
        {
            if (!class_exists('ZipArchive')) {
                $message = [
                    'sent' => false,
                    'datetime' => current_time('mysql'),
                    'message' => __('PHP needs to have the zip extension installed. If you are using cpanel you may have zip extension installed but not activated. You need to activate it. Please contact your hosting provider to activate it.', 'pwh-dcfh'),
                ];
                $this->log_message($message);

                return false;
            }
            $contact_forms = pwh_dcfh_db()::get_contact_forms_list();
            if (!empty($contact_forms)) {
                $wp_upload_dir = wp_upload_dir();
                $upload_path = $wp_upload_dir['basedir'];
                $upload_url = $wp_upload_dir['baseurl'];
                $zip_file_name = 'divi-contact-form-helper-backup-'.time().'.zip';
                $zip_file_dir = wp_normalize_path($upload_path.DIRECTORY_SEPARATOR.$zip_file_name);
                $zip_file_url = wp_normalize_path($upload_url.DIRECTORY_SEPARATOR.$zip_file_name);
                $zip = new ZipArchive();
                $total_files_zipped = 0;
                foreach ($contact_forms as $contact_form) {
                    $contact_form_id = $contact_form['unique_id'];
                    $contact_form_title = sanitize_file_name($contact_form['title']); // Sanitize file name
                    $csv_file_name = $contact_form_title.'.csv';
                    $csv_file_dir = wp_normalize_path($upload_path.DIRECTORY_SEPARATOR.$csv_file_name);
                    if (false === ($f_handle = fopen($csv_file_dir, 'wb'))) { // phpcs:ignore
                        $message = [
                            'sent' => false,
                            'datetime' => current_time('mysql'),
                            'message' => __('Backup needs to create a CSV file. Server is not allowed to create file.', 'pwh-dcfh'),
                        ];
                        $this->log_message($message);
                        continue; // Skip to the next contact form
                    }
                    fwrite($f_handle, chr(0xEF).chr(0xBB).chr(0xBF)); // phpcs:ignore
                    $total_posts_obj = new WP_Query([
                        'post_type' => 'pwh_dcfh',
                        'post_status' => 'any',
                        'meta_key' => '_pwh_dcfh_contact_form_id', // phpcs:ignore
                        'meta_value' => $contact_form_id // phpcs:ignore
                    ]);
                    $total_posts = $total_posts_obj->found_posts;
                    $posts_per_page = 200;
                    $counter = 0;
                    $form_data = [];
                    $csv_headers = [];
                    $csv_rows = [];
                    for ($i = 0; $i < ceil($total_posts / $posts_per_page); ++$i) {
                        $post_obj = new WP_Query([
                            'post_type' => 'pwh_dcfh',
                            'post_status' => 'any',
                            'posts_per_page' => $posts_per_page,
                            'offset' => $i * $posts_per_page,
                            'meta_key' => '_pwh_dcfh_contact_form_id', // phpcs:ignore
                            'meta_value' => $contact_form_id // phpcs:ignore
                        ]);
                        foreach ($post_obj->posts as $post) {
                            $counter++;
                            $post_id = $post->ID;
                            $post_excerpt = $post->post_excerpt;
                            if (is_serialized($post_excerpt)) {
                                $page_id = pwh_dcfh_post_meta_handler()::get_page_id_meta_value($post_id);
                                $form_entries = pwh_dcfh_helpers()::maybe_unserialize($post_excerpt);
                                if (!empty($form_entries) && is_array($form_entries)) {
                                    foreach ($form_entries as $form_entry) {
                                        $field_id = $form_entry['id'];
                                        $field_label = $form_entry['label'];
                                        $field_type = $form_entry['type'];
                                        $form_data[$contact_form_id][$field_id] = $field_id;
                                        $csv_headers[$contact_form_id][$field_id] = $field_label;
                                        $wp_subdir = $form_entry['subdir'] ?? '';
                                        $wp_basedir = rtrim($wp_upload_dir['basedir'], '/').'/'.$wp_subdir;
                                        $wp_baseurl = rtrim($wp_upload_dir['baseurl'], '/').'/'.$wp_subdir;
                                        if ('file' === $field_type || 'signature_pad' === $field_type) {
                                            $attachments = array_filter(explode(',', $form_entry['value']));
                                            if (!empty($attachments)) {
                                                $attachments_list = [];
                                                foreach ($attachments as $attachment) {
                                                    if (!empty($form_entry['is_media_library'])) {
                                                        $upload_dir = path_join($wp_basedir, $attachment);
                                                        $upload_url = path_join($wp_baseurl, $attachment);
                                                    } else {
                                                        $upload_dir = pwh_dcfh_file_helpers()::get_form_upload_dir($contact_form_id, $wp_subdir, $attachment);
                                                        $upload_url = pwh_dcfh_file_helpers()::get_form_upload_url($contact_form_id, $wp_subdir, $attachment);
                                                    }
                                                    if (et_()->WPFS()->is_file($upload_dir) && et_()->WPFS()->exists($upload_dir)) {
                                                        $attachments_list[] = $upload_url;
                                                    }
                                                }
                                                $csv_rows[$contact_form_id][$counter][$field_id] = implode(',', $attachments_list);
                                            }
                                        } else {
                                            $csv_rows[$contact_form_id][$counter][$field_id] = !empty($form_entry['value']) ? $form_entry['value'] : '-';
                                        }
                                    }
                                    $csv_rows[$contact_form_id][$counter] = array_merge($csv_rows[$contact_form_id][$counter], [
                                        'entry_number' => $post_id,
                                        'read_by' => '0000-00-00 00:00:00' !== $post->post_modified ? pwh_dcfh_wp_helpers()::get_author_name(pwh_dcfh_post_meta_handler()::get_read_by_meta_value($post_id)) : '-',
                                        'submitter' => pwh_dcfh_wp_helpers()::get_submitter_name($post->post_author),
                                        'page_title' => get_the_title($page_id),
                                        'page_url' => get_the_permalink($page_id),
                                        'date' => $post->post_date,
                                        'ip_address' => !empty(pwh_dcfh_post_meta_handler()::get_ip_address_meta_value($post_id)) ? pwh_dcfh_post_meta_handler()::get_ip_address_meta_value($post_id) : '-',
                                        'browser' => isset($user_agent_meta['browser']) ? ucfirst($user_agent_meta['browser']) : null,
                                        'platform' => isset($user_agent_meta['platform']) ? ucfirst($user_agent_meta['platform']) : null,
                                    ]);
                                }
                            }
                        }
                    }
                    if (!empty($csv_rows)) {
                        $form_data[$contact_form_id] = wp_parse_args(array_keys(pwh_dcfh_helpers()::fixed_form_placeholders()), $form_data[$contact_form_id]);
                        $csv_headers[$contact_form_id] = wp_parse_args(array_values(pwh_dcfh_helpers()::fixed_form_placeholders()), array_values($csv_headers[$contact_form_id]));
                        fputcsv($f_handle, $csv_headers[$contact_form_id], ',', '"');
                        foreach ($csv_rows[$contact_form_id] as $value) {
                            $csv_row_data = [];
                            foreach ($form_data[$contact_form_id] as $header) {
                                $csv_row_data[] = $value[$header] ?? '-';
                            }
                            fputcsv($f_handle, $csv_row_data, ',', '"');
                        }
                        $csv_footer = [
                            ["path" => "\n\n"],
                            ["path" => __("Total Entries: ".$total_posts, 'pwh-dcfh')],
                            ["path" => __("Generated on: ".date_i18n("F j, Y, g:i a"), 'pwh-dcfh')],
                            ["path" => __("Auto Generated", 'pwh-dcfh')],
                        ];
                        foreach ($csv_footer as $footer) {
                            fputcsv($f_handle, $footer, ',', '"');
                        }
                        fclose($f_handle); // phpcs:ignore
                        // Zipped CSV
                        if ($zip->open($zip_file_dir, ZipArchive::CREATE)) {
                            $zip->addFile($csv_file_dir, $csv_file_name);
                            @$zip->close(); // phpcs:ignore
                            if (file_exists($csv_file_dir)) {
                                wp_delete_file($csv_file_dir);
                                $total_files_zipped++;
                            }
                        }
                    }
                }
                if ($total_files_zipped > 0) {
                    return ['path' => $zip_file_dir, 'url' => $zip_file_url, 'total_files' => $total_files_zipped];
                }
            }

            return false;
        }

        /**
         * Log Message to Option
         *
         * @param array $message
         *
         * @return void
         */
        private function log_message(array $message)
        {
            update_option('pwh_dcfh_entries_auto_backup_status', $message, 'no');
        }

    }
}
