import React, { useState, useMemo, useRef, useEffect } from 'react';
import { useLanguage } from '../../contexts/LanguageContext';
import styles from './FormGenerator.module.css';

// Types for the FormGenerator
export interface ColumnConfig {
  key: string;
  label: string;
  type?: 'string' | 'number' | 'date' | 'boolean' | 'enum';
  width?: number;
  minWidth?: number;
  maxWidth?: number;
  sortable?: boolean;
  filterable?: boolean;
  searchable?: boolean;
  formatter?: (value: any, row: any) => React.ReactNode;
  filterOptions?: string[]; // For enum/select filters
}

export interface FormGeneratorProps<T = any> {
  data: T[];
  columns?: ColumnConfig[];
  title?: string;
  searchable?: boolean;
  filterable?: boolean;
  sortable?: boolean;
  resizable?: boolean;
  pagination?: boolean;
  pageSize?: number;
  pageSizeOptions?: number[];
  showPageSizeSelector?: boolean;
  onRowClick?: (row: T, index: number) => void;
  onRowSelect?: (selectedRows: T[]) => void;
  selectable?: boolean;
  loading?: boolean;
  actions?: {
    label: string;
    onClick: (row: T) => void;
    icon?: string | React.ReactNode | ((row: T) => React.ReactNode);
  }[];
  onDelete?: (row: T) => void;
  onDeleteMultiple?: (rows: T[]) => void;
  className?: string;
}

