<?php

declare(strict_types=1);

namespace MailerPress\Actions\ActionScheduler\Processors;

\defined('ABSPATH') || exit;

use MailerPress\Core\Attributes\Action;
use MailerPress\Core\Attributes\Endpoint;
use MailerPress\Core\Enums\Tables;
use ZipArchive;
use WP_REST_Request;

class ExportContact
{
    #[Action('mailerpress_export_contact_batch', priority: 10, acceptedArgs: 4)]
    public function run($export_id, $status = null, $offset = null, $contact_ids = []): void
    {
        global $wpdb;
        $table_contacts = Tables::get(Tables::MAILERPRESS_CONTACT);
        $table_custom   = Tables::get(Tables::MAILERPRESS_CONTACT_CUSTOM_FIELDS);
        $batch_size     = 200;

        $contacts = [];

        if (!empty($contact_ids) && is_array($contact_ids)) {
            $contact_ids_safe = array_map('intval', $contact_ids);
            $placeholders = implode(',', array_fill(0, count($contact_ids_safe), '%d'));
            $sql = "SELECT contact_id, email, first_name, last_name, updated_at, subscription_status FROM $table_contacts WHERE contact_id IN ($placeholders)";
            $prepared = $wpdb->prepare($sql, $contact_ids_safe);
            $contacts = $wpdb->get_results($prepared, ARRAY_A);
        } elseif (isset($status, $offset)) {
            $contacts = $wpdb->get_results($wpdb->prepare(
                "SELECT contact_id, email, first_name, last_name, updated_at, subscription_status FROM $table_contacts WHERE subscription_status = %s LIMIT %d OFFSET %d",
                $status,
                $batch_size,
                $offset
            ), ARRAY_A);
        }

        if (empty($contacts)) return;

        $contact_ids_batch = array_column($contacts, 'contact_id');
        $in_clause = implode(',', array_map('intval', $contact_ids_batch));

        // Fetch custom fields
        $custom_fields = $wpdb->get_results(
            "SELECT contact_id, field_key, field_value FROM $table_custom WHERE contact_id IN ($in_clause)",
            ARRAY_A
        );

        $grouped_custom = [];
        foreach ($custom_fields as $cf) {
            $grouped_custom[$cf['contact_id']][$cf['field_key']] = $cf['field_value'] ?? '';
        }

        // Prepare CSV
        $upload_dir = wp_upload_dir();
        $export_dir = trailingslashit($upload_dir['basedir']) . 'mailerpress_exports/' . $export_id;
        if (!file_exists($export_dir)) wp_mkdir_p($export_dir);

        $status_label = $status ?? 'export';
        $file_path = $export_dir . "/{$status_label}.csv";
        $is_new_file = !file_exists($file_path);

        $file = fopen($file_path, 'a');

        // Determine all custom keys
        $all_custom_keys = [];
        foreach ($grouped_custom as $fields) {
            $all_custom_keys = array_merge($all_custom_keys, array_keys($fields));
        }
        $all_custom_keys = array_unique($all_custom_keys);

        // Header
        if ($is_new_file && isset($contacts[0])) {
            $header = array_merge(array_keys($contacts[0]), $all_custom_keys);
            fputcsv($file, $header);
        }

        // Rows
        foreach ($contacts as $contact) {
            $custom_values = [];
            foreach ($all_custom_keys as $key) {
                $custom_values[] = $grouped_custom[$contact['contact_id']][$key] ?? '';
            }
            fputcsv($file, array_merge($contact, $custom_values));
        }

        fclose($file);
    }

    #[Action('mailerpress_finalize_export_contact_zip', priority: 10, acceptedArgs: 2)]
    public function handleZip($export_id, $email): void
    {
        if (!$export_id) {
            return;
        }

        $upload_dir = wp_upload_dir();
        $export_dir = trailingslashit($upload_dir['basedir']) . "mailerpress_exports/{$export_id}/";
        $zip_path = trailingslashit($upload_dir['basedir']) . "mailerpress_exports/{$export_id}.zip";

        if (!is_dir($export_dir)) {
            return;
        }

        $zip = new ZipArchive();
        if ($zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
            return;
        }

        foreach (glob($export_dir . "*.csv") as $file) {
            $filename = basename($file);
            $zip->addFile($file, $filename);
        }

        $zip->close();

        array_map('unlink', glob($export_dir . "*.csv"));
        rmdir($export_dir);

        $token = wp_generate_password(24, false);
        $expires = time() + DAY_IN_SECONDS;

        $export_data = [
            'zip_path' => $zip_path,
            'expires'  => $expires,
            'token'    => $token,
        ];

        update_option("mailerpress_export_{$export_id}", $export_data);

        $download_url = rest_url("mailerpress/v1/export/{$export_id}?token={$token}");

        if ($email && is_email($email)) {
            wp_mail(
                $email,
                esc_html__('Your MailerPress Export is Ready', 'mailerpress'),
                sprintf(
                    esc_html__(
                        "Hello,\n\nYour export is complete. You can download it here:\n\n%s\n\nThis link will expire in 24 hours.",
                        'mailerpress'
                    ),
                    esc_url($download_url)
                ),
                ['Content-Type: text/plain; charset=UTF-8']
            );
        }
    }
}
