import { ref } from "vue";
import { defineStore } from "pinia";
import { apiGet, apiPost, apiPut, apiPatch, apiDelete } from "@/api/client";
import { useToastStore } from "@/stores/toast";
import type { Task, TaskListResponse, TaskStatus, TaskPriority } from "@/types/task";

export const useTasksStore = defineStore("tasks", () => {
  const tasks = ref<Task[]>([]);
  const currentTask = ref<Task | null>(null);
  const total = ref(0);
  const loading = ref(false);

  // Filter / pagination / sort state
  const activeTagFilters = ref<string[]>([]);
  const statusFilter = ref<TaskStatus[]>([]);
  const priorityFilter = ref<TaskPriority[]>([]);
  const limit = ref(20);
  const offset = ref(0);
  const sortField = ref("updated_at");
  const sortOrder = ref<"asc" | "desc">("desc");
  const searchQuery = ref("");

  async function refresh() {
    loading.value = true;
    try {
      const searchParams = new URLSearchParams();
      if (searchQuery.value) searchParams.set("q", searchQuery.value);
      for (const t of activeTagFilters.value) {
        searchParams.append("tag", t);
      }
      for (const s of statusFilter.value) searchParams.append("status", s);
      for (const p of priorityFilter.value) searchParams.append("priority", p);
      searchParams.set("sort", sortField.value);
      searchParams.set("order", sortOrder.value);
      searchParams.set("limit", String(limit.value));
      searchParams.set("offset", String(offset.value));

      const qs = searchParams.toString();
      const data = await apiGet<TaskListResponse>(
        `/api/tasks${qs ? `?${qs}` : ""}`
      );
      tasks.value = data.tasks;
      total.value = data.total;
    } catch (e) {
      useToastStore().show("Failed to load tasks", "error");
      throw e;
    } finally {
      loading.value = false;
    }
  }

  async function fetchTask(id: number) {
    loading.value = true;
    try {
      currentTask.value = await apiGet<Task>(`/api/tasks/${id}`);
    } catch (e) {
      useToastStore().show("Failed to load task", "error");
      throw e;
    } finally {
      loading.value = false;
    }
  }

  async function createTask(data: {
    title: string;
    body: string;
    tags?: string[];
    status?: TaskStatus;
    priority?: TaskPriority;
    due_date?: string | null;
    project_id?: number | null;
    milestone_id?: number | null;
    parent_id?: number | null;
    recurrence_rule?: Record<string, unknown> | null;
  }): Promise<Task> {
    try {
      return await apiPost<Task>("/api/tasks", data);
    } catch (e) {
      useToastStore().show("Failed to create task", "error");
      throw e;
    }
  }

  async function updateTask(
    id: number,
    data: Partial<
      Pick<Task, "title" | "body" | "tags" | "status" | "priority" | "due_date" | "project_id" | "milestone_id" | "parent_id" | "recurrence_rule">
    >
  ): Promise<Task> {
    try {
      const task = await apiPut<Task>(`/api/tasks/${id}`, data);
      if (currentTask.value?.id === id) {
        currentTask.value = task;
      }
      return task;
    } catch (e) {
      useToastStore().show("Failed to update task", "error");
      throw e;
    }
  }

  async function patchStatus(id: number, status: TaskStatus): Promise<Task> {
    try {
      const task = await apiPatch<Task>(`/api/tasks/${id}/status`, { status });
      const idx = tasks.value.findIndex((t) => t.id === id);
      if (idx !== -1) {
        tasks.value[idx] = task;
      }
      if (currentTask.value?.id === id) {
        currentTask.value = task;
      }
      return task;
    } catch (e) {
      useToastStore().show("Failed to update task status", "error");
      throw e;
    }
  }

  async function deleteTask(id: number) {
    try {
      await apiDelete(`/api/tasks/${id}`);
      tasks.value = tasks.value.filter((t) => t.id !== id);
      if (currentTask.value?.id === id) {
        currentTask.value = null;
      }
    } catch (e) {
      useToastStore().show("Failed to delete task", "error");
      throw e;
    }
  }

  function setStatusFilter(statuses: TaskStatus[]) {
    statusFilter.value = statuses;
    offset.value = 0;
    refresh();
  }

  function setPriorityFilter(priorities: TaskPriority[]) {
    priorityFilter.value = priorities;
    offset.value = 0;
    refresh();
  }

  function addTagFilter(tag: string) {
    if (!activeTagFilters.value.includes(tag)) {
      activeTagFilters.value.push(tag);
      offset.value = 0;
      refresh();
    }
  }

  function removeTagFilter(tag: string) {
    activeTagFilters.value = activeTagFilters.value.filter((t) => t !== tag);
    offset.value = 0;
    refresh();
  }

  function clearTagFilters() {
    activeTagFilters.value = [];
    offset.value = 0;
    refresh();
  }

  function setSort(field: string, order: "asc" | "desc") {
    sortField.value = field;
    sortOrder.value = order;
    offset.value = 0;
    refresh();
  }

  function setOffset(newOffset: number) {
    offset.value = newOffset;
    refresh();
  }

  function setSearch(q: string) {
    searchQuery.value = q;
    offset.value = 0;
    refresh();
  }

  return {
    tasks,
    currentTask,
    total,
    loading,
    activeTagFilters,
    statusFilter,
    priorityFilter,
    limit,
    offset,
    sortField,
    sortOrder,
    searchQuery,
    refresh,
    fetchTask,
    createTask,
    updateTask,
    patchStatus,
    deleteTask,
    setStatusFilter,
    setPriorityFilter,
    addTagFilter,
    removeTagFilter,
    clearTagFilters,
    setSort,
    setOffset,
    setSearch,
  };
});
