<?php

declare(strict_types=1);

namespace FecaMailshots\Admin;

use FecaMailshots\Application\MailshotRunService;
use FecaMailshots\Application\MailshotService;
use FecaMailshots\WordPress\WordPressFacade;

final class RunMailshotAdminPage
{
    use AdminRequestHelpers;

    private const RESULT_OPTION_KEY = 'feca_mailshots_run_ui_result';
    private const CAPABILITY = 'edit_pages';
    private const NONCE_ACTION = 'feca_mailshots_run';

    /** @var callable(): MailshotRunService */
    private $runServiceFactory;

    /** @var callable(): MailshotService */
    private $mailshotServiceFactory;

    private WordPressFacade $wp;

    /** @param callable(): MailshotRunService $runServiceFactory @param callable(): MailshotService $mailshotServiceFactory */
    public function __construct(callable $runServiceFactory, callable $mailshotServiceFactory, WordPressFacade $wp)
    {
        $this->runServiceFactory = $runServiceFactory;
        $this->mailshotServiceFactory = $mailshotServiceFactory;
        $this->wp = $wp;
    }

    public function register(): void
    {
        $this->wp->addAction('admin_menu', [$this, 'registerMenu']);
        $this->wp->addAction('admin_post_feca_mailshots_run_api', [$this, 'handleApi']);
        $this->wp->addAction('admin_post_feca_mailshots_run_execute_ui', [$this, 'handleRunUi']);
        $this->wp->addAction('admin_post_feca_mailshots_retry_failed_ui', [$this, 'handleRetryFailedUi']);
        $this->wp->addAction('admin_post_feca_mailshots_retry_recipient_ui', [$this, 'handleRetryRecipientUi']);
    }

    public function registerMenu(): void
    {
        $this->wp->addSubmenuPage('feca-mailshot', 'Run Mailshot', 'Run Mailshot', self::CAPABILITY, 'feca-mailshots-run', [$this, 'render']);
    }

    public function render(): void
    {
        if (!$this->wp->currentUserCan(self::CAPABILITY)) {
            echo 'Permission denied';
            return;
        }

        $mailshots = $this->mailshotService()->list();
        $selectedMailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
        if ($selectedMailshotId <= 0 && $mailshots !== []) {
            $selectedMailshotId = (int) ($mailshots[0]['id'] ?? 0);
        }

        $result = $this->result();
        $lastRunRows = $selectedMailshotId > 0 ? $this->mailshotService()->lastRun($selectedMailshotId) : [];
        $recipientSummary = $selectedMailshotId > 0 ? $this->runService()->recipientCount($selectedMailshotId) : ['ok' => false, 'errors' => ['No mailshot selected.']];
        $runCount = !empty($recipientSummary['ok']) ? (int) ($recipientSummary['count'] ?? 0) : 0;
        $action = htmlspecialchars($this->wp->adminUrl('admin-post.php'));

        echo '<div class="wrap"><h1>Run Mailshot</h1>';
        echo '<p>Execute full sends and retry failures from the current mailshot last-run rows.</p>';

        if ($result !== null) {
            $ok = !empty($result['ok']);
            $bg = $ok ? '#f1f8e9' : '#ffebee';
            $border = $ok ? '#8bc34a' : '#ef9a9a';
            echo '<div style="padding:10px;border:1px solid ' . $border . ';background:' . $bg . ';margin:12px 0;">';
            echo '<strong>' . ($ok ? 'Run action completed.' : 'Run action failed.') . '</strong>';
            if ($ok) {
                echo '<p>attempted=' . (int) ($result['attempted'] ?? 0)
                    . ', sent=' . (int) ($result['sent'] ?? 0)
                    . ', failed=' . (int) ($result['failed'] ?? 0)
                    . ', warnings=' . (int) ($result['warnings'] ?? 0)
                    . ', skipped=' . (int) ($result['skipped'] ?? 0)
                    . '</p>';
            }
            if (!empty($result['errors']) && is_array($result['errors'])) {
                echo '<p style="margin:6px 0 0 0;">' . htmlspecialchars(implode('; ', $result['errors'])) . '</p>';
            }
            echo '<details style="margin-top:8px;"><summary>Show technical details</summary><pre style="margin-top:8px;">' . htmlspecialchars(json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)) . '</pre></details>';
            echo '</div>';
        }

