<?php

declare(strict_types=1);

namespace FecaMailshots\Admin;

use FecaMailshots\Application\PdfAssetService;
use FecaMailshots\WordPress\WordPressFacade;

final class PdfAssetsAdminPage
{
    use AdminRequestHelpers;

    private const CAPABILITY = 'edit_pages';
    private const RESULT_OPTION_KEY = 'feca_mailshots_pdf_assets_ui_result';
    private const DRAFT_OPTION_KEY = 'feca_mailshots_pdf_assets_ui_draft';
    private const PAGE_SLUG = 'feca-mailshots-pdf-assets';
    private const NONCE_ACTION = 'feca_mailshots_pdf_assets';
    /** @var callable(): PdfAssetService */
    private $serviceFactory;
    private WordPressFacade $wp;

    /** @param callable(): PdfAssetService $serviceFactory */
    public function __construct(callable $serviceFactory, WordPressFacade $wp)
    {
        $this->serviceFactory = $serviceFactory;
        $this->wp = $wp;
    }

    public function register(): void
    {
        $this->wp->addAction('admin_menu', [$this, 'registerMenu']);
        $this->wp->addAction('admin_post_feca_mailshots_pdf_assets_api', [$this, 'handleApi']);
        $this->wp->addAction('admin_post_feca_mailshots_pdf_assets_ui_save', [$this, 'handleUiSave']);
        $this->wp->addAction('admin_post_feca_mailshots_pdf_assets_ui_delete', [$this, 'handleUiDelete']);
    }

    public function registerMenu(): void
    {
        $this->wp->addSubmenuPage('feca-mailshot', 'PDF Assets', 'PDF Assets', self::CAPABILITY, self::PAGE_SLUG, [$this, 'render']);
    }

