/**
 * TASKMATE - Utility Functions
 * ============================
 */

// Date Formatting
export function formatDate(dateString, options = {}) {
  if (!dateString) return '';

  const date = new Date(dateString);
  const now = new Date();

  if (options.relative) {
    const diff = date - now;
    const days = Math.ceil(diff / (1000 * 60 * 60 * 24));

    if (days === 0) return 'Heute';
    if (days === 1) return 'Morgen';
    if (days === -1) return 'Gestern';
    if (days > 0 && days <= 7) return `In ${days} Tagen`;
    if (days < 0 && days >= -7) return `Vor ${Math.abs(days)} Tagen`;
  }

  return date.toLocaleDateString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: options.year ? 'numeric' : undefined,
    ...options
  });
}

export function formatDateTime(dateString) {
  if (!dateString) return '';

  const date = new Date(dateString);
  return date.toLocaleDateString('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit'
  });
}

export function formatTime(dateString) {
  if (!dateString) return '';

  const date = new Date(dateString);
  return date.toLocaleTimeString('de-DE', {
    hour: '2-digit',
    minute: '2-digit'
  });
}

export function formatRelativeTime(dateString) {
  if (!dateString) return '';

  const date = new Date(dateString);
  const now = new Date();
  const diff = now - date;

  const minutes = Math.floor(diff / 60000);
  const hours = Math.floor(diff / 3600000);
  const days = Math.floor(diff / 86400000);

  if (minutes < 1) return 'Gerade eben';
  if (minutes < 60) return `Vor ${minutes} Min.`;
  if (hours < 24) return `Vor ${hours} Std.`;
  if (days < 7) return `Vor ${days} Tagen`;

  return formatDate(dateString, { year: true });
}

// Time Duration
export function formatDuration(hours, minutes) {
  const parts = [];
  if (hours > 0) parts.push(`${hours}h`);
  if (minutes > 0) parts.push(`${minutes}m`);
  return parts.join(' ') || '0m';
}

export function parseDuration(durationString) {
  const match = durationString.match(/(\d+)h\s*(\d+)?m?|(\d+)m/);
  if (!match) return { hours: 0, minutes: 0 };

  if (match[1]) {
    return {
      hours: parseInt(match[1]) || 0,
      minutes: parseInt(match[2]) || 0
    };
  }

  return {
    hours: 0,
    minutes: parseInt(match[3]) || 0
  };
}

// File Size
export function formatFileSize(bytes) {
  if (bytes === 0) return '0 B';

  const units = ['B', 'KB', 'MB', 'GB'];
  const k = 1024;
  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + units[i];
}

// String Utilities
export function truncate(str, length = 50) {
  if (!str || str.length <= length) return str;
  return str.substring(0, length) + '...';
}

export function escapeHtml(str) {
  if (!str) return '';

  const div = document.createElement('div');
  div.textContent = str;
  return div.innerHTML;
}

export function slugify(str) {
  return str
    .toLowerCase()
    .replace(/[äöüß]/g, match => ({
      'ä': 'ae', 'ö': 'oe', 'ü': 'ue', 'ß': 'ss'
    }[match]))
    .replace(/[^\w\s-]/g, '')
    .replace(/[\s_-]+/g, '-')
    .replace(/^-+|-+$/g, '');
}

export function getInitials(name) {
  if (!name) return '?';

  return name
    .split(' ')
    .map(part => part.charAt(0).toUpperCase())
    .slice(0, 2)
    .join('');
}

// Color Utilities
export function hexToRgba(hex, alpha = 1) {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
  if (!result) return hex;

  return `rgba(${parseInt(result[1], 16)}, ${parseInt(result[2], 16)}, ${parseInt(result[3], 16)}, ${alpha})`;
}

export function getContrastColor(hexColor) {
  const rgb = parseInt(hexColor.slice(1), 16);
  const r = (rgb >> 16) & 0xff;
  const g = (rgb >> 8) & 0xff;
  const b = (rgb >> 0) & 0xff;

  const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
  return luminance > 0.5 ? '#000000' : '#FFFFFF';
}

