import { useState, useCallback } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';

import ProrankButton from '../../../components/ProrankButton';
import { ProrankCard, ProrankCardBody } from '../../../components/ProrankCard';
import { ProrankSpinner } from '../../../components/ProrankSpinner';
import { ProrankNotice } from '../../../components/ProrankNotice';

const TD = 'prorank-seo';

/**
 * Missing / empty H1 repair panel.
 *
 * Flow: Scan → Preview repairs (dry run) → Apply repairs (commit).
 * Bulk apply only ever touches high-confidence + fixable items. Source-level
 * repairs only — there is no global hidden-H1 injector. Every commit keeps a
 * restorable backup server-side.
 */
const H1RepairPanel = () => {
  const [busy, setBusy] = useState('');
  const [error, setError] = useState('');
  const [scan, setScan] = useState(null);
  const [preview, setPreview] = useState(null);
  const [applied, setApplied] = useState(null);

  const run = useCallback(async (phase, request) => {
    setBusy(phase);
    setError('');
    try {
      return await request();
    } catch (e) {
      setError(e?.message || __('Request failed.', TD));
      return null;
    } finally {
      setBusy('');
    }
  }, []);

  const doScan = useCallback(async () => {
    setPreview(null);
    setApplied(null);
    // verify=1 runs the cache-safe rendered pass so we headline CONFIRMED
    // rendered-missing H1, not the misleading raw stored-content count.
    const res = await run('scan', () =>
      apiFetch({ path: 'prorank-seo/v1/h1/scan?verify=1&limit=200' })
    );
    if (res) setScan(res);
  }, [run]);

  const repairAll = useCallback(
    async (dryRun) => {
      const res = await run(dryRun ? 'preview' : 'apply', () =>
        apiFetch({
          path: 'prorank-seo/v1/h1/repair-all',
          method: 'POST',
          // Bulk from the UI is ALWAYS high-confidence-only. Low-confidence
          // repair is intentionally CLI-only (wp prorank h1 repair-all
          // --include-low-confidence) so it can't be mass-applied by accident.
          data: { dry_run: dryRun, high_confidence_only: true, limit: 200 },
        })
      );
      if (!res) return;
      if (dryRun) {
        setPreview(res);
        setApplied(null);
      } else {
        setApplied(res);
        const fresh = await apiFetch({ path: 'prorank-seo/v1/h1/scan?verify=1&limit=200' }).catch(
          () => null
        );
        if (fresh) setScan(fresh);
      }
    },
    [run]
  );

  const buckets = scan?.buckets || null;
  const items = scan?.items || [];
  const confirmed = items.filter((m) => m.verification === 'rendered_missing_confirmed');
  const confirmedCount = buckets ? buckets.rendered_missing_confirmed || 0 : 0;
  // Only pages bulk repair-all will actually touch: confirmed-missing AND
  // fixable AND not a utility/noindex page AND high-confidence (Elementor).
  // confirmedCount alone over-enables the buttons (e.g. 3 confirmed utility
  // pages would enable preview, then repair 0).
  const safeBulkRepairable = confirmed.filter(
    (m) => m.fixable && !m.bulk_excluded && m.confidence === 'high'
  );
  const confirmedExcluded = confirmedCount - safeBulkRepairable.length;
  const unverifiedRemaining = buckets ? buckets.unverified_remaining || 0 : 0;
  const verifyComplete = buckets ? !!buckets.complete : false;
  const totals = preview?.totals || applied?.totals || null;

  return (
    <ProrankCard>
      <ProrankCardBody>
        <h2 className="pr:text-lg pr:font-semibold pr:mb-1">
          {__('H1 Safety — Missing / Empty H1 Repair', TD)}
        </h2>
        <p className="pr:text-sm pr:text-gray-600 pr:mb-4">
          {__(
            'Detects pages with no H1 and applies a source-level fix (Elementor widget, Gutenberg block, or classic content). No hidden H1 is ever injected. Every applied fix keeps a restorable backup.',
            TD
          )}
        </p>

        {error ? (
          <ProrankNotice status="error" isDismissible={false}>
            {error}
          </ProrankNotice>
        ) : null}

        <div className="pr:flex pr:gap-2 pr:flex-wrap pr:mb-4">
          <ProrankButton variant="secondary" onClick={doScan} disabled={!!busy}>
            {busy === 'scan' ? __('Scanning…', TD) : __('Scan', TD)}
          </ProrankButton>
          <ProrankButton
            variant="secondary"
            onClick={() => repairAll(true)}
            disabled={!!busy || !scan || safeBulkRepairable.length === 0}
          >
            {busy === 'preview' ? __('Previewing…', TD) : __('Preview repairs', TD)}
          </ProrankButton>
          <ProrankButton
            variant="primary"
            onClick={() => {
              // eslint-disable-next-line no-alert
              if (window.confirm(__('Apply H1 repairs now? Each change keeps a restorable backup.', TD))) {
                repairAll(false);
              }
            }}
            disabled={!!busy || !preview || (preview?.totals?.mutated || 0) === 0}
          >
            {busy === 'apply' ? __('Applying…', TD) : __('Apply repairs', TD)}
          </ProrankButton>
        </div>

        <p className="pr:text-xs pr:text-gray-600 pr:mb-4">
          {__(
            'Bulk repair only ever touches high-confidence, fixable pages. Low-confidence pages (where the theme may already render an H1) are never mass-applied here — use the WP-CLI advanced flag if you need them.',
            TD
          )}
        </p>

        {busy ? (
          <div className="pr:flex pr:items-center pr:gap-2 pr:py-3">
            <ProrankSpinner size="small" />
            <span className="pr:text-sm">{__('Working…', TD)}</span>
          </div>
        ) : null}

        {buckets ? (
          <>
            <div className="pr:mb-3">
              <div className="pr:text-3xl pr:font-bold">{confirmedCount}</div>
              <div className="pr:text-sm pr:text-gray-700">
                {verifyComplete
                  ? __('Confirmed missing H1 (rendered-verified — full-site real number)', TD)
                  : sprintf(
                      __(
                        'Confirmed missing H1 so far — LOWER BOUND only (%d of %d stored misses verified)',
                        TD
                      ),
                      buckets.examined || 0,
                      buckets.stored_missing || 0
                    )}
              </div>
            </div>
            {!verifyComplete && unverifiedRemaining > 0 ? (
              <ProrankNotice status="warning" isDismissible={false}>
                {sprintf(
                  __(
                    '%d stored-content misses were NOT rendered-verified in this pass. The confirmed number above is a lower bound, not the full-site total.',
                    TD
                  ),
                  unverifiedRemaining
                )}
              </ProrankNotice>
            ) : null}
            <div className="pr:grid pr:grid-cols-2 pr:md:grid-cols-4 pr:gap-3 pr:mt-3 pr:mb-2">
              <Stat label={__('Safe to bulk-repair', TD)} value={safeBulkRepairable.length} />
              <Stat label={__('Confirmed but excluded', TD)} value={Math.max(0, confirmedExcluded)} />
              <Stat label={__('Theme renders H1', TD)} value={buckets.theme_renders_h1 || 0} />
              <Stat label={__('Inconclusive', TD)} value={buckets.inconclusive || 0} />
              <Stat label={__('Utility (excluded from bulk)', TD)} value={buckets.bulk_excluded || 0} />
              <Stat label={__('Not yet verified', TD)} value={unverifiedRemaining} />
              <Stat
                label={__('Stored-content missing (raw)', TD)}
                value={buckets.stored_missing || 0}
              />
            </div>
            <p className="pr:text-xs pr:text-gray-500 pr:mb-4">
              {__(
                'Only "Safe to bulk-repair" pages are touched by Preview/Apply (confirmed-missing, fixable, not a utility/noindex page, high-confidence). "Confirmed but excluded" are real misses that need manual or CLI handling.',
                TD
              )}
            </p>
          </>
        ) : null}

        {totals ? (
          <ProrankNotice
            status={applied ? 'success' : 'info'}
            isDismissible={false}
          >
            {applied
              ? sprintf(
                  __('Applied: %d repaired, %d skipped (low-confidence), %d skipped (theme renders H1).', TD),
                  totals.mutated,
                  totals.skipped_low_confidence,
                  totals.skipped_theme_h1
                )
              : sprintf(
                  __('Preview: %d would be repaired, %d skipped (low-confidence), %d skipped (theme renders H1). Nothing was written.', TD),
                  totals.mutated,
                  totals.skipped_low_confidence,
                  totals.skipped_theme_h1
                )}
          </ProrankNotice>
        ) : null}

        {confirmed.length ? (
          <>
            <h3 className="pr:text-sm pr:font-semibold pr:mt-4 pr:mb-2">
              {__('Confirmed rendered missing-H1 pages', TD)}
            </h3>
            <table className="pr:w-full pr:text-sm pr:border-collapse">
              <thead>
                <tr className="pr:text-left pr:border-b">
                  <th className="pr:py-2">{__('Title', TD)}</th>
                  <th className="pr:py-2">{__('Type', TD)}</th>
                  <th className="pr:py-2">{__('Source', TD)}</th>
                  <th className="pr:py-2">{__('Fixable', TD)}</th>
                  <th className="pr:py-2">{__('Utility', TD)}</th>
                </tr>
              </thead>
              <tbody>
                {confirmed.slice(0, 100).map((m) => (
                  <tr key={m.id} className="pr:border-b">
                    <td className="pr:py-1">
                      <a href={m.edit_link} target="_blank" rel="noreferrer">
                        {m.title || `#${m.id}`}
                      </a>
                    </td>
                    <td className="pr:py-1">{m.type}</td>
                    <td className="pr:py-1">{m.source}</td>
                    <td className="pr:py-1">{m.fixable ? __('yes', TD) : __('no', TD)}</td>
                    <td className="pr:py-1">
                      {m.bulk_excluded ? __('yes (excluded)', TD) : __('no', TD)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </>
        ) : scan ? (
          <ProrankNotice status="success" isDismissible={false}>
            {__('No confirmed rendered missing-H1 pages. Nothing needs repair.', TD)}
          </ProrankNotice>
        ) : null}
      </ProrankCardBody>
    </ProrankCard>
  );
};

const Stat = ({ label, value }) => (
  <div className="pr:rounded-lg pr:border pr:p-3">
    <div className="pr:text-2xl pr:font-semibold">{value}</div>
    <div className="pr:text-xs pr:text-gray-600">{label}</div>
  </div>
);

export default H1RepairPanel;