    public function render(): void
    {
        if (!$this->wp->currentUserCan(self::CAPABILITY)) {
            echo 'Permission denied';
            return;
        }
        $items = $this->service()->list();
        $draft = $this->consumeOptionArray(self::DRAFT_OPTION_KEY);
        $requestedEditId = (int) ($this->wp->requestParam('edit_id', '0') ?? '0');
        $draftId = is_array($draft) && isset($draft['id']) ? (int) $draft['id'] : 0;
        $useDraft = is_array($draft) && (
            $requestedEditId <= 0 || ($draftId > 0 && $draftId === $requestedEditId)
        );
        $editId = $requestedEditId;
        if ($editId <= 0 && $useDraft && $draftId > 0) {
            $editId = $draftId;
        }
        $editItem = null;
        foreach ($items as $row) {
            if ((int) ($row['id'] ?? 0) === $editId) {
                $editItem = $row;
                break;
            }
        }
        $result = $this->consumeOptionArray(self::RESULT_OPTION_KEY);
        $action = htmlspecialchars($this->wp->adminUrl('admin-post.php'));
        $name = (string) ($editItem['name'] ?? '');
        $fileName = (string) ($editItem['file_name'] ?? '');
        $width = (string) ($editItem['width_mm'] ?? '210');
        $height = (string) ($editItem['height_mm'] ?? '297');
        $just = (string) ($editItem['justification'] ?? 'in-place');
        $base64 = '';
        if ($useDraft && is_array($draft)) {
            $name = (string) ($draft['name'] ?? $name);
            $fileName = (string) ($draft['file_name'] ?? $fileName);
            $width = (string) ($draft['width_mm'] ?? $width);
            $height = (string) ($draft['height_mm'] ?? $height);
            $just = (string) ($draft['justification'] ?? $just);
            $base64 = (string) ($draft['file_bytes_base64'] ?? '');
        }

        echo '<div class="wrap feca-mailshots-admin"><h1>PDF Assets</h1>';
        echo $this->renderAdminUiStyles();
        if ($result !== null) {
            $ok = !empty($result['ok']);
            $title = $ok ? 'PDF asset saved.' : 'PDF asset action failed.';
            $bannerClass = $ok ? 'feca-banner-success' : 'feca-banner-error';
            echo '<div class="feca-banner ' . $bannerClass . '">';
            echo '<strong>' . htmlspecialchars($title) . '</strong>';
            if (!empty($result['errors']) && is_array($result['errors'])) {
                echo '<p class="feca-banner-note">' . htmlspecialchars(implode('; ', $result['errors'])) . '</p>';
            }
            echo '</div>';
        }

        echo '<p class="feca-button-row"><button type="button" class="button button-primary" id="pdf-open-new">New PDF Asset</button></p>';
        echo '<div id="pdf-editor-modal" class="feca-modal-overlay">';
        echo '<div class="feca-modal-shell">';
        echo '<p class="feca-button-row feca-close-row"><button type="button" class="button" id="pdf-close-editor">Quit</button></p>';
        echo '<form method="post" enctype="multipart/form-data" action="' . $action . '" class="feca-form" id="pdf-editor-form">';
        echo '<h2 class="feca-modal-title">' . ($editId > 0 ? 'Edit PDF Asset' : 'New PDF Asset') . '</h2>';
        echo $this->modalErrorHtml($result);
        echo '<input type="hidden" name="action" value="feca_mailshots_pdf_assets_ui_save">';
        echo $this->hiddenNonceField(self::NONCE_ACTION);
        if ($editId > 0) {
            echo '<input type="hidden" name="id" value="' . $editId . '" id="pdf-editor-id">';
        } else {
            echo '<input type="hidden" name="id" value="" id="pdf-editor-id">';
        }
        echo '<table class="form-table" role="presentation">';
        echo '<tr><th scope="row"><label for="pdf_name">Name</label></th><td><input class="regular-text" type="text" id="pdf_name" name="name" value="' . htmlspecialchars($name, ENT_QUOTES) . '"></td></tr>';
        echo '<tr><th scope="row"><label for="pdf_file_name">File Name</label></th><td><input class="regular-text" type="text" id="pdf_file_name" name="file_name" value="' . htmlspecialchars($fileName, ENT_QUOTES) . '"></td></tr>';
        echo '<tr><th scope="row"><label for="pdf_width">Width (mm)</label></th><td><input class="small-text" type="number" step="0.01" id="pdf_width" name="width_mm" value="' . htmlspecialchars($width, ENT_QUOTES) . '"></td></tr>';
        echo '<tr><th scope="row"><label for="pdf_height">Height (mm)</label></th><td><input class="small-text" type="number" step="0.01" id="pdf_height" name="height_mm" value="' . htmlspecialchars($height, ENT_QUOTES) . '"></td></tr>';
        echo '<tr><th scope="row"><label for="pdf_just">Justification</label></th><td><select id="pdf_just" name="justification">';
        foreach (['in-place', 'left', 'right'] as $opt) {
            $selected = $opt === $just ? ' selected' : '';
            echo '<option value="' . htmlspecialchars($opt, ENT_QUOTES) . '"' . $selected . '>' . htmlspecialchars($opt) . '</option>';
        }
        echo '</select></td></tr>';
        echo '<tr><th scope="row"><label for="pdf_file_upload">Upload Image</label></th><td><input type="file" id="pdf_file_upload" name="file_upload" accept="image/*"></td></tr>';
        echo '<tr><th scope="row"><label for="pdf_base64">File Bytes (Base64)</label></th><td><textarea id="pdf_base64" name="file_bytes_base64" rows="4" class="large-text code">' . htmlspecialchars($base64) . '</textarea><p class="description">Provide base64 directly, or use file upload above.</p></td></tr>';
        echo '</table>';
        echo '<p class="feca-button-row"><button type="submit" class="button button-primary">' . ($editId > 0 ? 'Update PDF Asset' : 'Create PDF Asset') . '</button> ';
        if ($editId > 0) {
            echo '<a class="button" href="' . htmlspecialchars($this->wp->adminUrl('admin.php?page=' . self::PAGE_SLUG)) . '">Cancel Edit</a>';
        }
        echo '</p></form>';
        echo '</div></div>';

        echo '<h2>Existing PDF Assets</h2>';
        echo '<div class="feca-scroll-frame"><div class="feca-scroll-pane">';
        echo '<table class="widefat striped"><thead><tr><th>ID</th><th>Name</th><th>File</th><th>Size (mm)</th><th>Justification</th><th>Bytes</th><th>Actions</th></tr></thead><tbody>';
        foreach ($items as $row) {
            $id = (int) ($row['id'] ?? 0);
            $editUrl = $this->wp->adminUrl('admin.php?page=feca-mailshots-pdf-assets&edit_id=' . $id);
            echo '<tr>';
            echo '<td>' . $id . '</td>';
            echo '<td>' . htmlspecialchars((string) ($row['name'] ?? '')) . '</td>';
            echo '<td>' . htmlspecialchars((string) ($row['file_name'] ?? '')) . '</td>';
            echo '<td>' . htmlspecialchars((string) ($row['width_mm'] ?? '')) . ' x ' . htmlspecialchars((string) ($row['height_mm'] ?? '')) . '</td>';
            echo '<td>' . htmlspecialchars((string) ($row['justification'] ?? '')) . '</td>';
            echo '<td>' . htmlspecialchars((string) ($row['byte_size'] ?? '')) . '</td>';
            echo '<td><a class="button button-small" href="' . htmlspecialchars($editUrl) . '">Edit</a> ';
            echo '<form method="post" action="' . $action . '" class="feca-inline-form">';
            echo '<input type="hidden" name="action" value="feca_mailshots_pdf_assets_ui_delete">';
            echo $this->hiddenNonceField(self::NONCE_ACTION);
            echo '<input type="hidden" name="id" value="' . $id . '">';
            echo '<button type="submit" class="button button-small feca-button-danger" onclick="return confirm(\'Delete this PDF asset?\');">Delete</button>';
            echo '</form></td>';
            echo '</tr>';
        }
        if ($items === []) {
            echo '<tr><td colspan="7">No PDF assets found.</td></tr>';
        }
        echo '</tbody></table>';
        echo '</div></div>';
        echo $this->modalEditorScript(
            'pdf-editor-modal',
            'pdf-open-new',
            'pdf-close-editor',
            'pdf-editor-form',
            'pdf-editor-id',
            ['pdf_name', 'pdf_file_name', 'pdf_width', 'pdf_height', 'pdf_base64'],
            $editId > 0,
            $useDraft,
            $result !== null,
            !empty($result['ok']),
            'pdf_just',
            'in-place',
            'pdf_file_upload',
            'pdf_file_name'
        );
        echo '</div>';
    }

