import { useEffect, useMemo, useRef, useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { apiFetch } from '../lib/api';
import ScanSlideIn from './ScanSlideIn';
import { PageScannerSkeleton } from './Skeleton';
import type { PageScanSummary, ScannableUrl } from '../lib/types';

const ITEMS_PER_PAGE  = 20;

// ── Pluralise a post-type slug dynamically ────────────────────

function pluralize(type: string): string {
  if (!type) return type;
  const t = type.toLowerCase();
  // Known irregulars
  const irregulars: Record<string, string> = {
    category:   'Categories',
    taxonomy:   'Taxonomies',
    media:      'Media',
    person:     'People',
    // WordPress special page types — always singular
    home:       'Home',
    front_page: 'Front Page',
    search:     'Search',
    '404':      '404',
    archive:    'Archive',
    singular:   'Singular',
  };
  if (irregulars[t]) return irregulars[t];
  // Rules — longest-match first
  if (t.endsWith('quiz'))                        return cap(t) + 'zes';
  if (t.endsWith('s') || t.endsWith('x') ||
      t.endsWith('z') || t.endsWith('ch') ||
      t.endsWith('sh'))                          return cap(t) + 'es';
  if (/[^aeiou]y$/.test(t))                     return cap(t.slice(0, -1)) + 'ies';
  if (t.endsWith('fe'))                          return cap(t.slice(0, -2)) + 'ves';
  if (t.endsWith('f') && !t.endsWith('ff'))      return cap(t.slice(0, -1)) + 'ves';
  return cap(t) + 's';
}

function cap(s: string): string {
  // Capitalise each word in hyphenated / underscored slugs
  return s.replace(/[-_]/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
}

// ── Type filter searchable dropdown ──────────────────────────

function TypeFilterDropdown({
  types, urls, value, onChange,
}: {
  types:    string[];
  urls:     ScannableUrl[];
  value:    string;
  onChange: (type: string) => void;
}) {
  const [open, setOpen]       = useState(false);
  const [search, setSearch]   = useState('');
  const ref                   = useRef<HTMLDivElement>(null);

  // Close on outside click
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const typeLabel = (t: string) => t === 'all' ? 'All Types' : pluralize(t);

  const filtered = types.filter((t) =>
    t === 'all' || typeLabel(t).toLowerCase().includes(search.toLowerCase()),
  );

  const triggerLabel = typeLabel(value);
  const count = value === 'all' ? urls.length : urls.filter((u) => u.type === value).length;

  return (
    <div className="aai-type-dd-wrap">
      <span className="aai-type-dd-label">Filter by:</span>
      <div className="aai-type-dd" ref={ref}>
        <button
          className="aai-type-dd__trigger"
          onClick={() => setOpen((o) => !o)}
          aria-haspopup="listbox"
          aria-expanded={open}
        >
          <span className="aai-type-dd__label">{triggerLabel}</span>
          <span className="aai-type-dd__count">{count}</span>
          <span className="aai-type-dd__chevron" aria-hidden="true">{open ? '▲' : '▼'}</span>
        </button>

        {open && (
          <div className="aai-type-dd__menu" role="listbox">
            <div className="aai-type-dd__search-wrap">
              <input
                className="aai-type-dd__search"
                type="search"
                placeholder="Search types…"
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                autoFocus
              />
            </div>
            <ul className="aai-type-dd__list">
              {filtered.length === 0 && (
                <li className="aai-type-dd__empty">No types match</li>
              )}
              {filtered.map((type) => {
                const c = type === 'all' ? urls.length : urls.filter((u) => u.type === type).length;
                return (
                  <li
                    key={type}
                    className={`aai-type-dd__option${value === type ? ' aai-type-dd__option--active' : ''}`}
                    role="option"
                    aria-selected={value === type}
                    onClick={() => { onChange(type); setOpen(false); setSearch(''); }}
                  >
                    <span>{typeLabel(type)}</span>
                    <span className="aai-type-dd__opt-count">{c}</span>
                  </li>
                );
              })}
            </ul>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Main component ────────────────────────────────────────────

export default function PageScanner() {
  const [selectedScan, setSelectedScan] = useState<PageScanSummary | null>(null);

  // Filters + pagination
  const [typeFilter, setTypeFilter]   = useState('all');
  const [searchInput, setSearchInput] = useState('');
  const [search, setSearch]           = useState('');
  const [currentPage, setCurrentPage] = useState(0);

  const { data: urls = [], isLoading: urlsLoading } = useQuery({
    queryKey: ['scannable-urls', search],
    queryFn: () => apiFetch<ScannableUrl[]>(search ? `/scannable-urls?search=${encodeURIComponent(search)}` : '/scannable-urls'),
  });

  const { data: pageScans = {} } = useQuery({
    queryKey: ['page-scans'],
    queryFn: () => apiFetch<Record<string, PageScanSummary>>('/page-scans'),
  });

  // Derive unique post types from url list for the filter bar
  const uniqueTypes = useMemo(
    () => ['all', ...Array.from(new Set(urls.map((u) => u.type)))],
    [urls],
  );

  // Filter by type client-side (server already filtered by search)
  const filteredUrls = useMemo(
    () => typeFilter === 'all' ? urls : urls.filter((u) => u.type === typeFilter),
    [urls, typeFilter],
  );

  const totalPages  = Math.max(1, Math.ceil(filteredUrls.length / ITEMS_PER_PAGE));
  const safePage    = Math.min(currentPage, totalPages - 1);
  const pagedUrls   = filteredUrls.slice(safePage * ITEMS_PER_PAGE, (safePage + 1) * ITEMS_PER_PAGE);

  function handleTypeFilter(type: string) {
    setTypeFilter(type);
    setCurrentPage(0);
    setSelectedScan(null);
  }

  function commitSearch() {
    setSearch(searchInput.trim());
    setCurrentPage(0);
  }

  function handleSearchKey(e: React.KeyboardEvent<HTMLInputElement>) {
    if (e.key === 'Enter') commitSearch();
  }

  function clearSearch() {
    setSearchInput('');
    setSearch('');
    setCurrentPage(0);
  }

  function scoreColor(s: number) {
    return s >= 90 ? '#22c55e' : s >= 75 ? '#84cc16' : s >= 55 ? '#f59e0b' : s >= 35 ? '#f97316' : '#ef4444';
  }

  if (urlsLoading) return <PageScannerSkeleton />;

  const scannedCount = Object.keys(pageScans).length;

  return (
    <div className="aai-page-scanner">
      {/* ── Header ── */}
      <div className="aai-page-scanner__header">
        <div>
          <h2 className="aai-pane-title" style={{ margin: 0 }}>Pages &amp; Posts</h2>
          <p className="aai-page-scanner__sub">
            {urls.length} URLs &middot; {scannedCount} scanned &middot;{' '}
            <span style={{ color: '#3858e9', fontWeight: 500 }}>axe-core powered</span>
          </p>
        </div>
      </div>

      {/* ── Search + type filter row ── */}
      <div className="aai-ps-toolbar">
        <div className="aai-ps-search-wrap">
          <svg className="aai-ps-search-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="none" aria-hidden="true"><circle cx="8.5" cy="8.5" r="5.5" stroke="currentColor" strokeWidth="1.6"/><path d="M13 13l3.5 3.5" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
          <input
            className="aai-ps-search"
            type="search"
            placeholder="Search pages & posts… (press Enter)"
            value={searchInput}
            onChange={(e) => setSearchInput(e.target.value)}
            onKeyDown={handleSearchKey}
            aria-label="Search pages and posts"
          />
          {searchInput && (
            <button className="aai-ps-search-clear" onClick={clearSearch} aria-label="Clear search">✕</button>
          )}
        </div>
        <TypeFilterDropdown
          types={uniqueTypes}
          urls={urls}
          value={typeFilter}
          onChange={handleTypeFilter}
        />
      </div>

      {/* ── Results slide-in ── */}
      <ScanSlideIn scan={selectedScan} onClose={() => setSelectedScan(null)} />

      {/* ── Table ── */}
      <div className="aai-ps-layout">
        <div>
          <div className="aai-scan-table-wrap">
            <table className="aai-scan-table">
              <thead>
                <tr>
                  <th>Page / Post</th>
                  <th>Type</th>
                  <th>Score</th>
                  <th>Issues</th>
                  <th>Last Scanned</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {pagedUrls.length === 0 && (
                  <tr><td colSpan={6} style={{ textAlign: 'center', padding: '32px 16px', color: '#9ca3af', fontSize: 13 }}>
                    {search ? `No results for "${search}"` : 'No pages found.'}
                  </td></tr>
                )}
                {pagedUrls.map((item) => {
                  const result = pageScans[item.url];

                  return (
                    <tr key={item.url}>
                      <td>
                        <a
                          href={item.url + (item.url.includes('?') ? '&' : '?') + 'accessmate_scan=1'}
                          target="_blank"
                          rel="noopener noreferrer"
                          className="aai-scan-table__link"
                        >{item.label}</a>
                        <div className="aai-scan-table__url">{item.url}</div>
                      </td>
                      <td><span className="aai-badge">{item.type}</span></td>
                      <td>
                        {result
                          ? <span className="aai-scan-table__score" style={{ color: scoreColor(result.score) }}>
                              <strong>{result.grade}</strong> &middot; {result.score}
                            </span>
                          : <span className="aai-muted">—</span>}
                      </td>
                      <td>
                        {result
                          ? <span style={{ color: result.failed > 0 ? '#ef4444' : '#22c55e', fontWeight: 600 }}>
                              {result.failed}
                            </span>
                          : <span className="aai-muted">—</span>}
                      </td>
                      <td className="aai-muted" style={{ fontSize: 12, whiteSpace: 'nowrap' }}>
                        {result
                          ? new Date(result.scanned_at).toLocaleString(undefined, {
                              month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit',
                            })
                          : '—'}
                      </td>
                      <td style={{ whiteSpace: 'nowrap' }}>
                        {result && (
                          <button
                            className="aai-btn aai-btn--sm aai-btn--ghost"
                            onClick={() => setSelectedScan(result)}
                          >
                            View
                          </button>
                        )}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>

          {/* ── Pagination ── */}
          {totalPages > 1 && (
            <div className="aai-ps-pagination">
              <button
                className="aai-btn aai-btn--sm aai-btn--ghost"
                onClick={() => setCurrentPage((p) => Math.max(0, p - 1))}
                disabled={safePage === 0}
              >
                ← Prev
              </button>

              <span className="aai-ps-page-info">
                Page {safePage + 1} of {totalPages}
              </span>

              <button
                className="aai-btn aai-btn--sm aai-btn--ghost"
                onClick={() => setCurrentPage((p) => Math.min(totalPages - 1, p + 1))}
                disabled={safePage >= totalPages - 1}
              >
                Next →
              </button>
            </div>
          )}

        </div>
      </div>
    </div>
  );
}