// DOM Utilities
export function $(selector, context = document) {
  return context.querySelector(selector);
}

export function $$(selector, context = document) {
  return Array.from(context.querySelectorAll(selector));
}

export function createElement(tag, attributes = {}, children = []) {
  const element = document.createElement(tag);

  Object.entries(attributes).forEach(([key, value]) => {
    if (key === 'className') {
      element.className = value;
    } else if (key === 'dataset') {
      Object.entries(value).forEach(([dataKey, dataValue]) => {
        element.dataset[dataKey] = dataValue;
      });
    } else if (key === 'style' && typeof value === 'object') {
      Object.assign(element.style, value);
    } else if (key.startsWith('on') && typeof value === 'function') {
      element.addEventListener(key.slice(2).toLowerCase(), value);
    } else if (key === 'checked' || key === 'disabled' || key === 'selected') {
      // Boolean properties must be set as properties, not attributes
      element[key] = value;
    } else {
      element.setAttribute(key, value);
    }
  });

  children.forEach(child => {
    if (typeof child === 'string') {
      element.appendChild(document.createTextNode(child));
    } else if (child instanceof Node) {
      element.appendChild(child);
    }
  });

  return element;
}

export function removeElement(element) {
  if (element && element.parentNode) {
    element.parentNode.removeChild(element);
  }
}

export function clearElement(element) {
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

// Event Utilities
export function debounce(func, wait = 300) {
  let timeout;

  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };

    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
}

