import { createSelector } from '@reduxjs/toolkit';
import type { RootState } from '@/store/store';
import type {
  ZohoProjectsDashboardStats,
  ZohoProject,
  ZohoTask,
  ZohoApiInfo,
} from '../types/ZohoProjectsTypes';

// Base selectors
export const selectZohoProjects = (state: RootState) => state.zohoProjects.projects;
export const selectZohoTasks = (state: RootState) => state.zohoProjects.tasks;
export const selectZohoIssues = (state: RootState) => state.zohoProjects.issues;
export const selectZohoPhases = (state: RootState) => state.zohoProjects.phases;
export const selectZohoProjectsLoading = (state: RootState) => state.zohoProjects.loading;
export const selectZohoProjectsErrors = (state: RootState) => state.zohoProjects.error;
export const selectZohoProjectsPagination = (state: RootState) => state.zohoProjects.pagination;
export const selectZohoProjectsLastUpdated = (state: RootState) => state.zohoProjects.lastUpdated;

// Derived selectors
export const selectIsAnyLoading = createSelector(
  [selectZohoProjectsLoading],
  (loading) => Object.values(loading).some(Boolean)
);

export const selectHasAnyError = createSelector(
  [selectZohoProjectsErrors],
  (errors) => Object.values(errors).some(error => error !== null)
);

export const selectZohoProjectsStats = createSelector(
  [selectZohoProjects, selectZohoTasks, selectZohoIssues, selectZohoPhases],
  (projects, tasks, issues, phases): ZohoProjectsDashboardStats => {
    // Ensure arrays are valid
    const validProjects = Array.isArray(projects) ? projects : [];
    const validTasks = Array.isArray(tasks) ? tasks : [];
    const validIssues = Array.isArray(issues) ? issues : [];
    const validPhases = Array.isArray(phases) ? phases : [];

    // Project statistics
    const totalProjects = validProjects.length;
    const activeProjects = validProjects.filter(p => 
      p.status?.name === 'Active' || p.project_type === 'active'
    ).length;
    const completedProjects = validProjects.filter(p => 
      p.is_completed || p.status?.name === 'Completed'
    ).length;

    // Task statistics
    const totalTasks = validTasks.length;
    const openTasks = validTasks.filter(t => 
      !t.is_completed || t.status?.is_closed_type === false
    ).length;
    const closedTasks = validTasks.filter(t => 
      t.is_completed || t.status?.is_closed_type === true
    ).length;

    // Milestone statistics from projects
    const totalMilestones = validProjects.reduce((sum, p) => 
      sum + (p.milestones?.open_count || 0) + (p.milestones?.closed_count || 0), 0
    );
    const openMilestones = validProjects.reduce((sum, p) => 
      sum + (p.milestones?.open_count || 0), 0
    );
    const closedMilestones = validProjects.reduce((sum, p) => 
      sum + (p.milestones?.closed_count || 0), 0
    );

    // Issue statistics from issues data
    const totalIssues = validIssues.length;
    const openIssues = validIssues.filter(i => 
      !i.status?.is_closed_type || i.status?.name === 'Open'
    ).length;
    const closedIssues = validIssues.filter(i => 
      i.status?.is_closed_type || i.status?.name === 'Closed'
    ).length;

    // Phase statistics from phases data
    const totalPhases = validPhases.length;
    const activePhases = validPhases.filter(p => 
      !p.status?.is_closed || p.status?.name === 'Active'
    ).length;
    const completedPhases = validPhases.filter(p => 
      p.status?.is_closed || p.status?.name === 'Completed'
    ).length;

    // Average completion rate
    const averageCompletionRate = totalProjects > 0 
      ? Math.round(validProjects.reduce((sum, p) => sum + (p.percent_complete || 0), 0) / totalProjects)
      : 0;

    // Team members count (unique owners)
    const uniqueOwners = new Set(
      validProjects.map(p => p.owner?.email || p.owner?.name).filter(Boolean)
    );
    const totalTeamMembers = uniqueOwners.size;

    // Work hours statistics
    const totalWorkHours = validTasks.reduce((sum, t) => {
      const workHours = parseFloat(t.owners_and_work?.total_work?.replace(':', '.') || '0');
      return sum + workHours;
    }, 0);

    const billableHours = validTasks.reduce((sum, t) => {
      const billable = parseFloat(t.log_hours?.billable_hours?.replace(':', '.') || '0');
      return sum + billable;
    }, 0);

    const nonBillableHours = validTasks.reduce((sum, t) => {
      const nonBillable = parseFloat(t.log_hours?.non_billable_hours?.replace(':', '.') || '0');
      return sum + nonBillable;
    }, 0);

    // Task completion statistics
    const averageTaskCompletion = totalTasks > 0 
      ? Math.round(validTasks.reduce((sum, t) => sum + (t.completion_percentage || 0), 0) / totalTasks)
      : 0;

    // Priority and overdue tasks
    const highPriorityTasks = validTasks.filter(t => 
      t.priority === 'high' || t.priority === 'urgent'
    ).length;

    const overdueTasks = validTasks.filter(t => {
      if (t.is_completed) return false;
      const endDate = new Date(t.end_date);
      const now = new Date();
      return endDate < now;
    }).length;

    // Average phase completion
    const averagePhaseCompletion = totalPhases > 0 
      ? Math.round(validPhases.reduce((sum, p) => sum + (p.completion_percentage || 0), 0) / totalPhases)
      : 0;

    return {
      totalProjects,
      activeProjects,
      completedProjects,
      totalTasks,
      openTasks,
      closedTasks,
      totalMilestones,
      openMilestones,
      closedMilestones,
      totalIssues,
      openIssues,
      closedIssues,
      totalPhases,
      activePhases,
      completedPhases,
      averageCompletionRate,
      totalTeamMembers,
      totalWorkHours,
      billableHours,
      nonBillableHours,
      averageTaskCompletion,
      highPriorityTasks,
      overdueTasks,
      averagePhaseCompletion,
    };
  }
);