        echo '<div style="padding:12px;border:1px solid #dcdcde;background:#fff;margin-bottom:12px;">';
        echo '<h2 style="margin-top:0;">1. Select Mailshot</h2>';
        echo '<form method="get" action="' . htmlspecialchars($this->wp->adminUrl('admin.php')) . '" style="margin-bottom:0;" id="run-mailshot-picker">';
        echo '<input type="hidden" name="page" value="feca-mailshots-run">';
        echo '<div style="display:flex;gap:12px;align-items:center;flex-wrap:wrap;">';
        echo '<div style="display:flex;align-items:center;gap:8px;padding-top:6px;min-width:360px;">';
        echo '<label for="run_mailshot_id" style="white-space:nowrap;padding-left:4px;"><strong>Mailshot</strong></label>';
        echo '<select id="run_mailshot_id" name="mailshot_id" onchange="document.getElementById(\'run-mailshot-picker\').submit();">';
        foreach ($mailshots as $m) {
            $id = (int) ($m['id'] ?? 0);
            $sel = $id === $selectedMailshotId ? ' selected' : '';
            $label = trim((string) ($m['Purpose'] ?? ''));
            if ($label === '') {
                $label = 'Mailshot #' . $id;
            }
            echo '<option value="' . $id . '"' . $sel . '>' . htmlspecialchars($label) . '</option>';
        }
        echo '</select></div></div>';
        echo '</form>';
        if (!empty($recipientSummary['ok'])) {
            echo '<p style="margin-top:8px;"><strong>Recipient rows:</strong> ' . (int) ($recipientSummary['count'] ?? 0) . '</p>';
        } elseif (!empty($recipientSummary['errors']) && is_array($recipientSummary['errors'])) {
            echo '<p style="margin-top:8px;color:#b32d2e;"><strong>Recipient count failed:</strong> ' . htmlspecialchars(implode('; ', $recipientSummary['errors'])) . '</p>';
        }
        echo '</div>';

        echo '<form method="post" action="' . $action . '" style="padding:12px;border:1px solid #dcdcde;background:#fff;margin-bottom:12px;">';
        echo '<h2 style="margin-top:0;">2. Run Actions</h2>';
        echo $this->hiddenNonceField(self::NONCE_ACTION);
        echo '<input type="hidden" name="mailshot_id" value="' . $selectedMailshotId . '">';
        echo '<button class="button button-primary" type="submit" name="action" value="feca_mailshots_run_execute_ui" onclick="return confirm(\'Run Mailshot for ' . $runCount . ' recipients?\');">Run Mailshot</button> ';
        echo '<button class="button" type="submit" name="action" value="feca_mailshots_retry_failed_ui" onclick="return confirm(\'Retry all failed recipients for this mailshot?\');">Retry Failed Sends</button>';
        echo '</form>';

