/**
 * api.js
 *
 * Powers the Dashboard page. Talks to the Express / Mongoose backend
 * at http://localhost:3001 to create, read, update and delete tasks.
 *
 * Core CRUD (original):
 *   - displayTasks()       GET    /api/tasks
 *   - createNewTask()      POST   /api/tasks/todo
 *   - completeTask()       PATCH  /api/tasks/complete/:id
 *   - taskNotCompleted()   PATCH  /api/tasks/notComplete/:id
 *   - deleteTask()         DELETE /api/tasks/delete/:id
 *   - editTask()           PUT    /api/tasks/update/:id
 *
 * Added interactivity:
 *   - Stats cards: renders live counts of Active, Completed, Overdue
 *     and Due-Today tasks (see updateStats()).
 *   - Search filter: an input box filters the rendered task lists by
 *     title/description on every keystroke, without re-hitting the
 *     API (see renderTasks()).
 *   - Quick-pick date buttons: "Today", "Tomorrow" and "Next week"
 *     populate the due-date field of the new-task form.
 *
 * The in-memory `allTasks` array holds the latest fetched list so
 * search filtering can be recomputed purely on the client side.
 */

const taskForm = document.getElementById('taskForm');
const toDoList = document.getElementById('toDoList');
const completedList = document.getElementById('completedList');
const toDoEmpty = document.getElementById('toDoEmpty');
const completedEmpty = document.getElementById('completedEmpty');
const searchInput = document.getElementById('searchInput');
const dueDateInput = document.getElementById('dueDate');
const url = "http://localhost:3001";

// Cache of the most recent /api/tasks response so the search filter
// can re-render instantly without refetching.
let allTasks = [];

function resetForm() {
  taskForm.reset();
}

const sortButton = document.getElementById("sortSelect");
window.addEventListener("DOMContentLoaded", () => {
  sortButton.value = "default";
});
sortButton.addEventListener('change', () => {
  displayTasks();
});

// Search filter: re-renders the two lists on every keystroke using
// the cached `allTasks` array. No API round-trip required.
if (searchInput) {
  searchInput.addEventListener('input', () => {
    renderTasks();
  });
}

// Quick-pick date buttons: set the due-date input to today, tomorrow
// or a week from now. Saves the user from having to open the date
// picker for the most common options.
document.querySelectorAll('.quick-date-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    const offsetDays = { today: 0, tomorrow: 1, nextWeek: 7 }[btn.dataset.quick] ?? 0;
    const date = new Date();
    date.setDate(date.getDate() + offsetDays);
    dueDateInput.value = date.toISOString().split('T')[0];
  });
});

window.addEventListener("DOMContentLoaded", () => {
  displayTasks();
});


taskForm.addEventListener("submit", (event) => {
  event.preventDefault();
  createNewTask();
});

[toDoList, completedList].forEach(list => {
  list.addEventListener('click', (event) => {
    if (event.target.classList.contains("done")) {
      const taskId = event.target.getAttribute("data-id");
      completeTask(taskId);
    }
    else if (event.target.classList.contains("notDone")) {
      const taskId = event.target.getAttribute("data-id");
      taskNotCompleted(taskId);
    }

    else if (event.target.classList.contains("delete")) {
      const taskId = event.target.getAttribute("data-id");
      deleteTask(taskId);
    }
    else if (event.target.classList.contains('edit')) {
      const task = {
        id: event.target.getAttribute('data-id'),
        title: event.target.getAttribute('data-title'),
        description: event.target.getAttribute('data-description'),
        dueDate: new Date(event.target.getAttribute('data-due-date'))
      };
      const modal = {
        titleInput: document.getElementById('editTaskName'),
        descriptionInput: document.getElementById('editTaskDescription'),
        dueDateInput: document.getElementById('editDueDate'),
        saveButton: document.getElementById('saveButton')
      };
      modal.titleInput.value = task.title;
      modal.descriptionInput.value = task.description;
      modal.dueDateInput.value = task.dueDate.toISOString().split('T')[0];
      modal.saveButton.addEventListener('click', async () => {
        await editTask(task.id);
        bootstrap.Modal.getInstance(document.getElementById('editModal')).hide();
      }, { once: true });
    }
  });
});


async function displayTasks() {
  const sortSelect = document.getElementById('sortSelect');
  const sortBy = sortSelect.value;
  let query = '';
  if (sortBy !== 'default') {
    query = `?sortBy=${sortBy}`;
  }
  try {
    const response = await fetch(`${url}/api/tasks${query}`);
    if (!response.ok) {
      throw new Error(`Failed to get tasks: ${response.status}`);
    }
    allTasks = await response.json();
    updateStats(allTasks);
    renderTasks();
    resetForm();
  } catch (error) {
    console.error("Error: ", error);
  }
}

function formatTask(task) {
  const li = document.createElement("li");
  li.classList.add("card", "p-3", "shadow-sm", "mt-2");
  const done = task.completed ? "text-decoration-line-through opacity-50" : "";
  li.innerHTML = `
    <div class="d-flex justify-content-between align-items-start">
      <h4 class="${done} col-11">${task.title}</h4>
      <button data-id="${task._id}" type="button" class="btn-close delete" aria-label="Close"></button>
    </div>
    <p class="${done}">${task.description}</p>
    <p class="${done}"><strong>Due: </strong>${new Date(task.dueDate).toLocaleDateString()}</p>
    <div class="d-flex justify-content-between align-items-end">
      <div>
        ${task.completed ?
      `<button data-id="${task._id}" class="btn btn-primary shadow-sm notDone" type="button">Not done</button>`
      :
      `
            <button data-bs-toggle="modal" data-bs-target="#editModal" data-title="${task.title}" data-description="${task.description}" data-due-date="${task.dueDate}" data-id="${task._id}" class="btn btn-primary shadow-sm edit" type="button">Edit</button>
            <button data-id="${task._id}" class="btn btn-primary shadow-sm done" type="button">Done</button>
          `
    }
      </div>
      <p class="m-0 ${done}"><strong>Created on: </strong>${new Date(task.dateCreated).toLocaleDateString()}</p>
    </div>
  `;
  return li;
}

