<?php

namespace Formatrica\Admin;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use Formatrica\Submission\Submission_Repository;

/**
 * CSV export + single-delete for the submissions admin surface.
 *
 * Metadata columns first (id, uuid, form, status, created_at, ip_address),
 * then the union of field names across the exported rows; list values joined with '; '.
 */
final class Submission_Export_Controller
{
    private Submission_Repository $repo;

    public function __construct(?Submission_Repository $repo = null)
    {
        $this->repo = $repo ?? new Submission_Repository();
    }

    public function handle_export(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('You do not have permission to export submissions.', 'formatrica'));
        }
        check_admin_referer('formatrica_export_submissions');

        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- verified above
        $ids = isset($_GET['ids'])
            ? array_values(array_filter(array_map('intval', explode(',', sanitize_text_field(wp_unslash($_GET['ids']))))))
            : [];
        // phpcs:enable

        $this->export_ids($ids);
    }

    /**
     * Stream the given submissions as a CSV download, then exit. The CALLER
     * must have already run the capability + nonce checks (this is invoked both
     * from the admin-post handler above and directly from Submissions_Page::load(),
     * which streams under the already-verified bulk-submissions nonce so no
     * second nonce/redirect is needed).
     *
     * @param list<int> $ids
     */
    public function export_ids(array $ids): void
    {
        $ids = array_values(array_filter(array_map('intval', $ids), static fn ($i) => $i > 0));
        if ($ids === []) {
            wp_die(esc_html__('No submissions selected for export.', 'formatrica'));
        }

        $details = [];
        foreach ($ids as $id) {
            $detail = $this->repo->get_detail($id);
            if ($detail !== null) {
                $details[] = $detail;
            }
        }
        if ($details === []) {
            wp_die(esc_html__('No submissions found for export.', 'formatrica'));
        }

        // Union of field names across the exported rows, in first-seen order.
        $field_names = [];
        foreach ($details as $detail) {
            foreach (array_keys($detail['data']) as $name) {
                if (!in_array($name, $field_names, true)) {
                    $field_names[] = $name;
                }
            }
        }

        $filename = 'formatrica-submissions-' . gmdate('Ymd-His') . '.csv';
        nocache_headers();
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="' . $filename . '"');

        $out = fopen('php://output', 'w');
        fputcsv($out, array_merge(['id', 'uuid', 'form', 'status', 'created_at', 'ip_address'], $field_names));

        foreach ($details as $detail) {
            $row = [
                $detail['id'],
                $detail['uuid'],
                $detail['form_title'],
                $detail['status'],
                $detail['created_at'],
                $detail['ip_address'],
            ];
            foreach ($field_names as $name) {
                $value = $detail['data'][$name] ?? '';
                if (is_array($value)) {
                    $value = implode('; ', array_map('strval', $value));
                }
                $row[] = $value;
            }
            fputcsv($out, array_map([$this, 'guard_cell'], $row));
        }

        fclose($out); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose
        exit;
    }

    public function handle_delete(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('You do not have permission to delete submissions.', 'formatrica'));
        }

        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- verified below
        $id = isset($_GET['submission_id']) ? (int) $_GET['submission_id'] : 0;
        // phpcs:enable
        check_admin_referer('formatrica_delete_submission_' . $id);

        if ($id > 0) {
            $this->repo->delete_by_ids([$id]);
        }

        wp_safe_redirect(add_query_arg(['page' => 'formatrica-submissions', 'deleted' => 1], admin_url('admin.php')));
        exit;
    }

    /**
     * Row-action read/unread toggle for a single submission.
     */
    public function handle_mark(): void
    {
        if (!current_user_can('manage_options')) {
            wp_die(esc_html__('You do not have permission to update submissions.', 'formatrica'));
        }

        // phpcs:disable WordPress.Security.NonceVerification.Recommended -- verified below
        $id = isset($_GET['submission_id']) ? (int) $_GET['submission_id'] : 0;
        $status = (isset($_GET['status']) && $_GET['status'] === 'read') ? 'read' : 'new';
        // phpcs:enable
        check_admin_referer('formatrica_mark_submission_' . $id);

        if ($id > 0) {
            $this->repo->mark_status([$id], $status);
        }

        wp_safe_redirect(add_query_arg(
            ['page' => 'formatrica-submissions', 'marked' => 1, 'marked_as' => $status],
            admin_url('admin.php')
        ));
        exit;
    }

    /**
     * Formula-injection guard: a leading = + - @ (or tab/CR variants) gets an
     * apostrophe prefix so spreadsheet apps treat the cell as text.
     *
     * @param mixed $value
     */
    private function guard_cell($value): string
    {
        $value = is_scalar($value) ? (string) $value : '';
        if ($value !== '' && preg_match('/^[=+\-@\t\r]/', $value)) {
            return "'" . $value;
        }
        return $value;
    }
}
