import { defineStore } from 'pinia';
import { AppwriteIds, databases, ID } from 'src/boot/appwrite';
import type { Models } from 'appwrite';

export const TASKSTATUS = ['ready', 'complete', 'waiting', 'archived'];

export interface Task extends Partial<Models.Document> {
  title: string;
  description: string;
  /* Array of Appwrite Document IDs */
  required_skills: string[];
  /* Array of Appwrite Document IDs */
  tags: string[];
  due_date: string;
  duration: number;
  /* Array of Appwrite Document IDs */
  volunteers: string[];
  volunteers_required: number;
  status: string;
  /* Array of Appwrite Document IDs */
  depends_on: string[];
  /* Appwrite ID of a Boat resource */
  boat?: string[];
}

export interface TaskTag extends Models.Document {
  name: string;
  description: string;
  colour: string;
}
export interface SkillTag extends Models.Document {
  name: string;
  description: string;
  tagColour: string;
}

export const useTaskStore = defineStore('tasks', {
  state: () => ({
    tasks: [] as Task[],
    taskTags: [] as TaskTag[],
    skillTags: [] as SkillTag[],
  }),

  actions: {
    async fetchTasks() {
      try {
        await this.fetchTaskTags();
        await this.fetchSkillTags();
        const response = await databases.listDocuments(
          AppwriteIds.databaseId,
          AppwriteIds.collection.task
        );
        this.tasks = response.documents as Task[];
      } catch (error) {
        console.error('Failed to fetch tasks', error);
      }
    },
    async fetchTaskTags() {
      // This is fine for a small number of tags, but more than a few hundred tags, we'd need to optimize
      try {
        const response = await databases.listDocuments(
          AppwriteIds.databaseId,
          AppwriteIds.collection.taskTags
        );
        this.taskTags = response.documents as TaskTag[];
      } catch (error) {
        console.error('Failed to fetch task tags', error);
      }
    },
    async fetchSkillTags() {
      // This is fine for a small number of tags, but more than a few hundred tags, we'd need to optimize
      try {
        const response = await databases.listDocuments(
          AppwriteIds.databaseId,
          AppwriteIds.collection.skillTags
        );
        this.skillTags = response.documents as SkillTag[];
      } catch (error) {
        console.error('Failed to fetch skill tags', error);
      }
    },
    async deleteTask(task: Task | string) {
      const docId = typeof task === 'string' ? task : task.$id;
      if (docId === undefined) {
        console.error('No document ID provided to deleteTask!');
        return;
      }
      try {
        await databases.deleteDocument(
          AppwriteIds.databaseId,
          AppwriteIds.collection.task,
          docId
        );
        this.tasks = this.tasks.filter((task) => docId !== task.$id);
      } catch (error) {
        // Need some better error handling, here.
        console.error('Failed to delete task:', error);
      }
    },
    async addTask(task: Task) {
      const newTask = <Models.Document>{ ...task };
      try {
        const response = await databases.createDocument(
          AppwriteIds.databaseId,
          AppwriteIds.collection.task,
          ID.unique(),
          newTask
        );
        this.tasks.push(response as Task);
      } catch (error) {
        console.error('Failed to add task:', error);
      }
    },
    async updateTask(task: Task) {
      const newTask = <Partial<Models.Document>>{
        ...task,
        id: undefined,
        $databaseId: undefined,
        $collectionId: undefined,
      };
      if (!task.$id) {
        console.error('No Task ID!');
        return;
      }
      try {
        const response = await databases.updateDocument(
          AppwriteIds.databaseId,
          AppwriteIds.collection.task,
          task.$id,
          newTask
        );
        this.tasks.push(response as Task);
      } catch (error) {
        console.error('Failed to update task:', error);
      }
    },
    // TODO: Enhance this store to include offline caching, and subscription notification when items change on the server.
  },
  // Add more actions as needed (e.g., updateTask, deleteTask)
  getters: {
    getTaskById: (state) => (id: string) => {
      return state.tasks.find((task) => task.$id === id) || null;
    },
    getTaskTagById: (state) => (id: string) => {
      return state.taskTags.find((tag) => tag.$id === id) || null;
    },
    getSkillById: (state) => (id: string) => {
      return state.skillTags.find((tag) => tag.$id === id) || null;
    },
    filterTasksByTitle: (state) => (searchQuery: string) => {
      const result = state.tasks.filter((task) =>
        task.title.toLowerCase().includes(searchQuery.toLowerCase())
      );
      return result;
    },
  },
});