export function throttle(func, limit = 100) {
  let inThrottle;

  return function executedFunction(...args) {
    if (!inThrottle) {
      func(...args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

export function onClickOutside(element, callback) {
  const handler = (event) => {
    if (!element.contains(event.target)) {
      callback(event);
    }
  };

  document.addEventListener('click', handler);

  return () => document.removeEventListener('click', handler);
}

// Array Utilities
export function moveInArray(array, fromIndex, toIndex) {
  const element = array[fromIndex];
  array.splice(fromIndex, 1);
  array.splice(toIndex, 0, element);
  return array;
}

export function groupBy(array, key) {
  return array.reduce((groups, item) => {
    const value = typeof key === 'function' ? key(item) : item[key];
    (groups[value] = groups[value] || []).push(item);
    return groups;
  }, {});
}

export function sortBy(array, key, direction = 'asc') {
  const modifier = direction === 'desc' ? -1 : 1;

  return [...array].sort((a, b) => {
    const aValue = typeof key === 'function' ? key(a) : a[key];
    const bValue = typeof key === 'function' ? key(b) : b[key];

    if (aValue < bValue) return -1 * modifier;
    if (aValue > bValue) return 1 * modifier;
    return 0;
  });
}

// Object Utilities
export function deepClone(obj) {
  return JSON.parse(JSON.stringify(obj));
}

export function deepMerge(target, source) {
  const output = { ...target };

  Object.keys(source).forEach(key => {
    if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
      if (target[key] && typeof target[key] === 'object') {
        output[key] = deepMerge(target[key], source[key]);
      } else {
        output[key] = { ...source[key] };
      }
    } else {
      output[key] = source[key];
    }
  });

  return output;
}

// URL Utilities
export function getUrlDomain(url) {
  try {
    return new URL(url).hostname;
  } catch {
    return url;
  }
}

export function isValidUrl(string) {
  try {
    new URL(string);
    return true;
  } catch {
    return false;
  }
}

export function getFileExtension(filename) {
  return filename.split('.').pop().toLowerCase();
}

export function isImageFile(filename) {
  const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp'];
  return imageExtensions.includes(getFileExtension(filename));
}

// ID Generation
export function generateId() {
  return Date.now().toString(36) + Math.random().toString(36).substr(2);
}

export function generateTempId() {
  return 'temp_' + generateId();
}

// Local Storage
export function getFromStorage(key, defaultValue = null) {
  try {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : defaultValue;
  } catch {
    return defaultValue;
  }
}

export function setToStorage(key, value) {
  try {
    localStorage.setItem(key, JSON.stringify(value));
    return true;
  } catch {
    return false;
  }
}

export function removeFromStorage(key) {
  try {
    localStorage.removeItem(key);
    return true;
  } catch {
    return false;
  }
}

// Priority Stars
export function getPriorityStars(priority) {
  const config = {
    high: { stars: '★★★', label: 'Hohe Priorität', colorClass: 'priority-high' },
    medium: { stars: '★★', label: 'Mittlere Priorität', colorClass: 'priority-medium' },
    low: { stars: '★', label: 'Niedrige Priorität', colorClass: 'priority-low' }
  };
  return config[priority] || config.medium;
}

export function createPriorityElement(priority) {
  const config = getPriorityStars(priority);
  const span = document.createElement('span');
  span.className = `priority-stars ${config.colorClass}`;
  span.textContent = config.stars;
  span.title = config.label;
  return span;
}

// Due Date Status
export function getDueDateStatus(dueDate) {
  if (!dueDate) return null;

  const due = new Date(dueDate);
  const now = new Date();
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const dueDay = new Date(due.getFullYear(), due.getMonth(), due.getDate());

  const diffDays = Math.ceil((dueDay - today) / (1000 * 60 * 60 * 24));

  if (diffDays < 0) return 'overdue';
  if (diffDays === 0) return 'today';
  if (diffDays <= 2) return 'soon';
  return 'normal';
}

// Progress Calculation
export function calculateProgress(subtasks) {
  if (!subtasks || subtasks.length === 0) return null;

  const completed = subtasks.filter(st => st.completed).length;
  return {
    completed,
    total: subtasks.length,
    percentage: Math.round((completed / subtasks.length) * 100)
  };
}

// Search/Filter Helpers
export function matchesSearch(text, query) {
  if (!query) return true;
  if (!text) return false;

  return text.toLowerCase().includes(query.toLowerCase());
}

/**
 * Deep search in task content - searches in title, description, subtasks, and labels
 * @param {Object} task - The task object to search in
 * @param {string} query - The search query
 * @returns {boolean} - True if query matches any content
 */
export function searchInTaskContent(task, query) {
  if (!query || !query.trim()) return true;

  const searchQuery = query.toLowerCase().trim();

  // Search in title
  if (task.title && task.title.toLowerCase().includes(searchQuery)) {
    return true;
  }

  // Search in description
  if (task.description && task.description.toLowerCase().includes(searchQuery)) {
    return true;
  }

  // Search in subtasks
  if (task.subtasks && Array.isArray(task.subtasks)) {
    for (const subtask of task.subtasks) {
      if (subtask.title && subtask.title.toLowerCase().includes(searchQuery)) {
        return true;
      }
    }
  }

  // Search in labels
  if (task.labels && Array.isArray(task.labels)) {
    for (const label of task.labels) {
      if (label.name && label.name.toLowerCase().includes(searchQuery)) {
        return true;
      }
    }
  }

  // Search in assigned user name
  if (task.assignedName && task.assignedName.toLowerCase().includes(searchQuery)) {
    return true;
  }

  return false;
}

export function filterTasks(tasks, filters, searchResultIds = [], columns = []) {
  // Hilfsfunktion: Prüfen ob Aufgabe in der letzten Spalte (erledigt) ist
  const isTaskCompleted = (task) => {
    if (!columns || columns.length === 0) return false;
    const lastColumnId = columns[columns.length - 1].id;
    return task.columnId === lastColumnId;
  };

  return tasks.filter(task => {
    // Search query - use deep search
    // But allow tasks that were found by server search (for deep content like attachments)
    if (filters.search) {
      const isServerResult = searchResultIds.includes(task.id);
      const matchesClient = searchInTaskContent(task, filters.search);

      if (!isServerResult && !matchesClient) {
        return false;
      }
    }

    // Priority filter (string or array)
    if (filters.priority && filters.priority.length > 0) {
      const priorityFilter = Array.isArray(filters.priority) ? filters.priority : [filters.priority];
      if (!priorityFilter.includes(task.priority)) return false;
    }

    // Assignee filter (string or array)
    if (filters.assignee && filters.assignee.length > 0) {
      const assigneeFilter = Array.isArray(filters.assignee) ? filters.assignee : [filters.assignee];
      const assigneeIds = assigneeFilter.map(id => parseInt(id));
      const taskAssigneeId = task.assignedTo;
      const taskAssignees = task.assignees?.map(a => a.id || a) || [];
      const matches = assigneeIds.some(id => id === taskAssigneeId || taskAssignees.includes(id));
      if (!matches) return false;
    }

    // Label filter (string or array)
    if (filters.label && filters.label.length > 0) {
      const labelFilter = Array.isArray(filters.label) ? filters.label : [filters.label];
      const labelIds = labelFilter.map(id => parseInt(id));
      const hasLabel = task.labels?.some(l => labelIds.includes(l.id));
      if (!hasLabel) return false;
    }

    // Due date filter (string or array)
    if (filters.dueDate && filters.dueDate.length > 0) {
      const dueDateFilter = Array.isArray(filters.dueDate) ? filters.dueDate : [filters.dueDate];
      let matches = false;

      for (const filterVal of dueDateFilter) {
        if (filterVal === 'none') {
          if (!task.dueDate) { matches = true; break; }
        } else if (filterVal === 'overdue') {
          const status = getDueDateStatus(task.dueDate);
          if (status === 'overdue' && !isTaskCompleted(task)) { matches = true; break; }
        } else if (filterVal === 'today') {
          const status = getDueDateStatus(task.dueDate);
          if (status === 'today') { matches = true; break; }
        } else if (filterVal === 'week') {
          if (task.dueDate) {
            const due = new Date(task.dueDate);
            const weekFromNow = new Date();
            weekFromNow.setDate(weekFromNow.getDate() + 7);
            if (due <= weekFromNow) { matches = true; break; }
          }
        }
      }

      if (!matches) return false;
    }

    return true;
  });
}

// Clipboard
export async function copyToClipboard(text) {
  try {
    await navigator.clipboard.writeText(text);
    return true;
  } catch {
    // Fallback
    const textarea = document.createElement('textarea');
    textarea.value = text;
    textarea.style.position = 'fixed';
    textarea.style.opacity = '0';
    document.body.appendChild(textarea);
    textarea.select();

    try {
      document.execCommand('copy');
      return true;
    } finally {
      document.body.removeChild(textarea);
    }
  }
}

// Keyboard Helpers
export function getKeyCombo(event) {
  const parts = [];

  if (event.ctrlKey || event.metaKey) parts.push('Ctrl');
  if (event.altKey) parts.push('Alt');
  if (event.shiftKey) parts.push('Shift');

  if (event.key && !['Control', 'Alt', 'Shift', 'Meta'].includes(event.key)) {
    parts.push(event.key.toUpperCase());
  }

  return parts.join('+');
}

// Focus Management
export function trapFocus(element) {
  const focusableElements = element.querySelectorAll(
    'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
  );

  const firstFocusable = focusableElements[0];
  const lastFocusable = focusableElements[focusableElements.length - 1];

  const handleKeydown = (e) => {
    if (e.key !== 'Tab') return;

    if (e.shiftKey) {
      if (document.activeElement === firstFocusable) {
        lastFocusable.focus();
        e.preventDefault();
      }
    } else {
      if (document.activeElement === lastFocusable) {
        firstFocusable.focus();
        e.preventDefault();
      }
    }
  };

  element.addEventListener('keydown', handleKeydown);

  return () => element.removeEventListener('keydown', handleKeydown);
}

// Announcements for Screen Readers
export function announce(message, priority = 'polite') {
  const announcer = document.getElementById('sr-announcer') || createAnnouncer();
  announcer.setAttribute('aria-live', priority);
  announcer.textContent = message;
}

function createAnnouncer() {
  const announcer = document.createElement('div');
  announcer.id = 'sr-announcer';
  announcer.setAttribute('aria-live', 'polite');
  announcer.setAttribute('aria-atomic', 'true');
  announcer.className = 'sr-only';
  document.body.appendChild(announcer);
  return announcer;
}
