// src/client/entities/task.ts
// Task entity - Pinia store and types

import { defineStore } from 'pinia';
import { taskRepository, type Task, type Position, type CreateTaskInput, type UpdateTaskInput, type UpdateTaskPositionsInput } from '../shared/api/repositories';
import type { ReorderTasksInput } from '@shared/contracts/tasks';

// Re-export types for convenience
export type { Task, Position, CreateTaskInput, UpdateTaskInput, UpdateTaskPositionsInput };
export type { ReorderTasksInput };

// Task store
export const useTaskStore = defineStore('task', {
  state: (): {
    tasks: Task[];
    loading: boolean;
    error: string | null;
  } => ({
    tasks: [],
    loading: false,
    error: null,
  }),

  persist: true,

  getters: {
    // Root tasks (tasks without parent)
    rootTasks: (state) => {
      return (state.tasks || []).filter(task => task.parentId === null);
    },

    // Get child tasks for a specific parent
    getChildTasks: (state) => (parentId: string) => {
      return (state.tasks || [])
        .filter(task => task.parentId === parentId)
        .sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
    },

    // Get task by ID
    getTaskById: (state) => (id: string) => {
      return (state.tasks || []).find(task => task.id === id);
    },

    // Get all tasks with their children (nested structure)
    tasksTree: (state) => {
      const buildTree = (parentId: string | null): Task[] => {
        return (state.tasks || [])
          .filter(task => task.parentId === parentId)
          .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))
          .map(task => ({
            ...task,
            children: buildTree(task.id),
          }));
      };
      return buildTree(null);
    },
  },

  actions: {
    // Fetch all tasks
    async fetchTasks(): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        const response = await taskRepository.getAll();
        this.tasks = response;
      } catch (error: any) {
        this.error = error.message || 'Failed to fetch tasks';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Fetch all tasks without cache
    async fetchTasksFresh(): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        const response = await taskRepository.getAllFresh();
        this.tasks = response;
      } catch (error: any) {
        this.error = error.message || 'Failed to fetch tasks';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Create a new task
    async createTask(input: CreateTaskInput): Promise<Task> {
      this.loading = true;
      this.error = null;
      try {
        const response = await taskRepository.create(input);
        if (!this.tasks) this.tasks = [];
        this.tasks.push(response);
        return response;
      } catch (error: any) {
        this.error = error.message || 'Failed to create task';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Update a task
    async updateTask(id: string, updates: UpdateTaskInput): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        const response = await taskRepository.update(id, updates);
        const tasks = this.tasks || [];
        const index = tasks.findIndex(task => task.id === id);
        if (index !== -1) {
          this.tasks[index] = response;
        }
      } catch (error: any) {
        this.error = error.message || 'Failed to update task';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Delete a task (recursively deletes subtasks)
    async deleteTask(id: string): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        await taskRepository.deleteTask(id);
        // Remove task and all its subtasks
        const taskIdsToRemove = [id, ...this.getAllSubtaskIds(id)];
        this.tasks = (this.tasks || []).filter(task => !taskIdsToRemove.includes(task.id));
      } catch (error: any) {
        this.error = error.message || 'Failed to delete task';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Toggle task completion
    async toggleTask(id: string): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        const response = await taskRepository.toggle(id);
        const tasks = this.tasks || [];
        const index = tasks.findIndex(task => task.id === id);
        if (index !== -1) {
          this.tasks[index] = response;
        }
      } catch (error: any) {
        this.error = error.message || 'Failed to toggle task';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Update task positions (batch update for grid layout)
    async updateTaskPositions(data: UpdateTaskPositionsInput): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        await taskRepository.updatePositions(data);
        // Update local state with new positions
        const tasks = this.tasks || [];
        for (const { id, position } of data.tasks) {
          const index = tasks.findIndex(task => task.id === id);
          if (index !== -1) {
            this.tasks[index] = {
              ...this.tasks[index],
              position,
            };
          }
        }
      } catch (error: any) {
        this.error = error.message || 'Failed to update task positions';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Reorder tasks with hierarchy support (batch update for order and parentId)
    async reorderTasks(data: ReorderTasksInput): Promise<void> {
      this.loading = true;
      this.error = null;
      try {
        await taskRepository.reorder(data);
        // Update local state with new order and parentId
        const tasks = this.tasks || [];
        for (const { id, order, parentId } of data.tasks) {
          const index = tasks.findIndex(task => task.id === id);
          if (index !== -1) {
            this.tasks[index] = {
              ...this.tasks[index],
              order,
              parentId,
            };
          }
        }
      } catch (error: any) {
        this.error = error.message || 'Failed to reorder tasks';
        throw error;
      } finally {
        this.loading = false;
      }
    },

    // Local actions
    addTask(task: Task) {
      if (!this.tasks) this.tasks = [];
      this.tasks.push(task);
    },

    updateLocalTask(id: string, updates: Partial<Task>) {
      const tasks = this.tasks || [];
      const index = tasks.findIndex(task => task.id === id);
      if (index !== -1) {
        this.tasks[index] = { ...this.tasks[index], ...updates };
      }
    },

    deleteLocalTask(id: string) {
      // Remove task and all its subtasks
      const taskIdsToRemove = [id, ...this.getAllSubtaskIds(id)];
      this.tasks = (this.tasks || []).filter(task => !taskIdsToRemove.includes(task.id));
    },

    // Sync layout (update positions from external source)
    syncLayout(tasks: Array<{ id: string; position: Position }>) {
      const tasksArray = this.tasks || [];
      for (const { id, position } of tasks) {
        const index = tasksArray.findIndex(task => task.id === id);
        if (index !== -1) {
          this.tasks[index] = {
            ...this.tasks[index],
            position,
          };
        }
      }
    },

    clearError() {
      this.error = null;
    },

    // Clear all tasks (used on logout)
    clearTasks() {
      this.tasks = [];
      this.error = null;
    },

    // Helper: Get all subtask IDs recursively
    getAllSubtaskIds(parentId: string): string[] {
      const directChildren = (this.tasks || []).filter(task => task.parentId === parentId);
      const allIds: string[] = [];
      
      for (const child of directChildren) {
        allIds.push(child.id);
        allIds.push(...this.getAllSubtaskIds(child.id));
      }
      
      return allIds;
    },
  },
});
