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';

/**
 * Title Length Repair — Phase 3.
 *
 * Detects confirmed (rendered-verified) too-long titles and offers a
 * deterministic shorter SEO title PER TITLE with explicit apply. There is no
 * bulk commit. Apply writes only _prorank_seo_title and keeps a restorable
 * backup; post_title is never touched.
 */
const TitleRepairPanel = () => {
  const [busy, setBusy] = useState('');
  const [error, setError] = useState('');
  const [scan, setScan] = useState(null);
  const [rowState, setRowState] = useState({}); // id -> {suggested, applied, busy}

  const doScan = useCallback(async () => {
    setBusy('scan');
    setError('');
    try {
      const res = await apiFetch({ path: 'prorank-seo/v1/titles/scan?verify=1&limit=500' });
      setScan(res);
      setRowState({});
    } catch (e) {
      setError(e?.message || __('Scan failed.', TD));
    } finally {
      setBusy('');
    }
  }, []);

  const setRow = (id, patch) =>
    setRowState((s) => ({ ...s, [id]: { ...(s[id] || {}), ...patch } }));

  const suggest = useCallback(async (id) => {
    setRow(id, { busy: 'suggest' });
    try {
      const r = await apiFetch({ path: `prorank-seo/v1/titles/suggest/${id}`, method: 'POST' });
      setRow(id, { suggested: r, busy: '' });
    } catch (e) {
      setRow(id, { busy: '', err: e?.message || __('Suggest failed.', TD) });
    }
  }, []);

  const apply = useCallback(async (id, title, dryRun) => {
    setRow(id, { busy: dryRun ? 'preview' : 'apply' });
    try {
      const r = await apiFetch({
        path: `prorank-seo/v1/titles/apply/${id}`,
        method: 'POST',
        data: { title, dry_run: dryRun },
      });
      setRow(id, { applied: r, busy: '', err: '' });
    } catch (e) {
      setRow(id, { busy: '', err: e?.message || __('Apply failed.', TD) });
    }
  }, []);

  const buckets = scan?.buckets || null;
  const confirmed = (scan?.items || []).filter((m) => m.verification === 'too_long_confirmed');

  return (
    <ProrankCard>
      <ProrankCardBody>
        <h2 className="pr:text-lg pr:font-semibold pr:mb-1">{__('Title Length Repair', TD)}</h2>
        <p className="pr:text-sm pr:text-gray-600 pr:mb-4">
          {__(
            'Confirmed (rendered-verified) too-long titles. Apply a deterministic shorter SEO title per page — this writes only the ProRank SEO title (never the post title) and keeps a restorable backup. There is no bulk apply.',
            TD
          )}
        </p>

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

        <div className="pr:mb-4">
          <ProrankButton variant="secondary" onClick={doScan} disabled={!!busy}>
            {busy === 'scan' ? __('Scanning…', TD) : __('Scan & verify', TD)}
          </ProrankButton>
        </div>

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

        {buckets ? (
          <div className="pr:mb-4">
            <div className="pr:text-3xl pr:font-bold">{buckets.too_long_confirmed || 0}</div>
            <div className="pr:text-sm pr:text-gray-700">
              {buckets.complete
                ? __('Confirmed too-long titles (rendered-verified — full-site real number)', TD)
                : sprintf(
                    __('Confirmed too-long so far — LOWER BOUND (%d of %d verified)', TD),
                    buckets.examined || 0,
                    buckets.stored_too_long || 0
                  )}
            </div>
            <p className="pr:text-xs pr:text-gray-500 pr:mt-1">
              {sprintf(
                __(
                  '%d titles are over the limit only because of the site-name suffix — already stripped at render time, not a problem.',
                  TD
                ),
                buckets.mechanically_ok_after_sitename_omit || 0
              )}
            </p>
          </div>
        ) : null}

        {confirmed.length ? (
          <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">{__('Current rendered title', TD)}</th>
                <th className="pr:py-2">{__('Suggested', TD)}</th>
                <th className="pr:py-2">{__('Actions', TD)}</th>
              </tr>
            </thead>
            <tbody>
              {confirmed.slice(0, 100).map((m) => {
                const rs = rowState[m.id] || {};
                const sug = rs.suggested;
                return (
                  <tr key={m.id} className="pr:border-b pr:align-top">
                    <td className="pr:py-2">
                      <a href={m.edit_link} target="_blank" rel="noreferrer">
                        {m.rendered_title || m.title || `#${m.id}`}
                      </a>
                      <div className="pr:text-xs pr:text-gray-500">
                        {sprintf(__('%d chars · source: %s', TD), m.rendered_len || 0, m.source || '')}
                      </div>
                    </td>
                    <td className="pr:py-2">
                      {sug ? (
                        <>
                          <div>{sug.suggested_title}</div>
                          <div className="pr:text-xs pr:text-gray-500">
                            {sprintf(__('%d chars · %s · %s', TD), sug.suggested_len || 0, sug.method || '', sug.within_limit ? __('within limit', TD) : __('STILL OVER', TD))}
                          </div>
                        </>
                      ) : (
                        <span className="pr:text-gray-400">{__('—', TD)}</span>
                      )}
                      {rs.applied ? (
                        <div className="pr:text-xs pr:mt-1">
                          {rs.applied.mutated
                            ? __('Applied. Backup kept.', TD)
                            : rs.applied.reason === 'dry_run'
                              ? __('Preview only — not written.', TD)
                              : `${__('No change:', TD)} ${rs.applied.reason}`}
                        </div>
                      ) : null}
                      {rs.err ? (
                        <div className="pr:text-xs pr:text-red-600 pr:mt-1">{rs.err}</div>
                      ) : null}
                    </td>
                    <td className="pr:py-2">
                      <div className="pr:flex pr:gap-1 pr:flex-wrap">
                        <ProrankButton
                          variant="tertiary"
                          onClick={() => suggest(m.id)}
                          disabled={!!rs.busy}
                        >
                          {rs.busy === 'suggest' ? __('…', TD) : __('Suggest', TD)}
                        </ProrankButton>
                        <ProrankButton
                          variant="secondary"
                          onClick={() => apply(m.id, sug.suggested_title, true)}
                          disabled={!!rs.busy || !sug || !sug.within_limit}
                        >
                          {rs.busy === 'preview' ? __('…', TD) : __('Preview', TD)}
                        </ProrankButton>
                        <ProrankButton
                          variant="primary"
                          onClick={() => {
                            // eslint-disable-next-line no-alert
                            if (
                              window.confirm(
                                __('Apply this SEO title? Only the ProRank SEO title changes; a restorable backup is kept.', TD)
                              )
                            ) {
                              apply(m.id, sug.suggested_title, false);
                            }
                          }}
                          disabled={!!rs.busy || !sug || !sug.within_limit || !(rs.applied && rs.applied.reason === 'dry_run')}
                        >
                          {rs.busy === 'apply' ? __('…', TD) : __('Apply', TD)}
                        </ProrankButton>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        ) : scan ? (
          <ProrankNotice status="success" isDismissible={false}>
            {__('No confirmed rendered too-long titles. Nothing needs a rewrite.', TD)}
          </ProrankNotice>
        ) : null}
      </ProrankCardBody>
    </ProrankCard>
  );
};

export default TitleRepairPanel;