    public function handleUiSave(): void
    {
        if (!$this->enforceMutationGuardOrJson(self::CAPABILITY, self::NONCE_ACTION)) {
            return;
        }
        $id = $this->requestOptionalInt('id');
        $uploadedBase64 = $this->uploadedFileToBase64('file_upload');
        $base64 = $uploadedBase64 !== null ? $uploadedBase64 : $this->requestString('file_bytes_base64', '');
        $payload = $this->pdfAssetPayload($base64);
        $result = $this->service()->save($id, $payload);
        $this->persistResultAndDraft(self::RESULT_OPTION_KEY, self::DRAFT_OPTION_KEY, $result, ['id' => $id] + $payload);
        $editId = $id;
        if (!empty($result['ok']) && isset($result['id'])) {
            $editId = (int) $result['id'];
        }
        $this->redirectToAdminPage(self::PAGE_SLUG, $editId);
    }

    public function handleUiDelete(): void
    {
        if (!$this->enforceMutationGuardOrJson(self::CAPABILITY, self::NONCE_ACTION)) {
            return;
        }
        $id = $this->requestInt('id', 0);
        $result = ['ok' => true];
        try {
            if ($id > 0) {
                $this->service()->delete($id);
            }
        } catch (\Throwable $e) {
            $result = ['ok' => false, 'errors' => [$e->getMessage()]];
        }
        $this->wp->updateOption(self::RESULT_OPTION_KEY, $result);
        $this->redirectToAdminPage(self::PAGE_SLUG);
    }

    public function handleApi(): void
    {
        if (!$this->enforceCapabilityOrJson(self::CAPABILITY)) {
            return;
        }

        $op = $this->requestString('op', 'list');

        try {
            $this->handleBasicCrudApi(
                $op,
                fn(): array => ['ok' => true, 'items' => $this->service()->list()],
                function (): array {
                    if (!$this->mutationGuardValid(self::CAPABILITY, self::NONCE_ACTION)) {
                        return ['ok' => false, 'error' => 'Mutation guard rejected request.'];
                    }
                    $id = $this->requestOptionalInt('id');
                    $payload = $this->pdfAssetPayload($this->requestString('file_bytes_base64', ''));
                    return $this->service()->save($id, $payload);
                },
                function (): array {
                    if (!$this->mutationGuardValid(self::CAPABILITY, self::NONCE_ACTION)) {
                        return ['ok' => false, 'error' => 'Mutation guard rejected request.'];
                    }
                    $id = $this->requestInt('id', 0);
                    $this->service()->delete($id);
                    return ['ok' => true];
                }
            );
        } catch (\Throwable $e) {
            $this->wp->sendJson(['ok' => false, 'error' => $e->getMessage()], 500);
        }
    }

    private function service(): PdfAssetService
    {
        return ($this->serviceFactory)();
    }

    /** @return array{name:string,file_name:string,mime_type:string,file_bytes_base64:string,width_mm:string,height_mm:string,justification:string} */
    private function pdfAssetPayload(string $base64): array
    {
        return [
            'name' => $this->requestString('name', ''),
            'file_name' => $this->requestString('file_name', ''),
            'mime_type' => $this->requestString('mime_type', ''),
            'file_bytes_base64' => $base64,
            'width_mm' => $this->requestString('width_mm', '0'),
            'height_mm' => $this->requestString('height_mm', '0'),
            'justification' => $this->requestString('justification', 'in-place'),
        ];
    }

}