export function FormGenerator<T extends Record<string, any>>({
  data,
  columns: providedColumns,
  searchable = true,
  filterable = true,
  sortable = true,
  resizable = true,
  pagination = true,
  pageSize = 10,
  pageSizeOptions = [10, 25, 50, 100],
  showPageSizeSelector = true,
  onRowClick,
  onRowSelect,
  selectable = true, // Default to true for selection functionality
  loading = false,
  actions = [],
  onDelete,
  onDeleteMultiple,
  className = ''
}: FormGeneratorProps<T>) {
  const { t } = useLanguage();
  // Auto-detect columns if not provided
  const detectedColumns = useMemo((): ColumnConfig[] => {
    if (providedColumns) return providedColumns;
    
    if (data.length === 0) return [];
    
    const sampleRow = data[0];
    return Object.keys(sampleRow).map(key => {
      const value = sampleRow[key];
      let type: ColumnConfig['type'] = 'string';
      
      // Auto-detect type based on value
      if (typeof value === 'number') {
        type = 'number';
      } else if (typeof value === 'boolean') {
        type = 'boolean';
      } else if (value instanceof Date || (typeof value === 'string' && !isNaN(Date.parse(value)) && value.includes('-'))) {
        type = 'date';
      }
      
      return {
        key,
        label: key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, ' $1'),
        type,
        sortable: true,
        filterable: true,
        searchable: type === 'string',
        width: 150,
        minWidth: 100,
        maxWidth: 400
      };
    });
  }, [data, providedColumns]);

  // State management
  const [searchTerm, setSearchTerm] = useState('');
  const [searchFocused, setSearchFocused] = useState(false);
  const [filterFocused, setFilterFocused] = useState<Record<string, boolean>>({});
  const [sortConfig, setSortConfig] = useState<{ key: string; direction: 'asc' | 'desc' } | null>(null);
  const [filters, setFilters] = useState<Record<string, any>>({});
  const [columnWidths, setColumnWidths] = useState<Record<string, number>>({});
  const [selectedRows, setSelectedRows] = useState<Set<number>>(new Set());
  const [currentPage, setCurrentPage] = useState(1);
  const [currentPageSize, setCurrentPageSize] = useState(pageSize);
  
  // Refs for resizing
  const tableRef = useRef<HTMLTableElement>(null);
  const resizingColumn = useRef<string | null>(null);
  const startX = useRef<number>(0);
  const startWidth = useRef<number>(0);

  // Initialize column widths
  useEffect(() => {
    const initialWidths: Record<string, number> = {};
    
    detectedColumns.forEach(col => {
      // Set a default width if none specified to ensure all columns have explicit widths
      initialWidths[col.key] = col.width || 150;
    });
    setColumnWidths(initialWidths);
  }, [detectedColumns]);

  // Filter and search data
  const filteredData = useMemo(() => {
    let result = [...data];

    // Apply search filter
    if (searchTerm && searchable) {
      const searchLower = searchTerm.toLowerCase();
      result = result.filter(row => {
        return detectedColumns.some(col => {
          if (!col.searchable) return false;
          const value = row[col.key];
          return String(value).toLowerCase().includes(searchLower);
        });
      });
    }

    // Apply column filters
    Object.entries(filters).forEach(([key, filterValue]) => {
      if (filterValue !== undefined && filterValue !== '') {
        result = result.filter(row => {
          const value = row[key];
          const column = detectedColumns.find(col => col.key === key);
          
          if (column?.type === 'boolean') {
            return Boolean(value) === Boolean(filterValue);
          } else if (column?.type === 'number') {
            return Number(value) === Number(filterValue);
          } else if (column?.type === 'date') {
            // Convert row value to DD.MM.YYYY format for comparison
            const rowDate = new Date(value);
            const rowFormatted = `${rowDate.getDate().toString().padStart(2, '0')}.${(rowDate.getMonth() + 1).toString().padStart(2, '0')}.${rowDate.getFullYear()}`;
            
            // Check if filter value is complete (DD.MM.YYYY)
            if (filterValue.length === 10 && filterValue.match(/^\d{2}\.\d{2}\.\d{4}$/)) {
              return rowFormatted === filterValue;
            } else {
              // Partial matching for incomplete dates
              return rowFormatted.startsWith(filterValue);
            }
          } else {
            return String(value).toLowerCase().includes(String(filterValue).toLowerCase());
          }
        });
      }
    });

    // Apply sorting
    if (sortConfig) {
      result.sort((a, b) => {
        const aVal = a[sortConfig.key];
        const bVal = b[sortConfig.key];
        
        if (aVal < bVal) return sortConfig.direction === 'asc' ? -1 : 1;
        if (aVal > bVal) return sortConfig.direction === 'asc' ? 1 : -1;
        return 0;
      });
    }

    return result;
  }, [data, searchTerm, filters, sortConfig, detectedColumns, searchable]);

  // Pagination
  const paginatedData = useMemo(() => {
    if (!pagination) return filteredData;
    
    const startIndex = (currentPage - 1) * currentPageSize;
    return filteredData.slice(startIndex, startIndex + currentPageSize);
  }, [filteredData, currentPage, currentPageSize, pagination]);

  const totalPages = Math.ceil(filteredData.length / currentPageSize);

  // Handle sorting
  const handleSort = (key: string) => {
    if (!sortable) return;
    
    setSortConfig(current => {
      if (current?.key === key) {
        return current.direction === 'asc' 
          ? { key, direction: 'desc' }
          : null;
      }
      return { key, direction: 'asc' };
    });
  };

  // Handle filtering
  const handleFilter = (key: string, value: any) => {
    setFilters(prev => ({
      ...prev,
      [key]: value
    }));
    setCurrentPage(1); // Reset to first page when filtering
  };

  // Handle filter input focus
  const handleFilterFocus = (key: string, focused: boolean) => {
    setFilterFocused(prev => ({
      ...prev,
      [key]: focused
    }));
  };

  // Handle row selection
  const handleRowSelect = (index: number) => {
    if (!selectable) return;
    
    const newSelected = new Set(selectedRows);
    if (newSelected.has(index)) {
      newSelected.delete(index);
    } else {
      newSelected.add(index);
    }
    setSelectedRows(newSelected);
    
    if (onRowSelect) {
      const selectedData = Array.from(newSelected).map(i => paginatedData[i]);
      onRowSelect(selectedData);
    }
  };

  // Handle select all
  const handleSelectAll = () => {
    if (!selectable) return;
    
    if (selectedRows.size === paginatedData.length) {
      setSelectedRows(new Set());
      onRowSelect?.([]);
    } else {
      const allIndices = new Set(paginatedData.map((_, index) => index));
      setSelectedRows(allIndices);
      onRowSelect?.(paginatedData);
    }
  };

  // Handle delete single item
  const handleDeleteSingle = (row: T, index: number) => {
    if (onDelete) {
      onDelete(row);
      // Remove from selection if it was selected
      if (selectedRows.has(index)) {
        const newSelected = new Set(selectedRows);
        newSelected.delete(index);
        setSelectedRows(newSelected);
        if (onRowSelect) {
          const selectedData = Array.from(newSelected).map(i => paginatedData[i]);
          onRowSelect(selectedData);
        }
      }
    }
  };

  // Handle delete multiple items
  const handleDeleteMultiple = () => {
    if (onDeleteMultiple && selectedRows.size > 0) {
      const selectedData = Array.from(selectedRows).map(i => paginatedData[i]);
      onDeleteMultiple(selectedData);
      // Clear selection
      setSelectedRows(new Set());
      onRowSelect?.([]);
    }
  };

  // Handle page size change
  const handlePageSizeChange = (newPageSize: number) => {
    setCurrentPageSize(newPageSize);
    setCurrentPage(1); // Reset to first page when page size changes
  };

  // Handle column resizing
  const handleMouseDown = (e: React.MouseEvent, columnKey: string) => {
    if (!resizable) return;
    
    e.preventDefault();
    resizingColumn.current = columnKey;
    startX.current = e.clientX;
    startWidth.current = columnWidths[columnKey] || 150;
    
    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  };

  const handleMouseMove = (e: MouseEvent) => {
    if (!resizingColumn.current) return;
    
    const diff = e.clientX - startX.current;
    let newWidth = Math.max(100, startWidth.current + diff);
    
    // Prevent extending beyond table container
    const tableContainer = tableRef.current?.parentElement;
    if (tableContainer) {
      const containerWidth = tableContainer.clientWidth;
      const actionsColumnWidth = actions.length > 0 ? 120 : 0; // Fixed width actions column
      const selectColumnWidth = selectable ? 50 : 0; // Fixed width select column
      const fixedWidth = actionsColumnWidth + selectColumnWidth;
      
      // Calculate total width of all OTHER data columns (excluding the one being resized)
      const otherDataColumnsWidth = detectedColumns.reduce((total, col) => {
        if (col.key !== resizingColumn.current) {
          return total + (columnWidths[col.key] || col.width || 150);
        }
        return total;
      }, 0);
      
      // Maximum allowed width for this column
      const maxAllowedWidth = containerWidth - fixedWidth - otherDataColumnsWidth - 40; // 40px buffer
      newWidth = Math.min(newWidth, Math.max(100, maxAllowedWidth));
    }
    
    setColumnWidths(prev => ({
      ...prev,
      [resizingColumn.current!]: newWidth
    }));
  };

  const handleMouseUp = () => {
    resizingColumn.current = null;
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
  };

  // Format cell value
  const formatCellValue = (value: any, column: ColumnConfig, row: T) => {
    if (column.formatter) {
      return column.formatter(value, row);
    }
    
    if (value === null || value === undefined) {
      return '-';
    }
    
    switch (column.type) {
      case 'date':
        return new Date(value).toLocaleDateString();
      case 'boolean':
        return value ? '✓' : '✗';
      case 'number':
        return typeof value === 'number' ? value.toLocaleString() : value;
      default:
        return String(value);
    }
  };

  return (
    <div className={`${styles.formGenerator} ${className}`}>
      
      {(searchable || filterable || (selectable && selectedRows.size > 0)) && (
        <div className={styles.controls}>
          {/* Delete Controls - Show when items are selected */}
          {selectable && selectedRows.size > 0 && (
            <div className={styles.deleteControlsIntegrated}>
              {selectedRows.size === 1 && onDelete && (
                <button
                  onClick={() => {
                    const selectedIndex = Array.from(selectedRows)[0];
                    const selectedRow = paginatedData[selectedIndex];
                    handleDeleteSingle(selectedRow, selectedIndex);
                  }}
                  className={styles.deleteButton}
                  title={t('formgen.delete.single', 'Delete selected item')}
                >
                  <span className={styles.deleteIcon}>✕</span>
                  {t('formgen.delete.single', 'Delete')}
                </button>
              )}
              {selectedRows.size > 1 && onDeleteMultiple && (
                <button
                  onClick={handleDeleteMultiple}
                  className={styles.deleteAllButton}
                  title={t('formgen.delete.multiple', `Delete ${selectedRows.size} selected items`)}
                >
                  <span className={styles.deleteIcon}>✕</span>
                  {t('formgen.delete.multiple', `Delete All (${selectedRows.size})`)}
                </button>
              )}

            </div>
          )}

          {/* Search Controls - Hide when items are selected */}
          {searchable && selectedRows.size === 0 && (
            <div className={styles.searchContainer}>
              <div className={styles.floatingLabelInput}>
                <input
                  type="text"
                  placeholder=" "
                  value={searchTerm}
                  onChange={(e) => setSearchTerm(e.target.value)}
                  onFocus={() => setSearchFocused(true)}
                  onBlur={() => setSearchFocused(false)}
                  className={`${styles.searchInput} ${searchFocused || searchTerm ? styles.focused : ''}`}
                />
                <label className={searchFocused || searchTerm ? styles.focusedLabel : styles.label}>{t('formgen.search.placeholder')}</label>
              </div>
            </div>
          )}
          
          {filterable && (
            <div className={styles.filtersContainer}>
              {detectedColumns.filter(col => col.filterable).map(column => (
                <div key={column.key} className={styles.filterGroup}>
                  {column.type === 'boolean' ? (
                    <div className={styles.customSelectContainer}>
                      <select
                        value={filters[column.key] || ''}
                        onChange={(e) => handleFilter(column.key, e.target.value === '' ? undefined : e.target.value === 'true')}
                        className={`${styles.filterSelect} ${filters[column.key] ? styles.hasValue : ''}`}
                      >
                        <option value="" disabled hidden>{column.label}</option>
                        <option value="true">{t('formgen.filter.yes')}</option>
                        <option value="false">{t('formgen.filter.no')}</option>
                      </select>
                      {filters[column.key] && (
                        <button
                          type="button"
                          onClick={() => handleFilter(column.key, '')}
                          className={styles.clearFilterButton}
                          title={t('formgen.filter.clear')}
                        >
                          ✕
                        </button>
                      )}
                    </div>
                  ) : column.filterOptions ? (
                    <div className={styles.customSelectContainer}>
                      <select
                        value={filters[column.key] || ''}
                        onChange={(e) => handleFilter(column.key, e.target.value)}
                        className={`${styles.filterSelect} ${filters[column.key] ? styles.hasValue : ''}`}
                      >
                        <option value="" disabled hidden>{column.label}</option>

                        {column.filterOptions.map(option => (
                          <option key={option} value={option}>{option}</option>
                        ))}
                      </select>
                      {filters[column.key] && (
                        <button
                          type="button"
                          onClick={() => handleFilter(column.key, '')}
                          className={styles.clearFilterButton}
                          title={t('formgen.filter.clear')}
                        >
                          ✕
                        </button>
                      )}
                    </div>
                  ) : column.type === 'date' ? (
                    <div className={styles.floatingLabelInput}>
                      <input
                        type="text"
                        placeholder=" "
                        value={filters[column.key] || ''}
                        onChange={(e) => {
                          let value = e.target.value;
                          const currentValue = filters[column.key] || '';
                          
                          // Check if user is deleting (new value is shorter)
                          const isDeleting = value.length < currentValue.length;
                          
                          if (isDeleting) {
                            // When deleting, preserve the exact input without auto-formatting
                            handleFilter(column.key, value);
                            return;
                          }
                          
                          // Auto-pad single digits followed by dot (e.g., "4." -> "04.")
                          value = value.replace(/^(\d)\./, '0$1.');
                          value = value.replace(/\.(\d)\./, '.0$1.');
                          
                          // Allow typing and format as DD.MM.YYYY
                          const digitsOnly = value.replace(/\D/g, ''); // Remove non-digits
                          
                          let formatted = '';
                          if (digitsOnly.length >= 8) {
                            // Full format: DDMMYYYY -> DD.MM.YYYY
                            const day = digitsOnly.slice(0, 2);
                            const month = digitsOnly.slice(2, 4);
                            const year = digitsOnly.slice(4, 8);
                            
                            // Validate day (01-31) and month (01-12)
                            if (parseInt(day) > 31 || parseInt(month) > 12 || parseInt(day) === 0 || parseInt(month) === 0) {
                              return; // Don't update if invalid
                            }
                            formatted = `${day}.${month}.${year}`;
                          } else if (digitsOnly.length >= 4) {
                            // Partial format: DDMM -> DD.MM.
                            const day = digitsOnly.slice(0, 2);
                            const month = digitsOnly.slice(2, 4);
                            const remaining = digitsOnly.slice(4);
                            
                            // Validate day (01-31) and month (01-12)
                            if (parseInt(day) > 31 || parseInt(month) > 12 || parseInt(day) === 0 || parseInt(month) === 0) {
                              return; // Don't update if invalid
                            }
                            formatted = `${day}.${month}.${remaining}`;
                          } else if (digitsOnly.length >= 2) {
                            // Start format: DD -> DD.
                            const day = digitsOnly.slice(0, 2);
                            const remaining = digitsOnly.slice(2);
                            
                            // Validate day (01-31)
                            if (parseInt(day) > 31 || parseInt(day) === 0) {
                              return; // Don't update if invalid
                            }
                            formatted = `${day}.${remaining}`;
                          } else {
                            // Just digits
                            formatted = digitsOnly;
                          }
                          
                          handleFilter(column.key, formatted);
                        }}
                        onFocus={() => handleFilterFocus(column.key, true)}
                        onBlur={() => handleFilterFocus(column.key, false)}
                        className={`${styles.filterInput} ${filterFocused[column.key] || filters[column.key] ? styles.focused : ''}`}
                        maxLength={10}
                      />
                      <label className={filterFocused[column.key] || filters[column.key] ? styles.focusedLabel : styles.label}>
                        {column.label}
                      </label>
                    </div>
                  ) : (
                    <div className={styles.floatingLabelInput}>
                      <input
                        type="text"
                        placeholder=" "
                        value={filters[column.key] || ''}
                        onChange={(e) => handleFilter(column.key, e.target.value)}
                        onFocus={() => handleFilterFocus(column.key, true)}
                        onBlur={() => handleFilterFocus(column.key, false)}
                        className={`${styles.filterInput} ${filterFocused[column.key] || filters[column.key] ? styles.focused : ''}`}
                      />
                      <label className={filterFocused[column.key] || filters[column.key] ? styles.focusedLabel : styles.label}>
                        {t('formgen.filter.placeholder').replace('{column}', column.label)}
                      </label>
                    </div>
                  )}
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {/* Table */}
      <div className={styles.tableContainer}>
        {loading ? (
          <div className={styles.loadingState}>
            <div className={styles.loadingSpinner}></div>
            <p>{t('common.loading', 'Loading...')}</p>
          </div>
        ) : (
          <table ref={tableRef} className={styles.table}>
            <thead>
              <tr>
                {selectable && (
                  <th className={styles.selectColumn} style={{ width: '50px', minWidth: '50px', maxWidth: '50px' }}>
                    <input
                      type="checkbox"
                      checked={selectedRows.size === paginatedData.length && paginatedData.length > 0}
                      onChange={handleSelectAll}
                      title="Select all items"
                    />
                  </th>
                )}
                {actions.length > 0 && (
                  <th 
                    className={styles.actionsColumn}
                    style={{ width: '120px', minWidth: '120px', maxWidth: '120px' }}
                  >
                     
                  </th>
                )}
                {detectedColumns.map(column => (
                  <th
                    key={column.key}
                    className={`${styles.th} ${sortable && column.sortable ? styles.sortable : ''}`}
                    style={{ 
                      width: columnWidths[column.key] || column.width || 150,
                      minWidth: columnWidths[column.key] || column.width || 150,
                      maxWidth: columnWidths[column.key] || column.width || 150
                    }}
                    onClick={() => column.sortable && handleSort(column.key)}
                  >
                    <div className={styles.headerContent}>
                      <span>{column.label}</span>
                      {sortable && column.sortable && (
                        <span className={styles.sortIcon}>
                          {sortConfig?.key === column.key ? (
                            sortConfig.direction === 'asc' ? '↑' : '↓'
                          ) : '↕'}
                        </span>
                      )}
                    </div>
                    {resizable && (
                      <div
                        className={styles.resizeHandle}
                        onMouseDown={(e) => handleMouseDown(e, column.key)}
                      />
                    )}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {paginatedData.map((row, index) => (
                <tr
                  key={index}
                  className={`${styles.tr} ${selectedRows.has(index) ? styles.selected : ''} ${onRowClick ? styles.clickable : ''}`}
                  onClick={() => onRowClick?.(row, index)}
                >
                  {selectable && (
                    <td className={styles.selectColumn} style={{ width: '50px', minWidth: '50px', maxWidth: '50px' }}>
                      <input
                        type="checkbox"
                        checked={selectedRows.has(index)}
                        onChange={() => handleRowSelect(index)}
                        onClick={(e) => e.stopPropagation()}
                        title="Select this item"
                      />
                    </td>
                  )}
                  {actions.length > 0 && (
                    <td 
                      className={styles.actionsColumn}
                      style={{ width: '120px', minWidth: '120px', maxWidth: '120px' }}
                    >
                      <div className={styles.actionButtons}>
                        {actions.map((action, actionIndex) => (
                          <button
                            key={actionIndex}
                            onClick={(e) => {
                              e.stopPropagation();
                              action.onClick(row);
                            }}
                            className={styles.actionButton}
                            title={action.label}
                          >
                            {action.icon && (
                              <span className={styles.actionIcon}>
                                {typeof action.icon === 'function' ? action.icon(row) : action.icon}
                              </span>
                            )}
                          </button>
                        ))}
                      </div>
                    </td>
                  )}
                  {detectedColumns.map(column => (
                    <td 
                      key={column.key} 
                      className={styles.td}
                      style={{ 
                        width: columnWidths[column.key] || column.width || 150,
                        minWidth: columnWidths[column.key] || column.width || 150,
                        maxWidth: columnWidths[column.key] || column.width || 150
                      }}
                    >
                      {formatCellValue(row[column.key], column, row)}
                    </td>
                  ))}
                  
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>

      {/* Pagination */}
      {pagination && (
        <div className={styles.pagination}>
          {showPageSizeSelector && (
            <div className={styles.pageSizeSelector}>
              <label htmlFor="pageSize">{t('formgen.pagination.pageSize', 'Items per page:')}</label>
              <select
                id="pageSize"
                value={currentPageSize}
                onChange={(e) => handlePageSizeChange(Number(e.target.value))}
                className={styles.pageSizeSelect}
              >
                {pageSizeOptions.map(size => (
                  <option key={size} value={size}>{size}</option>
                ))}
              </select>
            </div>
          )}
          
          {totalPages > 1 && (
            <>
              <button
                onClick={() => setCurrentPage(1)}
                disabled={currentPage === 1}
                className={styles.paginationButton}
                title={t('formgen.pagination.first')}
              >
                ««
              </button>
              <button
                onClick={() => setCurrentPage(currentPage - 1)}
                disabled={currentPage === 1}
                className={styles.paginationButton}
                title={t('formgen.pagination.prev')}
              >
                «
              </button>
              
              <span className={styles.paginationInfo}>
                {t('formgen.pagination.info')
                  .replace('{page}', currentPage.toString())
                  .replace('{total}', totalPages.toString())
                  .replace('{count}', filteredData.length.toString())}
              </span>
              
              <button
                onClick={() => setCurrentPage(currentPage + 1)}
                disabled={currentPage === totalPages}
                className={styles.paginationButton}
                title={t('formgen.pagination.next')}
              >
                »
              </button>
              <button
                onClick={() => setCurrentPage(totalPages)}
                disabled={currentPage === totalPages}
                className={styles.paginationButton}
                title={t('formgen.pagination.last')}
              >
                »»
              </button>
            </>
          )}
        </div>
      )}
    </div>
  );
}

export default FormGenerator; 