        echo '<div style="padding:12px;border:1px solid #dcdcde;background:#fff;">';
        echo '<h2 style="margin-top:0;">3. Last Run Rows</h2>';
        if ($lastRunRows === []) {
            echo '<p>No rows in mailshot_last_run for this mailshot.</p>';
        } else {
            echo '<table class="widefat striped"><thead><tr><th>Recipient Key</th><th>Email</th><th>Status</th><th>Attempts</th><th>Error/Warning</th><th>Retry</th></tr></thead><tbody>';
            foreach ($lastRunRows as $row) {
                $recipientKey = (string) ($row['recipient_key'] ?? '');
                $status = (string) ($row['status'] ?? '');
                $msg = (string) (($row['error_message'] ?? '') ?: ($row['warning_message'] ?? ''));
                echo '<tr>';
                echo '<td>' . htmlspecialchars($recipientKey) . '</td>';
                echo '<td>' . htmlspecialchars((string) ($row['recipient_email_last'] ?? '')) . '</td>';
                echo '<td>' . htmlspecialchars($status) . '</td>';
                echo '<td>' . (int) ($row['attempt_count'] ?? 0) . '</td>';
                echo '<td>' . htmlspecialchars($msg) . '</td>';
                echo '<td>';
                if ($status === 'failed') {
                    echo '<form method="post" action="' . $action . '">';
                    echo '<input type="hidden" name="action" value="feca_mailshots_retry_recipient_ui">';
                    echo $this->hiddenNonceField(self::NONCE_ACTION);
                    echo '<input type="hidden" name="mailshot_id" value="' . $selectedMailshotId . '">';
                    echo '<input type="hidden" name="recipient_key" value="' . htmlspecialchars($recipientKey, ENT_QUOTES) . '">';
                    echo '<button class="button" type="submit" onclick="return confirm(\'Retry this failed recipient now?\');">Retry</button>';
                    echo '</form>';
                }
                echo '</td>';
                echo '</tr>';
            }
            echo '</tbody></table>';
        }
        echo '</div>';

        echo '</div>';
    }

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

        $op = (string) ($this->wp->requestParam('op', '') ?? '');
        $service = $this->runService();

        try {
            if ($op === 'run_mailshot') {
                $mailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
                $this->wp->sendJson($service->runMailshot($mailshotId));
                return;
            }

            if ($op === 'retry_failed') {
                $mailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
                $this->wp->sendJson($service->retryFailed($mailshotId));
                return;
            }

            if ($op === 'retry_recipient') {
                $mailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
                $recipientKey = (string) ($this->wp->requestParam('recipient_key', '') ?? '');
                $this->wp->sendJson($service->retryRecipient($mailshotId, $recipientKey));
                return;
            }

            $this->wp->sendJson(['ok' => false, 'error' => 'Unknown op'], 400);
        } catch (\Throwable $e) {
            $this->wp->sendJson(['ok' => false, 'error' => $e->getMessage()], 500);
        }
    }

    public function handleRunUi(): void
    {
        if (!$this->enforceMutationGuardOrJson(self::CAPABILITY, self::NONCE_ACTION)) {
            return;
        }
        $mailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
        $result = $this->runService()->runMailshot($mailshotId);
        $this->wp->updateOption(self::RESULT_OPTION_KEY, $result);
        $this->redirect($mailshotId);
    }

    public function handleRetryFailedUi(): void
    {
        if (!$this->enforceMutationGuardOrJson(self::CAPABILITY, self::NONCE_ACTION)) {
            return;
        }
        $mailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
        $result = $this->runService()->retryFailed($mailshotId);
        $this->wp->updateOption(self::RESULT_OPTION_KEY, $result);
        $this->redirect($mailshotId);
    }

    public function handleRetryRecipientUi(): void
    {
        if (!$this->enforceMutationGuardOrJson(self::CAPABILITY, self::NONCE_ACTION)) {
            return;
        }
        $mailshotId = (int) ($this->wp->requestParam('mailshot_id', '0') ?? '0');
        $recipientKey = (string) ($this->wp->requestParam('recipient_key', '') ?? '');
        $result = $this->runService()->retryRecipient($mailshotId, $recipientKey);
        $this->wp->updateOption(self::RESULT_OPTION_KEY, $result);
        $this->redirect($mailshotId);
    }

    private function redirect(int $mailshotId): void
    {
        $url = $this->wp->adminUrl('admin.php?page=feca-mailshots-run&mailshot_id=' . $mailshotId);
        if (!headers_sent()) {
            header('Location: ' . $url, true, 302);
            exit;
        }
    }

    /** @return array<string,mixed>|null */
    private function result(): ?array
    {
        $raw = $this->wp->getOption(self::RESULT_OPTION_KEY, null);
        $this->wp->deleteOption(self::RESULT_OPTION_KEY);
        return is_array($raw) ? $raw : null;
    }

    private function runService(): MailshotRunService
    {
        return ($this->runServiceFactory)();
    }

    private function mailshotService(): MailshotService
    {
        return ($this->mailshotServiceFactory)();
    }
}
