/**
 * Keyword Opportunities Page
 * Shows available SeedKeywords for the active site/sectors
 * Allows users to add keywords to their workflow
 */

import { useState, useEffect, useRef, useMemo, useCallback } from 'react';
import TablePageTemplate from '../../templates/TablePageTemplate';
import {
  fetchSeedKeywords,
  SeedKeyword,
  SeedKeywordResponse,
  addSeedKeywordsToWorkflow,
} from '../../services/api';
import { useSiteStore } from '../../store/siteStore';
import { useSectorStore } from '../../store/sectorStore';
import { usePageSizeStore } from '../../store/pageSizeStore';
import { useToast } from '../../components/ui/toast/ToastContainer';
import { getDifficultyLabelFromNumber, getDifficultyRange, getDifficultyNumber } from '../../utils/difficulty';
import Badge from '../../components/ui/badge/Badge';
import { formatRelativeDate } from '../../utils/date';
import { BoltIcon, PlusIcon } from '../../icons';

export default function KeywordOpportunities() {
  const toast = useToast();
  const { activeSite } = useSiteStore();
  const { activeSector, loadSectorsForSite } = useSectorStore();
  const { pageSize } = usePageSizeStore();

  // Data state
  const [seedKeywords, setSeedKeywords] = useState<(SeedKeyword & { isAdded?: boolean })[]>([]);
  const [loading, setLoading] = useState(true);
  const [showContent, setShowContent] = useState(false);
  const [selectedIds, setSelectedIds] = useState<string[]>([]);
  // Track recently added keywords to preserve their state during reload
  const recentlyAddedRef = useRef<Set<number>>(new Set());
  
  // Pagination state
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(1);
  const [totalCount, setTotalCount] = useState(0);
  
  // Sorting state
  const [sortBy, setSortBy] = useState<string>('keyword');
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');
  
  // Filter state
  const [searchTerm, setSearchTerm] = useState('');
  const [intentFilter, setIntentFilter] = useState('');
  const [difficultyFilter, setDifficultyFilter] = useState('');
  const [volumeMin, setVolumeMin] = useState<number | ''>('');
  const [volumeMax, setVolumeMax] = useState<number | ''>('');

  // Load sectors for active site
  useEffect(() => {
    if (activeSite?.id) {
      loadSectorsForSite(activeSite.id);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [activeSite?.id]); // loadSectorsForSite is stable from Zustand store, no need to include it

  // Load seed keywords
  const loadSeedKeywords = useCallback(async () => {
    if (!activeSite || !activeSite.industry) {
      setSeedKeywords([]);
      setTotalCount(0);
      setTotalPages(1);
      setLoading(false);
      return;
    }

    setLoading(true);
    setShowContent(false);

    try {
      // Get already-attached keywords across ALL sectors for this site
      let attachedSeedKeywordIds = new Set<number>();
      try {
        const { fetchKeywords, fetchSiteSectors } = await import('../../services/api');
        // Get all sectors for the site
        const sectors = await fetchSiteSectors(activeSite.id);
        
        // Check keywords in all sectors
        for (const sector of sectors) {
          try {
            const keywordsData = await fetchKeywords({
              site_id: activeSite.id,
              sector_id: sector.id,
              page_size: 1000, // Get all to check which are attached
            });
            (keywordsData.results || []).forEach((k: any) => {
              // seed_keyword_id is write_only in serializer, so use seed_keyword.id instead
              const seedKeywordId = k.seed_keyword_id || (k.seed_keyword && k.seed_keyword.id);
              if (seedKeywordId) {
                attachedSeedKeywordIds.add(Number(seedKeywordId));
              }
            });
          } catch (err) {
            // If keywords fetch fails for a sector, continue with others
            console.warn(`Could not fetch attached keywords for sector ${sector.id}:`, err);
          }
        }
      } catch (err) {
        // If sectors fetch fails, continue without filtering
        console.warn('Could not fetch sectors or attached keywords:', err);
      }

      // Build filters - fetch ALL results by paginating through all pages
      const baseFilters: any = {
        industry: activeSite.industry,
        page_size: 1000, // Use reasonable page size (API might have max limit)
      };

      // Add sector filter if active sector is selected
      // IMPORTANT: Filter by industry_sector (IndustrySector ID) which is what SeedKeyword.sector references
      if (activeSector && activeSector.industry_sector) {
        baseFilters.sector = activeSector.industry_sector;
      }

      if (searchTerm) baseFilters.search = searchTerm;
      if (intentFilter) baseFilters.intent = intentFilter;

      // Fetch ALL pages to get complete dataset
      let allResults: SeedKeyword[] = [];
      let currentPageNum = 1;
      let hasMore = true;
      
      while (hasMore) {
        const filters = { ...baseFilters, page: currentPageNum };
        const data: SeedKeywordResponse = await fetchSeedKeywords(filters);
        
        if (data.results && data.results.length > 0) {
          allResults = [...allResults, ...data.results];
        }
        
        // Check if there are more pages
        hasMore = data.next !== null && data.next !== undefined;
        currentPageNum++;
        
        // Safety limit to prevent infinite loops
        if (currentPageNum > 100) {
          console.warn('Reached maximum page limit (100) while fetching seed keywords');
          break;
        }
      }
      
      // Mark already-attached keywords instead of filtering them out
      // Also check recentlyAddedRef to preserve state for keywords just added
      let filteredResults = allResults.map(sk => {
        const isAdded = attachedSeedKeywordIds.has(Number(sk.id)) || recentlyAddedRef.current.has(Number(sk.id));
        return {
          ...sk,
          isAdded: Boolean(isAdded) // Explicitly convert to boolean true/false
        };
      });
      
      if (difficultyFilter) {
        const difficultyNum = parseInt(difficultyFilter);
        const label = getDifficultyLabelFromNumber(difficultyNum);
        if (label !== null) {
          const range = getDifficultyRange(label);
          if (range) {
            filteredResults = filteredResults.filter(
              sk => sk.difficulty >= range.min && sk.difficulty <= range.max
            );
          }
        }
      }
      
      if (volumeMin !== '' && volumeMin !== null && volumeMin !== undefined) {
        filteredResults = filteredResults.filter(sk => sk.volume >= Number(volumeMin));
      }
      if (volumeMax !== '' && volumeMax !== null && volumeMax !== undefined) {
        filteredResults = filteredResults.filter(sk => sk.volume <= Number(volumeMax));
      }

      // Apply client-side sorting
      if (sortBy) {
        filteredResults.sort((a, b) => {
          let aVal: any;
          let bVal: any;
          
          if (sortBy === 'keyword') {
            aVal = a.keyword.toLowerCase();
            bVal = b.keyword.toLowerCase();
          } else if (sortBy === 'volume') {
            aVal = a.volume;
            bVal = b.volume;
          } else if (sortBy === 'difficulty') {
            aVal = a.difficulty;
            bVal = b.difficulty;
          } else if (sortBy === 'intent') {
            aVal = a.intent.toLowerCase();
            bVal = b.intent.toLowerCase();
          } else {
            return 0;
          }
          
          if (aVal < bVal) return sortDirection === 'asc' ? -1 : 1;
          if (aVal > bVal) return sortDirection === 'asc' ? 1 : -1;
          return 0;
        });
      }

      // Calculate total count and pages from filtered results
      const totalFiltered = filteredResults.length;
      const pageSizeNum = pageSize || 10;
      
      // Apply client-side pagination
      const startIndex = (currentPage - 1) * pageSizeNum;
      const endIndex = startIndex + pageSizeNum;
      const paginatedResults = filteredResults.slice(startIndex, endIndex);


      setSeedKeywords(paginatedResults);
      setTotalCount(totalFiltered);
      setTotalPages(Math.ceil(totalFiltered / pageSizeNum));
      
      setShowContent(true);
    } catch (error: any) {
      console.error('Error loading seed keywords:', error);
      toast.error(`Failed to load keyword opportunities: ${error.message}`);
      setSeedKeywords([]);
      setTotalCount(0);
      setTotalPages(1);
    } finally {
      setLoading(false);
    }
  }, [activeSite, activeSector, currentPage, pageSize, searchTerm, intentFilter, difficultyFilter, volumeMin, volumeMax, sortBy, sortDirection]);

  // Load data on mount and when filters change (excluding search - handled separately)
  useEffect(() => {
    loadSeedKeywords();
  }, [loadSeedKeywords]);

  // Debounced search - reset to page 1 when search term changes
  useEffect(() => {
    const timer = setTimeout(() => {
      setCurrentPage(1);
    }, 500);

    return () => clearTimeout(timer);
  }, [searchTerm]); // Only depend on searchTerm

  // Handle pageSize changes - reload data when pageSize changes
  // Note: loadSeedKeywords will be recreated when pageSize changes (it's in its dependencies)
  // The effect that depends on loadSeedKeywords will handle the reload
  // We just need to reset to page 1
  useEffect(() => {
    setCurrentPage(1);
  }, [pageSize]); // Only depend on pageSize

  // Handle sorting
  const handleSort = (field: string, direction: 'asc' | 'desc') => {
    setSortBy(field || 'keyword');
    setSortDirection(direction);
    setCurrentPage(1);
  };

  // Handle adding keywords to workflow
  const handleAddToWorkflow = useCallback(async (seedKeywordIds: number[]) => {
    if (!activeSite) {
      toast.error('Please select an active site first');
      return;
    }

    // Get sector to use - use activeSector if available, otherwise get first available sector
    let sectorToUse = activeSector;
    if (!sectorToUse) {
      try {
        const { fetchSiteSectors } = await import('../../services/api');
        const sectors = await fetchSiteSectors(activeSite.id);
        if (sectors.length === 0) {
          toast.error('No sectors available for this site. Please create a sector first.');
          return;
        }
        sectorToUse = {
          id: sectors[0].id,
          name: sectors[0].name,
          slug: sectors[0].slug,
          site_id: activeSite.id,
          is_active: sectors[0].is_active !== false,
          industry_sector: sectors[0].industry_sector || null,
        };
      } catch (error: any) {
        toast.error(`Failed to get sectors: ${error.message}`);
        return;
      }
    }

    try {
      const result = await addSeedKeywordsToWorkflow(
        seedKeywordIds,
        activeSite.id,
        sectorToUse.id
      );

      if (result.success) {
        toast.success(`Successfully added ${result.created} keyword(s) to workflow`);
        
        // Track these as recently added to preserve state during reload
        seedKeywordIds.forEach(id => {
          recentlyAddedRef.current.add(id);
        });
        
        // Clear selection
        setSelectedIds([]);
        
        // Immediately update state to mark keywords as added - this gives instant feedback
        setSeedKeywords(prevKeywords => 
          prevKeywords.map(kw => 
            seedKeywordIds.includes(kw.id) 
              ? { ...kw, isAdded: true }
              : kw
          )
        );
        
        // Don't reload immediately - the state is already updated
        // The recentlyAddedRef will ensure they stay marked as added
        // Only reload if user changes filters/pagination
      } else {
        toast.error(`Failed to add keywords: ${result.errors?.join(', ') || 'Unknown error'}`);
      }
    } catch (error: any) {
      toast.error(`Failed to add keywords: ${error.message}`);
    }
  }, [activeSite, activeSector, toast]);

  // Handle bulk add selected - filter out already added keywords
  const handleBulkAddSelected = useCallback(async (ids: string[]) => {
    if (ids.length === 0) {
      toast.error('Please select at least one keyword');
      return;
    }

    // Filter out already added keywords
    const availableIds = ids.filter(id => {
      const keyword = seedKeywords.find(sk => String(sk.id) === id);
      return keyword && !keyword.isAdded;
    });

    if (availableIds.length === 0) {
      toast.error('All selected keywords are already added to workflow');
      return;
    }

    if (availableIds.length < ids.length) {
      toast.info(`${ids.length - availableIds.length} keyword(s) were already added and were skipped`);
    }

    const seedKeywordIds = availableIds.map(id => parseInt(id));
    await handleAddToWorkflow(seedKeywordIds);
  }, [handleAddToWorkflow, toast, seedKeywords]);

  // Handle add all - fetch all keywords for site/sectors, not just current page
  const handleAddAll = useCallback(async () => {
    if (!activeSite || !activeSite.industry) {
      toast.error('Please select an active site first');
      return;
    }

    try {
      // Fetch ALL seed keywords for the site/sectors (no pagination)
      const filters: any = {
        industry: activeSite.industry,
        page_size: 1000, // Large page size to get all
      };

      if (activeSector?.industry_sector) {
        filters.sector = activeSector.industry_sector;
      }

      const data: SeedKeywordResponse = await fetchSeedKeywords(filters);
      const allSeedKeywords = data.results || [];

      if (allSeedKeywords.length === 0) {
        toast.error('No keywords available to add');
        return;
      }

      // Get already-added keywords to filter them out
      const { fetchKeywords, fetchSiteSectors } = await import('../../services/api');
      const sectors = await fetchSiteSectors(activeSite.id);
      let attachedSeedKeywordIds = new Set<number>();
      
      for (const sector of sectors) {
        try {
          const keywordsData = await fetchKeywords({
            site_id: activeSite.id,
            sector_id: sector.id,
            page_size: 1000,
          });
          (keywordsData.results || []).forEach((k: any) => {
            // seed_keyword_id is write_only in serializer, so use seed_keyword.id instead
            const seedKeywordId = k.seed_keyword_id || (k.seed_keyword && k.seed_keyword.id);
            if (seedKeywordId) {
              attachedSeedKeywordIds.add(Number(seedKeywordId));
            }
          });
        } catch (err) {
          console.warn(`Could not fetch attached keywords for sector ${sector.id}:`, err);
        }
      }

      // Filter out already added keywords
      const availableKeywords = allSeedKeywords.filter(sk => !attachedSeedKeywordIds.has(sk.id));
      
      if (availableKeywords.length === 0) {
        toast.error('All keywords are already added to workflow');
        return;
      }

      if (availableKeywords.length < allSeedKeywords.length) {
        toast.info(`${allSeedKeywords.length - availableKeywords.length} keyword(s) were already added and were skipped`);
      }

      const seedKeywordIds = availableKeywords.map(sk => sk.id);
      await handleAddToWorkflow(seedKeywordIds);
    } catch (error: any) {
      toast.error(`Failed to load all keywords: ${error.message}`);
    }
  }, [activeSite, activeSector, handleAddToWorkflow, toast]);

  // Page config
  const pageConfig = useMemo(() => {
    const showSectorColumn = !activeSector; // Show when viewing all sectors

    return {
      columns: [
        {
          key: 'keyword',
          label: 'Keyword',
          sortable: true,
          sortField: 'keyword',
        },
        ...(showSectorColumn ? [{
          key: 'sector_name',
          label: 'Sector',
          sortable: false,
          render: (_value: string, row: SeedKeyword) => (
            <Badge color="info" size="sm" variant="light">
              {row.sector_name || '-'}
            </Badge>
          ),
        }] : []),
        {
          key: 'volume',
          label: 'Volume',
          sortable: true,
          sortField: 'volume',
          render: (value: number) => value.toLocaleString(),
        },
        {
          key: 'difficulty',
          label: 'Difficulty',
          sortable: true,
          sortField: 'difficulty',
          align: 'center' as const,
          render: (value: number) => {
            const difficultyNum = getDifficultyNumber(value);
            const difficultyBadgeVariant =
              typeof difficultyNum === 'number' && difficultyNum === 5
                ? 'solid'
                : typeof difficultyNum === 'number' &&
                  (difficultyNum === 2 || difficultyNum === 3 || difficultyNum === 4)
                ? 'light'
                : typeof difficultyNum === 'number' && difficultyNum === 1
                ? 'solid'
                : 'light';
            const difficultyBadgeColor =
              typeof difficultyNum === 'number' && difficultyNum === 1
                ? 'success'
                : typeof difficultyNum === 'number' && difficultyNum === 2
                ? 'success'
                : typeof difficultyNum === 'number' && difficultyNum === 3
                ? 'warning'
                : typeof difficultyNum === 'number' && difficultyNum === 4
                ? 'error'
                : typeof difficultyNum === 'number' && difficultyNum === 5
                ? 'error'
                : 'light';
            return typeof difficultyNum === 'number' ? (
              <Badge
                color={difficultyBadgeColor}
                variant={difficultyBadgeVariant}
                size="sm"
              >
                {difficultyNum}
              </Badge>
            ) : (
              difficultyNum
            );
          },
        },
        {
          key: 'intent',
          label: 'Intent',
          sortable: true,
          sortField: 'intent',
          render: (value: string) => {
            const getIntentColor = (intent: string) => {
              const lowerIntent = intent?.toLowerCase() || '';
              if (lowerIntent === 'transactional' || lowerIntent === 'commercial') {
                return 'success';
              } else if (lowerIntent === 'navigational') {
                return 'warning';
              }
              return 'info';
            };

            return (
              <Badge
                color={getIntentColor(value)}
                size="sm"
                variant={value?.toLowerCase() === 'informational' ? 'light' : undefined}
              >
                {value}
              </Badge>
            );
          },
        },
      ],
      filters: [
        {
          key: 'search',
          label: 'Search',
          type: 'text',
          placeholder: 'Search keywords...',
        },
        {
          key: 'intent',
          label: 'Intent',
          type: 'select',
          options: [
            { value: '', label: 'All Intent' },
            { value: 'informational', label: 'Informational' },
            { value: 'navigational', label: 'Navigational' },
            { value: 'transactional', label: 'Transactional' },
            { value: 'commercial', label: 'Commercial' },
          ],
        },
        {
          key: 'difficulty',
          label: 'Difficulty',
          type: 'select',
          options: [
            { value: '', label: 'All Difficulty' },
            { value: '1', label: '1 - Very Easy' },
            { value: '2', label: '2 - Easy' },
            { value: '3', label: '3 - Medium' },
            { value: '4', label: '4 - Hard' },
            { value: '5', label: '5 - Very Hard' },
          ],
        },
      ],
    };
  }, [activeSector]);

  return (
    <>
      <TablePageTemplate
        title="Keyword Opportunities"
        titleIcon={<BoltIcon className="text-brand-500 size-5" />}
        subtitle="Discover and add keywords to your workflow"
        columns={pageConfig.columns}
        data={seedKeywords}
        loading={loading}
        showContent={showContent}
        filters={pageConfig.filters}
        filterValues={{
          search: searchTerm,
          intent: intentFilter,
          difficulty: difficultyFilter,
        }}
        onFilterChange={(key, value) => {
          const stringValue = value === null || value === undefined ? '' : String(value);
          
          if (key === 'search') {
            setSearchTerm(stringValue);
          } else if (key === 'intent') {
            setIntentFilter(stringValue);
            setCurrentPage(1);
          } else if (key === 'difficulty') {
            setDifficultyFilter(stringValue);
            setCurrentPage(1);
          }
        }}
        onRowAction={async (actionKey: string, row: SeedKeyword & { isAdded?: boolean }) => {
          if (actionKey === 'add_to_workflow') {
            // Don't allow adding already-added keywords
            if (row.isAdded) {
              toast.info('This keyword is already added to workflow');
              return;
            }
            await handleAddToWorkflow([row.id]);
          }
        }}
        onBulkAction={async (actionKey: string, ids: string[]) => {
          if (actionKey === 'add_selected_to_workflow') {
            await handleBulkAddSelected(ids);
          }
        }}
        onCreate={handleAddAll}
        createLabel="Add All to Workflow"
        onCreateIcon={<PlusIcon />}
        pagination={{
          currentPage,
          totalPages,
          totalCount,
          onPageChange: setCurrentPage,
        }}
        sorting={{
          sortBy,
          sortDirection,
          onSort: handleSort,
        }}
        selection={{
          selectedIds,
          onSelectionChange: setSelectedIds,
        }}
      />
    </>
  );
}

