/**
 * Product Hunt top posts with vote counts — INTERCEPT strategy.
 *
 * Navigates to the Product Hunt homepage and scrapes rendered product cards.
 */
import { cli, Strategy } from '@jackwener/opencli/registry';
import { CliError } from '@jackwener/opencli/errors';
import { pickVoteCount } from './utils.js';
cli({
    site: 'producthunt',
    name: 'hot',
    access: 'read',
    description: "Today's top Product Hunt launches with vote counts",
    domain: 'www.producthunt.com',
    strategy: Strategy.INTERCEPT,
    args: [
        { name: 'limit', type: 'int', default: 20, help: 'Number of results (max 50)' },
    ],
    columns: ['rank', 'name', 'votes', 'url'],
    func: async (page, args) => {
        const count = Math.min(Number(args.limit) || 20, 50);
        await page.installInterceptor('producthunt.com');
        await page.goto('https://www.producthunt.com');
        await page.waitForCapture(5);
        const domItems = await page.evaluate(`
      (() => {
        const seen = new Set();
        const results = [];

        const cardLinks = Array.from(document.querySelectorAll('a[href^="/products/"]')).filter((el) => {
          const href = el.getAttribute('href') || '';
          const text = el.textContent?.trim() || '';
          return href && !href.includes('/reviews') && text.length > 0 && text.length < 120;
        });

        const normalizeName = (text) => text
          .replace(/^\\d+\\.\\s*/, '')
          .replace(/\\s*Launched\\s+this\\s+(month|week|year|day)\\s*/gi, '')
          .replace(/\\s*Featured\\s*/gi, '')
          .trim();

        for (const cardLink of cardLinks) {
          const href = cardLink.getAttribute('href') || '';
          if (!href || seen.has(href)) continue;

          let card = cardLink;
          let node = cardLink.parentElement;
          for (let i = 0; i < 6 && node; i++) {
            const hasReviewLink = !!node.querySelector('a[href="' + href + '/reviews"]');
            const hasNumericNode = Array.from(node.querySelectorAll('button, [role="button"], p, span, div'))
              .some((el) => /^\\d+$/.test(el.textContent?.trim() || ''));
            if (hasReviewLink || hasNumericNode) {
              card = node;
              break;
            }
            node = node.parentElement;
          }

          const name = normalizeName(cardLink.textContent?.trim() || '');
          if (!name) continue;

          const voteCandidates = Array.from(card.querySelectorAll('button, [role="button"], a, p, span, div'))
            .map((el) => {
              const reviewLink = el.closest('a[href="' + href + '/reviews"]');
              return {
                text: el.textContent?.trim() || '',
                tagName: el.tagName,
                className: el.className || '',
                role: el.getAttribute('role') || '',
                inButton: !!el.closest('button, [role="button"]'),
                inReviewLink: !!reviewLink,
              };
            })
            .filter((candidate) => /^\\d+$/.test(candidate.text));

          if (voteCandidates.length === 0) continue;

          seen.add(href);
          results.push({
            name,
            voteCandidates,
            url: 'https://www.producthunt.com' + href,
          });
        }

        return results;
      })()
    `);
        const items = Array.isArray(domItems) ? domItems : [];
        if (items.length === 0) {
            throw new CliError('NO_DATA', 'Could not retrieve Product Hunt top posts', 'Product Hunt may have changed its layout');
        }
        const rankedItems = items
            .map((item) => ({
            name: item.name,
            url: item.url,
            votes: pickVoteCount(Array.isArray(item.voteCandidates) ? item.voteCandidates : []),
        }))
            .filter((item) => item.name && item.url && item.votes);
        if (rankedItems.length === 0) {
            throw new CliError('NO_DATA', 'Could not retrieve Product Hunt vote counts', 'Product Hunt may have changed its vote button structure');
        }
        rankedItems.sort((a, b) => parseInt(b.votes, 10) - parseInt(a.votes, 10));
        return rankedItems.slice(0, count).map((item, i) => ({
            rank: i + 1,
            name: item.name,
            votes: item.votes,
            url: item.url,
        }));
    },
});
