/**
 * YouTube history — watch history via InnerTube browse API (FEhistory).
 */
import { cli, Strategy } from '@jackwener/opencli/registry';
import { CommandExecutionError, EmptyResultError } from '@jackwener/opencli/errors';

cli({
    site: 'youtube',
    name: 'history',
    access: 'read',
    description: 'Get YouTube watch history',
    domain: 'www.youtube.com',
    strategy: Strategy.COOKIE,
    args: [
        { name: 'limit', type: 'int', default: 30, help: 'Max videos to return (default 30, max 200)' },
    ],
    columns: ['rank', 'title', 'channel', 'views', 'duration', 'url'],
    func: async (page, kwargs) => {
        const limit = Math.min(kwargs.limit || 30, 200);
        await page.goto('https://www.youtube.com/feed/history');
        await page.wait(3);
        await page.autoScroll({ times: Math.min(Math.max(Math.ceil(limit / 20), 1), 8), delayMs: 1200 });
        const data = await page.evaluate(`
      (async () => {
        const limit = ${limit};

        const videos = [];
        const seen = new Set();
        const root = document.querySelector('ytd-two-column-browse-results-renderer #primary ytd-section-list-renderer');
        if (!root) return { error: 'YouTube history list not found' };

        function text(el) {
          return (el?.textContent || '').replace(/\\s+/g, ' ').trim();
        }

        function push(entry) {
          if (!entry?.url || seen.has(entry.url) || videos.length >= limit) return;
          seen.add(entry.url);
          videos.push({ rank: videos.length + 1, ...entry });
        }

        for (const section of root.querySelectorAll('ytd-item-section-renderer')) {
          if (videos.length >= limit) break;

          for (const renderer of section.querySelectorAll('yt-lockup-view-model, ytd-video-renderer, ytd-rich-item-renderer, ytd-grid-video-renderer, ytd-compact-video-renderer')) {
            if (videos.length >= limit) break;
            const link = renderer.querySelector('a[href^="/watch?v="]');
            const href = link?.getAttribute('href') || '';
            if (!href) continue;
            const title =
              link?.getAttribute('title')
              || text(renderer.querySelector('#video-title'))
              || text(renderer.querySelector('h3 a'))
              || text(renderer.querySelector('h3'))
              || text(link);
            const channel =
              text(renderer.querySelector('#channel-name a'))
              || text(renderer.querySelector('[aria-label^="前往频道："]'))
              || text(renderer.querySelector('[aria-label^="Go to channel:"]'))
              || text(renderer.querySelector('ytd-channel-name'))
              || text(renderer.querySelector('#metadata #byline-container'))
              || '';
            const metadata = Array.from(renderer.querySelectorAll('#metadata-line span, #metadata span, .metadata span'))
              .map(node => text(node))
              .filter(Boolean);
            const lockupMetadata = Array.from(renderer.querySelectorAll('yt-content-metadata-view-model span, yt-lockup-metadata-view-model span'))
              .map(node => text(node))
              .filter(Boolean);
            const combinedMetadata = (metadata.length ? metadata : lockupMetadata)
              .filter(value => value && value !== title && value !== '•');
            const inferredChannel = channel || combinedMetadata.find(value => !/观看|views|前|前に|ago|次观看|次查看|stream/i.test(value)) || '';
            const inferredViews = combinedMetadata.find(value => /观看|views/i.test(value)) || '';
            const inferredPublished = combinedMetadata.find(value => value !== inferredChannel && value !== inferredViews) || '';
            const duration =
              text(renderer.querySelector('ytd-thumbnail-overlay-time-status-renderer'))
              || text(renderer.querySelector('yt-thumbnail-badge-view-model'))
              || text(renderer.querySelector('badge-shape'))
              || '';
            push({
              title,
              channel: inferredChannel,
              views: inferredViews,
              duration,
              published: inferredPublished,
              url: href.startsWith('http') ? href : 'https://www.youtube.com' + href,
            });
          }

          for (const shortLink of section.querySelectorAll('a[href^="/shorts/"]')) {
            if (videos.length >= limit) break;
            const card = shortLink.closest('ytm-shorts-lockup-view-model-v2, ytm-shorts-lockup-view-model, ytd-reel-item-renderer') || shortLink.parentElement;
            const href = shortLink.getAttribute('href') || '';
            if (!href) continue;
            const title = shortLink.getAttribute('title') || text(card?.querySelector('h3')) || text(shortLink);
            const stats = Array.from(card?.querySelectorAll('span') || []).map(node => text(node)).filter(Boolean);
            push({
              title,
              channel: 'Shorts',
              views: stats.find(value => /观看|views/i.test(value)) || '',
              duration: 'SHORT',
              published: '',
              url: href.startsWith('http') ? href : 'https://www.youtube.com' + href,
            });
          }
        }

        return videos.length ? videos : { error: 'No watch history items found on youtube.com/feed/history' };
      })()
    `);
        if (!Array.isArray(data)) {
            const errMsg = data && typeof data === 'object' ? String(data.error || '') : '';
            throw new CommandExecutionError(errMsg || 'Failed to fetch watch history — make sure you are logged into YouTube');
        }
        if (data.length === 0) {
            throw new EmptyResultError('youtube history');
        }
        return data;
    },
});
