import { useCallback, useState, useMemo } from "react"
import { SelectHeaderTable } from "./components/SelectHeaderTable"
import { useRsi } from "../../hooks/useRsi"
import type { RawData } from "../../types"
import { Button } from "@/components/ui/button"
import { toast } from "sonner"

type SelectHeaderProps = {
  data: RawData[]
  onContinue: (headerValues: RawData, data: RawData[]) => Promise<void>
  onBack?: () => void
}

/**
 * Checks if a row is completely empty (all values are undefined, null, or whitespace-only strings)
 */
const isRowCompletelyEmpty = (row: RawData): boolean => {
  return Object.values(row).every(val =>
    val === undefined ||
    val === null ||
    (typeof val === 'string' && val.trim() === '')
  );
};

export const SelectHeaderStep = ({ data, onContinue, onBack }: SelectHeaderProps) => {
  const { translations } = useRsi()
  const [selectedRows, setSelectedRows] = useState<ReadonlySet<number>>(new Set([0]))
  const [isLoading, setIsLoading] = useState(false)

  // Automatically filter out completely empty rows on initial load
  const initialFilteredData = useMemo(() => {
    return data.filter(row => !isRowCompletelyEmpty(row));
  }, [data]);

  const [localData, setLocalData] = useState<RawData[]>(initialFilteredData)

  const handleContinue = useCallback(async () => {
    const [selectedRowIndex] = selectedRows
    // We consider data above header to be redundant
    const trimmedData = localData.slice(selectedRowIndex + 1)
    setIsLoading(true)
    await onContinue(localData[selectedRowIndex], trimmedData)
    setIsLoading(false)
  }, [onContinue, localData, selectedRows])

  const discardEmptyAndDuplicateRows = useCallback(() => {
    // Helper function to count non-empty values in a row
    const countNonEmptyValues = (values: Record<string, any>): number => {
      return Object.values(values).filter(val => 
        val !== undefined && 
        val !== null && 
        (typeof val === 'string' ? val.trim() !== '' : true)
      ).length;
    };

    // Helper function to normalize row values for case-insensitive comparison
    const normalizeRowForComparison = (row: Record<string, any>): Record<string, any> => {
      return Object.entries(row).reduce((acc, [key, value]) => {
        // Convert string values to lowercase for case-insensitive comparison
        if (typeof value === 'string') {
          acc[key.toLowerCase()] = value.toLowerCase().trim();
        } else {
          acc[key.toLowerCase()] = value;
        }
        return acc;
      }, {} as Record<string, any>);
    };

    // First, analyze all rows to determine if we have rows with multiple values
    const rowsWithValues = localData.map(row => {
      return countNonEmptyValues(row);
    });

    // Check if we have any rows with more than one value
    const hasMultiValueRows = rowsWithValues.some(count => count > 1);

    // Get the selected header row
    const [selectedRowIndex] = selectedRows;
    const selectedHeaderRow = localData[selectedRowIndex];
    
    const normalizedHeaderRow = normalizeRowForComparison(selectedHeaderRow);
    
    const selectedHeaderStr = JSON.stringify(Object.entries(normalizedHeaderRow).sort());

    // Filter out empty rows, rows with single values (if we have multi-value rows),
    // and duplicate rows (including duplicates of the header row)
    const seen = new Set<string>();
    // Add the selected header row to the seen set first
    seen.add(selectedHeaderStr);

    // Debug: Track which rows are being removed and why
    const removedRows: { index: number; reason: string; row: any }[] = [];

    const filteredRows = localData.filter((row, index) => {
      // Always keep the selected header row
      if (index === selectedRowIndex) {
        return true;
      }

      // Check if it's empty or has only one value
      const nonEmptyCount = rowsWithValues[index];
      if (nonEmptyCount === 0 || (hasMultiValueRows && nonEmptyCount <= 1)) {
        removedRows.push({ index, reason: "Empty or single value", row });
        return false;
      }

      // Check if it's a duplicate (case-insensitive)
      const normalizedRow = normalizeRowForComparison(row);
      
      const rowStr = JSON.stringify(Object.entries(normalizedRow).sort());
      
      if (seen.has(rowStr)) {
        removedRows.push({ 
          index, 
          reason: "Duplicate", 
          row
        });
        return false;
      }
      
      seen.add(rowStr);
      return true;
    });

    // Only update if we actually removed any rows
    if (filteredRows.length < localData.length) {
      // Adjust the selected row index if needed
      const newSelectedIndex = filteredRows.findIndex(row => 
        JSON.stringify(Object.entries(normalizeRowForComparison(row)).sort()) === selectedHeaderStr
      );
      
      setLocalData(filteredRows);
      setSelectedRows(new Set([newSelectedIndex]));
      
      toast.success("Rows removed", {
        description: `Removed ${localData.length - filteredRows.length} empty, single-value, or duplicate rows`,
      });
    } else {
      toast.info("No rows removed", {
        description: "No empty, single-value, or duplicate rows were found",
      });
    }
  }, [localData, selectedRows]);

  return (
    <div className="flex flex-col h-[calc(100vh-9.5rem)]">
      <div className="px-8 py-6 bg-background flex justify-between items-end">
        <div>
          <h2 className="text-2xl font-semibold text-foreground">
            {translations.selectHeaderStep.title}
          </h2>
          <p className="mt-1 text-sm text-muted-foreground">
            Select the row that contains your column headers
          </p>
        </div>
        <Button
          variant="secondary"
          size="sm"
          onClick={discardEmptyAndDuplicateRows}
        >
          Remove Empty/Duplicates
        </Button>
      </div>
      <div className="flex-1 flex flex-col min-h-0">
        <div className="px-8 flex-1 overflow-auto">
          <SelectHeaderTable 
            data={localData} 
            selectedRows={selectedRows} 
            setSelectedRows={setSelectedRows} 
          />
        </div>
      </div>
      <div className="flex items-center justify-between border-t bg-muted px-8 py-4 mt-2">
        {onBack && (
          <Button variant="outline" onClick={onBack}>
            {translations.selectHeaderStep.backButtonTitle}
          </Button>
        )}
        <Button 
          className="ml-auto"
          disabled={isLoading}
          onClick={handleContinue}
        >
          {translations.selectHeaderStep.nextButtonTitle}
        </Button>
      </div>
    </div>
  )
}
