/**
 * Blocks listing page with dual view modes:
 * - Pagination: Traditional page-by-page navigation
 * - Infinite scroll: Virtual scrolling with load-more
 *
 * Includes real-time WebSocket updates for new blocks.
 */

import { useState, useEffect, useMemo } from 'react';
import { Box, LayoutList, Rows3, Radio } from 'lucide-react';
import { useBlocks } from '../hooks/useApi';
import { useInfiniteBlocks } from '../hooks/useInfiniteBlocks';
import { useRealtimeBlocks } from '../contexts/WebSocketContext';
import BlockList, { BlockListSkeleton } from '../components/BlockList';
import VirtualBlockList, { VirtualBlockListSkeleton } from '../components/VirtualBlockList';
import Pagination from '../components/Pagination';
import ConnectionStatus from '../components/ConnectionStatus';
import { cn } from '../lib/utils';
import type { ExplorerBlock } from '../lib/types';

type ViewMode = 'paginated' | 'infinite';

const VIEW_MODE_STORAGE_KEY = 'blocksViewMode';

export default function Blocks() {
  // Persist view mode preference
  const [viewMode, setViewMode] = useState<ViewMode>(() => {
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(VIEW_MODE_STORAGE_KEY);
      if (stored === 'paginated' || stored === 'infinite') {
        return stored;
      }
    }
    return 'paginated';
  });

  const [page, setPage] = useState(1);

  // Flash animation state for new blocks
  const [flashBlock, setFlashBlock] = useState<string | null>(null);

  // Paginated data fetching
  const { data: paginatedData, isLoading: isPaginatedLoading, error: paginatedError } = useBlocks(
    page,
    25
  );

  // Infinite scroll data fetching
  const {
    blocks: infiniteBlocks,
    isLoading: isInfiniteLoading,
    isLoadingMore,
    error: infiniteError,
    hasMore,
    loadMore,
    total: infiniteTotal,
    reset: resetInfinite,
  } = useInfiniteBlocks({ pageSize: 50, initialLoad: viewMode === 'infinite' });

  // Real-time WebSocket updates
  const { latestBlock, blockHistory, isConnected } = useRealtimeBlocks(25);

  // Convert real-time block events to ExplorerBlock format
  const convertRealtimeBlock = (b: typeof latestBlock): ExplorerBlock | null => {
    if (!b) return null;
    return {
      hash: b.hash,
      version: 1,
      parentHashes: [],
      timestamp: b.timestamp,
      timestampHuman: new Date(b.timestamp).toISOString(),
      bits: 0,
      nonce: 0,
      daaScore: b.blueScore,
      blueScore: b.blueScore,
      blueWork: '',
      difficulty: 0,
      transactionCount: b.txCount,
      isChainBlock: b.isChainBlock,
      childrenHashes: [],
      mergeSetBlues: [],
      mergeSetReds: [],
    };
  };

  // Merge paginated data with real-time updates (only on page 1)
  const mergedPaginatedBlocks = useMemo<ExplorerBlock[]>(() => {
    const apiBlocks = paginatedData?.data || [];

    // Only merge real-time blocks on page 1
    if (page !== 1 || !blockHistory.length) return apiBlocks;

    // Convert real-time blocks
    const realtimeBlocks: ExplorerBlock[] = blockHistory
      .map(convertRealtimeBlock)
      .filter((b): b is ExplorerBlock => b !== null);

    // Merge: real-time first, then API blocks (avoiding duplicates)
    const seen = new Set(realtimeBlocks.map((b) => b.hash));
    const merged = [...realtimeBlocks];

    for (const block of apiBlocks) {
      if (!seen.has(block.hash)) {
        merged.push(block);
        seen.add(block.hash);
      }
    }

    // Keep same size as original page
    return merged.slice(0, 25);
  }, [paginatedData, blockHistory, page]);

  // Merge infinite scroll data with real-time updates
  const mergedInfiniteBlocks = useMemo<ExplorerBlock[]>(() => {
    if (!blockHistory.length) return infiniteBlocks;

    // Convert real-time blocks
    const realtimeBlocks: ExplorerBlock[] = blockHistory
      .map(convertRealtimeBlock)
      .filter((b): b is ExplorerBlock => b !== null);

    // Merge: real-time first, then existing blocks (avoiding duplicates)
    const seen = new Set(realtimeBlocks.map((b) => b.hash));
    const merged = [...realtimeBlocks];

    for (const block of infiniteBlocks) {
      if (!seen.has(block.hash)) {
        merged.push(block);
        seen.add(block.hash);
      }
    }

    return merged;
  }, [infiniteBlocks, blockHistory]);

  // Save view mode preference
  useEffect(() => {
    localStorage.setItem(VIEW_MODE_STORAGE_KEY, viewMode);
  }, [viewMode]);

  // Flash effect when new block arrives
  useEffect(() => {
    if (latestBlock) {
      setFlashBlock(latestBlock.hash);
      const timer = setTimeout(() => setFlashBlock(null), 1000);
      return () => clearTimeout(timer);
    }
  }, [latestBlock]);

  // Reset infinite scroll when switching to it
  const handleViewModeChange = (mode: ViewMode) => {
    if (mode === 'infinite' && viewMode !== 'infinite') {
      resetInfinite();
    }
    setViewMode(mode);
    setPage(1);
  };

  const error = viewMode === 'paginated' ? paginatedError : infiniteError;
  const totalBlocks = viewMode === 'paginated'
    ? (paginatedData?.total || 0) + blockHistory.length
    : infiniteTotal + blockHistory.length;

  return (
    <div className="space-y-6">
      {/* Header with view toggle */}
      <div className="flex items-center justify-between flex-wrap gap-4">
        <div className="flex items-center gap-3">
          <div className="p-2 rounded-lg bg-synor-900/50">
            <Box size={24} className="text-synor-400" />
          </div>
          <div>
            <h1 className="text-2xl font-bold">Blocks</h1>
            {totalBlocks > 0 && (
              <p className="text-sm text-gray-400">
                {totalBlocks.toLocaleString()} total blocks
              </p>
            )}
          </div>
        </div>

        {/* Connection status and view toggle */}
        <div className="flex items-center gap-3">
          {/* Live indicator */}
          {isConnected && latestBlock && (
            <div className="hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-lg bg-synor-500/10 border border-synor-500/30 text-synor-400 text-xs">
              <Radio size={12} className="animate-pulse" />
              <span>Block #{latestBlock.blueScore.toLocaleString()}</span>
            </div>
          )}

          <ConnectionStatus size="sm" />

          {/* View mode toggle */}
          <div className="flex items-center gap-1 p-1 bg-gray-800 rounded-lg">
            <button
              onClick={() => handleViewModeChange('paginated')}
              className={cn(
                'flex items-center gap-2 px-3 py-1.5 rounded text-sm font-medium transition-colors',
                viewMode === 'paginated'
                  ? 'bg-synor-600 text-white'
                  : 'text-gray-400 hover:text-white hover:bg-gray-700'
              )}
              title="Paginated view"
            >
              <LayoutList size={16} />
              <span className="hidden sm:inline">Pages</span>
            </button>
            <button
              onClick={() => handleViewModeChange('infinite')}
              className={cn(
                'flex items-center gap-2 px-3 py-1.5 rounded text-sm font-medium transition-colors',
                viewMode === 'infinite'
                  ? 'bg-synor-600 text-white'
                  : 'text-gray-400 hover:text-white hover:bg-gray-700'
              )}
              title="Infinite scroll view (virtualized)"
            >
              <Rows3 size={16} />
              <span className="hidden sm:inline">Scroll</span>
            </button>
          </div>
        </div>
      </div>

      {/* Error state */}
      {error && (
        <div className="card p-6 text-red-400">
          Error loading blocks: {error.message}
        </div>
      )}

      {/* Paginated view */}
      {viewMode === 'paginated' && (
        <>
          {isPaginatedLoading && !mergedPaginatedBlocks.length ? (
            <BlockListSkeleton count={25} />
          ) : mergedPaginatedBlocks.length ? (
            <>
              <BlockList
                blocks={mergedPaginatedBlocks}
                showHeader={false}
                highlightHash={flashBlock}
              />
              {paginatedData && paginatedData.totalPages > 1 && (
                <Pagination
                  page={page}
                  totalPages={paginatedData.totalPages}
                  hasNext={paginatedData.hasNext}
                  hasPrev={paginatedData.hasPrev}
                  onPageChange={setPage}
                />
              )}
            </>
          ) : null}
        </>
      )}

      {/* Infinite scroll view */}
      {viewMode === 'infinite' && (
        <>
          {isInfiniteLoading && mergedInfiniteBlocks.length === 0 ? (
            <VirtualBlockListSkeleton />
          ) : (
            <VirtualBlockList
              blocks={mergedInfiniteBlocks}
              hasMore={hasMore}
              isLoadingMore={isLoadingMore}
              onLoadMore={loadMore}
              maxHeight="calc(100vh - 280px)"
              highlightHash={flashBlock}
            />
          )}
        </>
      )}
    </div>
  );
}