/**
 * Render the cached task list into the To-Do and Completed columns.
 * Applies the current search term (if any) as a case-insensitive
 * match on title or description, and toggles per-column empty-state
 * messages when nothing matches.
 */
function renderTasks() {
  const term = (searchInput?.value || '').trim().toLowerCase();
  const filtered = term
    ? allTasks.filter(t =>
        t.title.toLowerCase().includes(term) ||
        t.description.toLowerCase().includes(term))
    : allTasks;

  toDoList.innerHTML = '';
  completedList.innerHTML = '';

  let activeCount = 0;
  let completedCount = 0;

  filtered.forEach(task => {
    const node = formatTask(task);
    if (task.completed) {
      completedList.appendChild(node);
      completedCount += 1;
    } else {
      toDoList.appendChild(node);
      activeCount += 1;
    }
  });

  toDoEmpty?.classList.toggle('d-none', activeCount > 0);
  completedEmpty?.classList.toggle('d-none', completedCount > 0);
}

/**
 * Recompute and display the four dashboard stat cards.
 *
 *   Active     - tasks that are not yet completed
 *   Completed  - tasks marked done
 *   Overdue    - active tasks whose due date is before today
 *   Due Today  - active tasks whose due date is today
 *
 * Dates are normalised to midnight so the comparison ignores time
 * of day.
 */
function updateStats(tasks) {
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  let active = 0, completed = 0, overdue = 0, dueToday = 0;

  tasks.forEach(task => {
    const due = new Date(task.dueDate);
    due.setHours(0, 0, 0, 0);

    if (task.completed) {
      completed += 1;
    } else {
      active += 1;
      if (due.getTime() < today.getTime()) {
        overdue += 1;
      } else if (due.getTime() === today.getTime()) {
        dueToday += 1;
      }
    }
  });

  const set = (id, value) => {
    const el = document.getElementById(id);
    if (el) el.textContent = value;
  };
  set('statActive', active);
  set('statCompleted', completed);
  set('statOverdue', overdue);
  set('statDueToday', dueToday);
}
async function createNewTask() {

  const taskDetails = {
    title: taskForm.taskName.value.trim(),
    description: taskForm.taskDescription.value.trim(),
    dueDate: taskForm.dueDate.value
  }
  if (!taskDetails.title || !taskDetails.description || !taskDetails.dueDate) {
    return alert("All fields required!");
  }
  try {
    const response = await fetch(`${url}/api/tasks/todo`, {
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(taskDetails)
    });
    if (!response.ok) {
      throw new Error(`Failed to post task: ${response.status}`);
    }
    const data = await response.json();
    console.log(data);
    displayTasks();
  } catch (error) {
    console.error("Error:", error);
  }
}
async function completeTask(taskId) {
  try {
    const response = await fetch(`${url}/api/tasks/complete/${taskId}`, {
      method: "PATCH",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ completed: true })
    });
    if (!response.ok) {
      throw new Error(`Failed to complete task: ${response.status}`);
    }
    const data = await response.json();
    console.log("Task completed:", data);
    displayTasks();
  }
  catch (error) {
    console.error("Error:", error);
  }
};
async function taskNotCompleted(taskId) {
  try {
    const response = await fetch(`${url}/api/tasks/notComplete/${taskId}`, {
      method: "PATCH",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify({ completed: false })
    });
    if (!response.ok) {
      throw new Error(`Failed to make task incomplete: ${response.status}`);
    }
    const data = await response.json();
    console.log("Task not complete:", data);
    displayTasks();

  } catch (error) {
    console.error("Error:", error);
  }
};
async function deleteTask(taskId) {
  try {
    const response = await fetch(`${url}/api/tasks/delete/${taskId}`, {
      method: "DELETE",
      headers: {
        "Content-Type": "application/json"
      }
    });
    if (!response.ok) {
      throw new Error(`Failed to delete task: ${response.status}`);
    }
    const data = await response.json();
    console.log({ message: "Deleted Task:", Task: data });
    displayTasks();

  } catch (error) {
    console.error("Error:", error);
  }
};
async function editTask(taskId) {
  const updatedDetails = {
    title: document.getElementById('editTaskName').value.trim(),
    description: document.getElementById('editTaskDescription').value.trim(),
    dueDate: document.getElementById('editDueDate').value
  };
  if (!updatedDetails.title || !updatedDetails.description || !updatedDetails.dueDate) {
    return alert("All fields required!");
  }

  try {
    const response = await fetch(`${url}/api/tasks/update/${taskId}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json"
      },
      body: JSON.stringify(updatedDetails)
    });
    if (!response.ok) {
      throw new Error(`Failed to edit task: ${response.status}`);
    }
    const data = await response.json();
    console.log("Edited Task:", data);
    displayTasks();
  } catch (error) {
    console.error("Error:", error);
  }
};