export const selectDashboardData = createSelector(
  [selectZohoProjects, selectZohoTasks, selectZohoIssues, selectZohoPhases, selectZohoProjectsStats],
  (projects, tasks, issues, phases, stats) => {
    const validProjects = Array.isArray(projects) ? projects : [];
    const validTasks = Array.isArray(tasks) ? tasks : [];
    const validIssues = Array.isArray(issues) ? issues : [];
    const validPhases = Array.isArray(phases) ? phases : [];

    // Project status distribution
    const projectStatusDistribution = validProjects.reduce((acc, project) => {
      const status = project.status?.name || 'Unknown';
      acc[status] = (acc[status] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Task status distribution
    const taskStatusDistribution = validTasks.reduce((acc, task) => {
      const status = task.status?.name || 'Unknown';
      acc[status] = (acc[status] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Project types distribution
    const projectTypesDistribution = validProjects.reduce((acc, project) => {
      const type = project.project_type || 'Unknown';
      acc[type] = (acc[type] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Top projects by completion
    const topProjectsByCompletion = validProjects
      .sort((a, b) => (b.percent_complete || 0) - (a.percent_complete || 0))
      .slice(0, 5)
      .map(p => ({
        id: p.id,
        name: p.name,
        completion: p.percent_complete || 0,
        owner: p.owner?.full_name || p.owner?.name || 'Unknown',
        status: p.status?.name || 'Unknown',
      }));

    // Recent projects
    const recentProjects = validProjects
      .sort((a, b) => new Date(b.created_time).getTime() - new Date(a.created_time).getTime())
      .slice(0, 5)
      .map(p => ({
        id: p.id,
        name: p.name,
        createdTime: p.created_time,
        owner: p.owner?.full_name || p.owner?.name || 'Unknown',
        status: p.status?.name || 'Unknown',
      }));

    // Task priority distribution
    const taskPriorityDistribution = validTasks.reduce((acc, task) => {
      const priority = task.priority || 'Unknown';
      acc[priority] = (acc[priority] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Project owners distribution
    const projectOwnersDistribution = validProjects.reduce((acc, project) => {
      const owner = project.owner?.full_name || project.owner?.name || 'Unknown';
      acc[owner] = (acc[owner] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Issue status distribution
    const issueStatusDistribution = validIssues.reduce((acc, issue) => {
      const status = issue.status?.name || 'Unknown';
      acc[status] = (acc[status] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Issue severity distribution
    const issueSeverityDistribution = validIssues.reduce((acc, issue) => {
      const severity = issue.severity?.value || 'Unknown';
      acc[severity] = (acc[severity] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Phase status distribution
    const phaseStatusDistribution = validPhases.reduce((acc, phase) => {
      const status = phase.status?.name || 'Unknown';
      acc[status] = (acc[status] || 0) + 1;
      return acc;
    }, {} as Record<string, number>);

    // Top issues by severity
    const topIssuesBySeverity = validIssues
      .filter(i => i.severity?.value && i.severity.value !== 'None')
      .sort((a, b) => {
        const severityOrder = { 'Critical': 4, 'High': 3, 'Medium': 2, 'Low': 1 };
        return (severityOrder[b.severity.value as keyof typeof severityOrder] || 0) - 
               (severityOrder[a.severity.value as keyof typeof severityOrder] || 0);
      })
      .slice(0, 5)
      .map(i => ({
        id: i.id,
        name: i.name,
        severity: i.severity?.value || 'Unknown',
        status: i.status?.name || 'Unknown',
        assignee: i.assignee?.name || 'Unassigned',
      }));

    // Recent phases
    const recentPhases = validPhases
      .sort((a, b) => new Date(b.created_time).getTime() - new Date(a.created_time).getTime())
      .slice(0, 5)
      .map(p => ({
        id: p.id,
        name: p.name,
        createdTime: p.created_time,
        status: p.status?.name || 'Unknown',
        project: p.project?.name || 'Unknown',
      }));

    return {
      projectStatusDistribution,
      taskStatusDistribution,
      projectTypesDistribution,
      topProjectsByCompletion,
      recentProjects,
      taskPriorityDistribution,
      projectOwnersDistribution,
      issueStatusDistribution,
      issueSeverityDistribution,
      phaseStatusDistribution,
      topIssuesBySeverity,
      recentPhases,
    };
  }
);

// Helper function to get time ago
function getTimeAgo(dateString: string): string {
  const now = new Date();
  const date = new Date(dateString);
  const diffInMs = now.getTime() - date.getTime();
  const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60));
  
  if (diffInHours < 1) return 'Just now';
  if (diffInHours < 24) return `${diffInHours}h`;
  const diffInDays = Math.floor(diffInHours / 24);
  return `${diffInDays}d`;
}

// Helper function to get status color
function getStatusColor(status: string): string {
  const colorPalette = [
    '#3B82F6', // Bright Blue
    '#8B5CF6', // Purple
    '#06B6D4', // Cyan
    '#F59E0B', // Amber
    '#10B981', // Emerald
    '#F97316', // Orange
    '#22C55E', // Green
    '#84CC16', // Lime
    '#14B8A6', // Teal
    '#059669', // Dark Green
    '#EF4444', // Red
    '#DC2626', // Dark Red
    '#991B1B', // Darker Red
    '#9CA3AF', // Gray
    '#EC4899', // Pink
    '#8B5A2B', // Brown
    '#B91C1C', // Lost Red
    '#16A34A', // Success Green
    '#6366F1', // Indigo
    '#7C3AED', // Violet
    '#0891B2', // Sky Blue
    '#CA8A04', // Gold
    '#1F2937', // Dark Gray
    '#BE185D', // Rose
    '#0D9488', // Emerald Dark
    '#7C2D12', // Brown Dark
    '#1E40AF', // Blue Dark
    '#C2410C', // Orange Dark
    '#9333EA', // Purple Dark
    '#059669', // Green Dark
    '#DC2626', // Hot Red
    '#F97316', // Warm Orange
    '#6B7280', // Cold Gray
    '#EF4444', // Error Red
    '#10B981', // Success Green
    '#F59E0B', // Warning Orange
    '#3B82F6', // Info Blue
    '#0077B5', // LinkedIn Blue
    '#1877F2', // Facebook Blue
    '#1DA1F2', // Twitter Blue
    '#E4405F', // Instagram Pink
    '#FF0000', // YouTube Red
  ];

  // Create a consistent hash from the status string
  let hash = 0;
  const normalizedStatus = status.toLowerCase().trim();
  for (let i = 0; i < normalizedStatus.length; i++) {
    const char = normalizedStatus.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // Convert to 32-bit integer
  }
  
  // Ensure positive index and get color from palette
  const colorIndex = Math.abs(hash) % colorPalette.length;
  return colorPalette[colorIndex];
}

export { getTimeAgo, getStatusColor };
