import { 
  TodayTask, 
  DailyWorkflow, 
  WorkflowProgress, 
  TaskCompletionData,
  TaskGenerationContext,
  WorkflowOrchestratorConfig,
  NavigationState,
  WorkflowError
} from '../types/workflow';
import { taskNavigationService } from './TaskNavigationService';
import { taskDependencyManager } from './TaskDependencyManager';
import { taskCompletionVerifier } from './TaskCompletionVerifier';

class TaskWorkflowOrchestrator {
  private workflows: Map<string, DailyWorkflow> = new Map();
  private config: WorkflowOrchestratorConfig;

  constructor(config: WorkflowOrchestratorConfig = {
    autoNavigate: true,
    showProgress: true,
    enableNotifications: true,
    persistProgress: true,
    allowTaskSkipping: true
  }) {
    this.config = config;
    this.loadPersistedWorkflows();
  }

  /**
   * Generate a new daily workflow for a user
   */
  async generateDailyWorkflow(
    userId: string, 
    date: string = new Date().toISOString().split('T')[0],
    context?: TaskGenerationContext
  ): Promise<DailyWorkflow> {
    try {
      // Check if workflow already exists for this date
      const existingWorkflow = this.getWorkflow(userId, date);
      if (existingWorkflow) {
        return existingWorkflow;
      }

      // Generate tasks based on context or default configuration
      const tasks = await this.generateTasksForDate(userId, date, context);
      
      // Create new workflow
      const workflow: DailyWorkflow = {
        id: `${userId}-${date}`,
        date,
        userId,
        tasks,
        currentTaskIndex: 0,
        completedTasks: 0,
        totalTasks: tasks.length,
        workflowStatus: 'not_started',
        totalEstimatedTime: tasks.reduce((sum, task) => sum + task.estimatedTime, 0),
        actualTimeSpent: 0
      };

      // Save workflow
      this.workflows.set(workflow.id, workflow);
      this.persistWorkflow(workflow);

      return workflow;
    } catch (error) {
      throw new WorkflowError({
        code: 'WORKFLOW_GENERATION_FAILED',
        message: `Failed to generate workflow for user ${userId} on ${date}`,
        timestamp: new Date(),
        recoverable: true,
        suggestedAction: 'Retry workflow generation'
      });
    }
  }

  /**
   * Get workflow for a specific user and date
   */
  getWorkflow(userId: string, date: string): DailyWorkflow | null {
    const workflowId = `${userId}-${date}`;
    return this.workflows.get(workflowId) || null;
  }

