<?php

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- APD is the established namespace shared with the Pro add-on and retained for backward compatibility.
namespace APD\Admin;

use APD\PostTypes\ProductConfigPostType;
use APD\Portability\ProductPackageArchive;
use APD\Portability\ProductPackageExporter;
use APD\Portability\ProductPackageImporter;
use APD\Repositories\ProductConfigRepository;
use APD\Support\Capabilities;
use APD\Support\RequestData;

defined('ABSPATH') || exit;

class ToolsController
{
    public function exportProductPackage() : void
    {
        $this->authorize(__('You are not allowed to export product packages.', 'asuka-product-designer'));
        check_admin_referer('apd_export_product_package');

        $query = RequestData::query();
        $result = (new ProductPackageExporter())->export(absint($query['config_id'] ?? 0), [
            'includeAssets' => ! empty($query['include_assets']),
            'includeTemplate' => ! empty($query['include_template']),
            'includeThemes' => ! empty($query['include_themes']),
        ]);
        if (is_wp_error($result)) {
            $this->redirectError('package_export_failed', $result);
        }

        $path = (string) $result['path'];
        nocache_headers();
        header('Content-Type: application/zip');
        header('Content-Disposition: attachment; filename="' . sanitize_file_name((string) $result['filename']) . '"');
        header('Content-Length: ' . (string) filesize($path));
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile -- Streaming the generated ZIP avoids loading a potentially large package into PHP memory.
        readfile($path);
        foreach ((array) ($result['cleanup'] ?? []) as $directory) {
            ProductPackageArchive::removeDirectory((string) $directory);
        }
        exit;
    }

    public function inspectProductPackage() : void
    {
        $this->authorize(__('You are not allowed to import product packages.', 'asuka-product-designer'));
        check_admin_referer('apd_inspect_product_package');

        $files = RequestData::files();
        $file = isset($files['apd_product_package']) && is_array($files['apd_product_package'])
            ? $files['apd_product_package']
            : [];
        $result = (new ProductPackageImporter())->stageUpload($file);
        if (is_wp_error($result)) {
            $this->redirectError('package_inspect_failed', $result);
        }

        wp_safe_redirect(add_query_arg([
            'page' => 'apd-tools',
            'package_token' => sanitize_key((string) $result['token']),
        ], admin_url('admin.php')));
        exit;
    }

    public function importProductPackage() : void
    {
        $this->authorize(__('You are not allowed to import product packages.', 'asuka-product-designer'));
        check_admin_referer('apd_import_product_package');

        $post = RequestData::post();
        $token = sanitize_key((string) ($post['package_token'] ?? ''));
        $result = (new ProductPackageImporter())->importToken($token, [
            'existingConfigId' => absint($post['existing_config_id'] ?? 0),
            'dependencyPolicy' => sanitize_key((string) ($post['dependency_policy'] ?? 'copy')),
        ]);
        if (is_wp_error($result)) {
            $this->redirectError('package_import_failed', $result, ['package_token' => $token]);
        }

        $configId = (int) $result['configId'];
        set_transient('apd_package_result_' . get_current_user_id(), $result, 120);
        if (! empty($post['open_after_import'])) {
            AdminNoticeStore::push(
                'post_' . $configId,
                sprintf(
                    /* translators: Placeholder values are populated from the current administration record. */ __('Portable product imported. %1$d media files were added and %2$d media references were resolved.', 'asuka-product-designer'),
                    (int) ($result['assetsImported'] ?? 0),
                    (int) ($result['assetsResolved'] ?? 0)
                ),
                'success'
            );
        }
        $redirect = ! empty($post['open_after_import'])
            ? admin_url('post.php?post=' . $configId . '&action=edit&apd_notice=package_imported')
            : add_query_arg([
                'page' => 'apd-tools',
                'apd_notice' => 'package_imported',
                'imported_config_id' => $configId,
            ], admin_url('admin.php'));
        wp_safe_redirect($redirect);
        exit;
    }

    public function discardProductPackage() : void
    {
        $this->authorize(__('You are not allowed to manage product packages.', 'asuka-product-designer'));
        check_admin_referer('apd_discard_product_package');
        $post = RequestData::post();
        (new ProductPackageImporter())->discardToken(sanitize_key((string) ($post['package_token'] ?? '')));
        wp_safe_redirect(admin_url('admin.php?page=apd-tools'));
        exit;
    }

    public function exportConfig() : void
    {
        if (! current_user_can(Capabilities::MANAGE)) {
            wp_die(esc_html__('You are not allowed to export configs.', 'asuka-product-designer'));
        }

        check_admin_referer('apd_export_config');

        $query = RequestData::query();
        $configId = absint($query['config_id'] ?? 0);
        $payload = (new ProductConfigRepository())->export($configId);

        if (! $payload) {
            wp_safe_redirect(admin_url('admin.php?page=apd-tools&apd_notice=export_failed'));
            exit;
        }

        nocache_headers();
        header('Content-Type: application/json; charset=' . get_option('blog_charset'));
        header('Content-Disposition: attachment; filename=apd-config-' . $configId . '.json');
        echo wp_json_encode($payload, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        exit;
    }

    public function importConfig() : void
    {
        if (! current_user_can(Capabilities::MANAGE)) {
            wp_die(esc_html__('You are not allowed to import configs.', 'asuka-product-designer'));
        }

        check_admin_referer('apd_import_config');

        $files = RequestData::files();
        $post = RequestData::post();
        $file = isset($files['apd_config_file']) && is_array($files['apd_config_file'])
            ? $files['apd_config_file']
            : [];
        if (empty($file['tmp_name'])) {
            wp_safe_redirect(admin_url('admin.php?page=apd-tools&apd_notice=import_missing'));
            exit;
        }

        $raw = file_get_contents((string) $file['tmp_name']);
        $payload = json_decode((string) $raw, true);
        if (! is_array($payload) || ($payload['schema'] ?? '') !== 'apd-product-config') {
            wp_safe_redirect(admin_url('admin.php?page=apd-tools&apd_notice=import_invalid'));
            exit;
        }

        $existingId = absint($post['apd_existing_config_id'] ?? 0);
        $importedId = (new ProductConfigRepository())->import($payload, $existingId);
        if ($importedId <= 0) {
            wp_safe_redirect(admin_url('admin.php?page=apd-tools&apd_notice=import_failed'));
            exit;
        }

        $redirect = ! empty($post['apd_open_after_import'])
            ? admin_url('post.php?post=' . $importedId . '&action=edit&apd_notice=imported')
            : admin_url('edit.php?post_type=' . ProductConfigPostType::TYPE . '&apd_notice=imported');

        wp_safe_redirect($redirect);
        exit;
    }

    private function authorize(string $message) : void
    {
        if (! current_user_can(Capabilities::MANAGE)) {
            wp_die(esc_html($message));
        }
    }

    private function redirectError(string $notice, \WP_Error $error, array $query = []) : never
    {
        set_transient('apd_tools_error_' . get_current_user_id(), $error->get_error_message(), 120);
        wp_safe_redirect(add_query_arg(array_merge([
            'page' => 'apd-tools',
            'apd_notice' => $notice,
        ], $query), admin_url('admin.php')));
        exit;
    }
}