  /**
   * Start a workflow
   */
  async startWorkflow(workflowId: string): Promise<DailyWorkflow> {
    const workflow = this.workflows.get(workflowId);
    if (!workflow) {
      throw new WorkflowError({
        code: 'WORKFLOW_NOT_FOUND',
        message: `Workflow ${workflowId} not found`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    workflow.workflowStatus = 'in_progress';
    workflow.startedAt = new Date();
    
    // Mark first task as in progress
    if (workflow.tasks.length > 0) {
      workflow.tasks[0].status = 'in_progress';
      workflow.tasks[0].startedAt = new Date();
    }

    this.persistWorkflow(workflow);
    return workflow;
  }

  /**
   * Complete a specific task
   */
  async completeTask(
    workflowId: string, 
    taskId: string, 
    completionData?: Partial<TaskCompletionData>
  ): Promise<WorkflowProgress> {
    const workflow = this.workflows.get(workflowId);
    if (!workflow) {
      throw new WorkflowError({
        code: 'WORKFLOW_NOT_FOUND',
        message: `Workflow ${workflowId} not found`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    const task = workflow.tasks.find(t => t.id === taskId);
    if (!task) {
      throw new WorkflowError({
        code: 'TASK_NOT_FOUND',
        message: `Task ${taskId} not found in workflow ${workflowId}`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    // Verify task completion
    await taskCompletionVerifier.verifyTaskCompletion(task, {
      userId: workflow.userId,
      timestamp: new Date()
    });

    // Mark task as completed
    task.status = 'completed';
    task.completedAt = new Date();
    
    // Calculate time spent
    if (task.startedAt) {
      const timeSpent = Math.round((task.completedAt.getTime() - task.startedAt.getTime()) / (1000 * 60));
      workflow.actualTimeSpent += timeSpent;
    }

    // Update dependency manager
    taskDependencyManager.updateTaskStatus(taskId, 'completed');

    // Update workflow progress
    workflow.completedTasks++;
    
    // Check if workflow is complete
    if (workflow.completedTasks === workflow.totalTasks) {
      workflow.workflowStatus = 'completed';
      workflow.completedAt = new Date();
    }

    // Auto-navigate to next task if enabled
    if (this.config.autoNavigate) {
      const nextTask = taskDependencyManager.getReadyTasks(workflow)[0];
      if (nextTask) {
        setTimeout(async () => {
          try {
            await taskNavigationService.navigateToTask(nextTask, workflow);
          } catch (error) {
            console.warn('Auto-navigation failed:', error);
          }
        }, 2000); // 2 second delay
      }
    }

    this.persistWorkflow(workflow);
    return this.getWorkflowProgress(workflowId);
  }

  /**
   * Skip a task
   */
  async skipTask(workflowId: string, taskId: string): Promise<WorkflowProgress> {
    const workflow = this.workflows.get(workflowId);
    if (!workflow) {
      throw new WorkflowError({
        code: 'WORKFLOW_NOT_FOUND',
        message: `Workflow ${workflowId} not found`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    const task = workflow.tasks.find(t => t.id === taskId);
    if (!task) {
      throw new WorkflowError({
        code: 'TASK_NOT_FOUND',
        message: `Task ${taskId} not found in workflow ${workflowId}`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    task.status = 'skipped';
    workflow.completedTasks++;
    
    this.persistWorkflow(workflow);
    return this.getWorkflowProgress(workflowId);
  }

  /**
   * Get current workflow progress
   */
  getWorkflowProgress(workflowId: string): WorkflowProgress {
    const workflow = this.workflows.get(workflowId);
    if (!workflow) {
      throw new WorkflowError({
        code: 'WORKFLOW_NOT_FOUND',
        message: `Workflow ${workflowId} not found`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    const currentTask = workflow.tasks[workflow.currentTaskIndex];
    const nextTask = workflow.tasks[workflow.currentTaskIndex + 1];
    const remainingTasks = workflow.tasks.slice(workflow.currentTaskIndex + 1);
    const estimatedTimeRemaining = remainingTasks.reduce((sum, task) => sum + task.estimatedTime, 0);

    return {
      completedTasks: workflow.completedTasks,
      totalTasks: workflow.totalTasks,
      completionPercentage: Math.round((workflow.completedTasks / workflow.totalTasks) * 100),
      currentTask,
      nextTask,
      estimatedTimeRemaining,
      actualTimeSpent: workflow.actualTimeSpent
    };
  }

  /**
   * Get navigation state for current workflow
   */
  getNavigationState(workflowId: string): NavigationState {
    const workflow = this.workflows.get(workflowId);
    if (!workflow) {
      throw new WorkflowError({
        code: 'WORKFLOW_NOT_FOUND',
        message: `Workflow ${workflowId} not found`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    const currentTask = workflow.tasks[workflow.currentTaskIndex];
    const previousTask = workflow.currentTaskIndex > 0 ? workflow.tasks[workflow.currentTaskIndex - 1] : null;
    const nextTask = workflow.currentTaskIndex < workflow.tasks.length - 1 ? workflow.tasks[workflow.currentTaskIndex + 1] : null;

    return {
      currentTask,
      previousTask,
      nextTask,
      canGoBack: workflow.currentTaskIndex > 0,
      canGoForward: workflow.currentTaskIndex < workflow.tasks.length - 1
    };
  }

  /**
   * Move to next task in workflow
   */
  async moveToNextTask(workflowId: string): Promise<TodayTask | null> {
    const workflow = this.workflows.get(workflowId);
    if (!workflow) {
      throw new WorkflowError({
        code: 'WORKFLOW_NOT_FOUND',
        message: `Workflow ${workflowId} not found`,
        timestamp: new Date(),
        recoverable: false
      });
    }

    if (workflow.currentTaskIndex < workflow.tasks.length - 1) {
      workflow.currentTaskIndex++;
      const nextTask = workflow.tasks[workflow.currentTaskIndex];
      
      // Mark next task as in progress
      if (nextTask.status === 'pending') {
        nextTask.status = 'in_progress';
        nextTask.startedAt = new Date();
      }

      this.persistWorkflow(workflow);
      return nextTask;
    }

    return null;
  }

  /**
   * Generate tasks for a specific date (enhanced with dependency management)
   */
  private async generateTasksForDate(
    userId: string, 
    date: string, 
    context?: TaskGenerationContext
  ): Promise<TodayTask[]> {
    const defaultTasks: TodayTask[] = [
      {
        id: `${userId}-${date}-plan`,
        pillarId: 'plan',
        title: 'Review today\'s plan',
        description: 'Confirm priorities and schedule for today\'s content work.',
        status: 'pending',
        priority: 'high',
        estimatedTime: 10,
        actionType: 'navigate',
        actionUrl: '/content-planning-dashboard',
        enabled: true,
        icon: 'Business',
        color: '#4CAF50'
      },
      {
        id: `${userId}-${date}-generate`,
        pillarId: 'generate',
        title: 'Generate a draft',
        description: 'Create one content draft using the content writer.',
        status: 'pending',
        priority: 'medium',
        estimatedTime: 20,
        dependencies: [`${userId}-${date}-plan`],
        actionType: 'navigate',
        actionUrl: '/facebook-writer',
        enabled: true,
        icon: 'AutoAwesome',
        color: '#2196F3'
      },
      {
        id: `${userId}-${date}-publish`,
        pillarId: 'publish',
        title: 'Publish approved content',
        description: 'Open publishing tools and publish today\'s approved draft.',
        status: 'pending',
        priority: 'high',
        estimatedTime: 10,
        dependencies: [`${userId}-${date}-generate`],
        actionType: 'navigate',
        actionUrl: '/facebook-writer',
        enabled: true,
        icon: 'Publish',
        color: '#FF9800'
      },
      {
        id: `${userId}-${date}-analyze`,
        pillarId: 'analyze',
        title: 'Check performance snapshot',
        description: 'Review key analytics to assess today\'s published content.',
        status: 'pending',
        priority: 'medium',
        estimatedTime: 10,
        dependencies: [`${userId}-${date}-publish`],
        actionType: 'navigate',
        actionUrl: '/analytics-dashboard',
        enabled: true,
        icon: 'Analytics',
        color: '#9C27B0'
      },
      {
        id: `${userId}-${date}-engage`,
        pillarId: 'engage',
        title: 'Respond to audience activity',
        description: 'Reply to new comments or mentions from today\'s posts.',
        status: 'pending',
        priority: 'low',
        estimatedTime: 10,
        dependencies: [`${userId}-${date}-publish`],
        actionType: 'navigate',
        actionUrl: '/engagement-dashboard',
        enabled: true,
        icon: 'ChatBubbleOutline',
        color: '#E91E63'
      },
      {
        id: `${userId}-${date}-remarket`,
        pillarId: 'remarket',
        title: 'Prepare remarketing audience',
        description: 'Open remarketing tools to refresh your retargeting audience.',
        status: 'pending',
        priority: 'low',
        estimatedTime: 15,
        dependencies: [`${userId}-${date}-analyze`],
        actionType: 'navigate',
        actionUrl: '/remarketing-dashboard',
        enabled: true,
        icon: 'Psychology',
        color: '#00695C'
      }
    ];

    const uniqueTasks = this.ensureUniqueTaskIds(defaultTasks);

    // Validate dependencies and get optimal execution order
    const tempWorkflow: DailyWorkflow = {
      id: `${userId}-${date}`,
      date,
      userId,
      tasks: uniqueTasks,
      currentTaskIndex: 0,
      completedTasks: 0,
      totalTasks: uniqueTasks.length,
      workflowStatus: 'not_started',
      totalEstimatedTime: uniqueTasks.reduce((sum, task) => sum + task.estimatedTime, 0),
      actualTimeSpent: 0
    };

    // Validate dependency graph
    const validation = taskDependencyManager.validateDependencyGraph(tempWorkflow);
    if (!validation.isValid) {
      console.warn('Dependency validation failed:', validation.errors);
      // Return tasks without dependencies if validation fails
      return uniqueTasks.map(task => ({ ...task, dependencies: [] }));
    }

    // Get optimal execution order
    const orderedTasks = taskDependencyManager.getOptimalExecutionOrder(tempWorkflow);
    
    return this.ensureUniqueTaskIds(orderedTasks);
  }

  private ensureUniqueTaskIds(tasks: TodayTask[]): TodayTask[] {
    const idOccurrences = new Map<string, number>();
    const oldToNew = new Map<string, string>();

    const withUniqueIds = tasks.map(task => {
      const count = idOccurrences.get(task.id) ?? 0;
      idOccurrences.set(task.id, count + 1);

      if (count === 0) {
        oldToNew.set(task.id, task.id);
        return { ...task };
      }

      const uniqueId = `${task.id}-${count + 1}`;
      oldToNew.set(`${task.id}#${count + 1}`, uniqueId);
      return { ...task, id: uniqueId };
    });

    const allTaskIds = new Set(withUniqueIds.map(task => task.id));

    return withUniqueIds.map(task => {
      const dependencies = (task.dependencies ?? [])
        .map(dep => oldToNew.get(dep) || dep)
        .filter((dep, index, arr) => arr.indexOf(dep) === index)
        .filter(dep => allTaskIds.has(dep));

      return {
        ...task,
        dependencies: dependencies.length > 0 ? dependencies : undefined
      };
    });
  }

  /**
   * Persist workflow to localStorage
   */
  private persistWorkflow(workflow: DailyWorkflow): void {
    if (this.config.persistProgress) {
      try {
        localStorage.setItem(`workflow-${workflow.id}`, JSON.stringify(workflow));
      } catch (error) {
        console.warn('Failed to persist workflow:', error);
      }
    }
  }

  /**
   * Load persisted workflows from localStorage
   */
  private loadPersistedWorkflows(): void {
    if (this.config.persistProgress) {
      try {
        const keys = Object.keys(localStorage).filter(key => key.startsWith('workflow-') && key !== 'workflow-store');
        keys.forEach(key => {
          const workflowData = localStorage.getItem(key);
          if (workflowData) {
            try {
              const workflow = JSON.parse(workflowData) as DailyWorkflow;
              
              // Ensure workflow has required properties
              if (!workflow.id || !workflow.date || !workflow.userId) {
                console.warn(`Invalid workflow data for key ${key}, skipping and cleaning up`);
                localStorage.removeItem(key);
                return;
              }
              
              // Ensure tasks array exists and is valid
              if (!workflow.tasks || !Array.isArray(workflow.tasks)) {
                console.warn(`Invalid tasks array for workflow ${workflow.id}, initializing empty array`);
                workflow.tasks = [];
              }
              
              // Convert date strings back to Date objects
              if (workflow.startedAt) workflow.startedAt = new Date(workflow.startedAt);
              if (workflow.completedAt) workflow.completedAt = new Date(workflow.completedAt);
              
              // Process tasks with null checks
              workflow.tasks.forEach(task => {
                if (task && typeof task === 'object') {
                  if (task.startedAt) task.startedAt = new Date(task.startedAt);
                  if (task.completedAt) task.completedAt = new Date(task.completedAt);
                }
              });
              
              this.workflows.set(workflow.id, workflow);
            } catch (parseError) {
              console.warn(`Failed to parse workflow data for key ${key}:`, parseError);
              // Remove corrupted data
              localStorage.removeItem(key);
            }
          }
        });
      } catch (error) {
        console.warn('Failed to load persisted workflows:', error);
      }
    }
  }

  /**
   * Clear completed workflows (cleanup)
   */
  clearCompletedWorkflows(): void {
    const completedWorkflows = Array.from(this.workflows.values())
      .filter(workflow => workflow.workflowStatus === 'completed');
    
    completedWorkflows.forEach(workflow => {
      this.workflows.delete(workflow.id);
      if (this.config.persistProgress) {
        localStorage.removeItem(`workflow-${workflow.id}`);
      }
    });
  }
}

// Export singleton instance
export const taskWorkflowOrchestrator = new TaskWorkflowOrchestrator();
export default TaskWorkflowOrchestrator;
