"use client";

import { useCallback, useEffect, useState } from "react";
import type { Task, TaskInput, TaskSort, TaskStatus, TaskUpdate } from "@/types/task";
import AddTaskForm from "./AddTaskForm";
import Column from "./Column";
import EditTaskForm from "./EditTaskForm";
import TaskCard from "./TaskCard";

type ViewMode = "board" | "list";

type TasksPayload = {
  tasks: Task[];
};

type TaskPayload = {
  task: Task;
};

async function readJson<T>(response: Response): Promise<T> {
  const payload = (await response.json()) as T & { error?: string };

  if (!response.ok) {
    throw new Error(payload.error ?? "Request failed.");
  }

  return payload;
}

export default function Board() {
  const [tasks, setTasks] = useState<Task[]>([]);
  const [sortMode, setSortMode] = useState<TaskSort>("createdAt");
  const [viewMode, setViewMode] = useState<ViewMode>("board");
  const [includeArchived, setIncludeArchived] = useState(false);
  const [showForm, setShowForm] = useState(false);
  const [editingTask, setEditingTask] = useState<Task | null>(null);
  const [popupTask, setPopupTask] = useState<Task | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const loadTasks = useCallback(async () => {
    setIsLoading(true);
    setError(null);

    try {
      const searchParams = new URLSearchParams({
        sort: sortMode,
        includeArchived: String(includeArchived),
      });
      const payload = await readJson<TasksPayload>(
        await fetch(`/api/tasks?${searchParams.toString()}`)
      );

      setTasks(payload.tasks);
    } catch (loadError) {
      setError(
        loadError instanceof Error ? loadError.message : "Tasks could not be loaded."
      );
    } finally {
      setIsLoading(false);
    }
  }, [includeArchived, sortMode]);

  useEffect(() => {
    // Tasks are external server state, so the initial sync starts here.
    // eslint-disable-next-line react-hooks/set-state-in-effect
    void loadTasks();
  }, [loadTasks]);

  const createNewTask = async (task: TaskInput) => {
    await readJson<TaskPayload>(
      await fetch("/api/tasks", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(task),
      })
    );
    await loadTasks();
  };

  const saveTaskChanges = async (id: number, updates: TaskUpdate) => {
    await readJson<TaskPayload>(
      await fetch("/api/tasks", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id, ...updates }),
      })
    );
    await loadTasks();
  };

  const handleStatusChange = async (taskId: number, newStatus: TaskStatus) => {
    try {
      await saveTaskChanges(taskId, { status: newStatus });
    } catch (statusError) {
      setError(
        statusError instanceof Error
          ? statusError.message
          : "Task status could not be changed."
      );
    }
  };

  const handleArchive = async (task: Task) => {
    try {
      await readJson<TaskPayload>(
        await fetch("/api/tasks", {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ id: task.id, action: "archive" }),
        })
      );
      await loadTasks();
    } catch (archiveError) {
      setError(
        archiveError instanceof Error
          ? archiveError.message
          : "Task could not be archived."
      );
    }
  };

  const handleStatusClick = (task: Task) => {
    if (task.status !== "Complete" && !task.archivedAt) {
      setPopupTask(task);
    }
  };

  const handleConfirmStatus = async (yes: boolean) => {
    const task = popupTask;
    setPopupTask(null);

    if (!task || !yes) {
      return;
    }

    if (task.status === "Todo") {
      await handleStatusChange(task.id, "In-Progress");
    } else if (task.status === "In-Progress") {
      await handleStatusChange(task.id, "Complete");
    }
  };

  const renderBoard = () => (
    <div style={styles.board}>
      <Column
        title="Todo"
        tasks={tasks.filter((task) => task.status === "Todo")}
        onAdd={() => setShowForm(true)}
        onArchive={handleArchive}
        onEdit={setEditingTask}
        onStatusClick={handleStatusClick}
      />
      <Column
        title="In-Progress"
        tasks={tasks.filter((task) => task.status === "In-Progress")}
        onArchive={handleArchive}
        onEdit={setEditingTask}
        onStatusClick={handleStatusClick}
      />
      <Column
        title="Complete"
        tasks={tasks.filter((task) => task.status === "Complete")}
        onArchive={handleArchive}
        onEdit={setEditingTask}
        onStatusClick={handleStatusClick}
      />
    </div>
  );

  const renderList = () => (
    <div style={styles.list}>
      {tasks.map((task) => (
        <TaskCard
          key={task.id}
          task={task}
          onArchive={handleArchive}
          onEdit={setEditingTask}
          onStatusClick={handleStatusClick}
        />
      ))}
    </div>
  );

  return (
    <>
      <div style={styles.toolbar}>
        <div style={styles.segmented}>
          <button
            type="button"
            style={viewMode === "board" ? styles.activeSegment : styles.segment}
            onClick={() => setViewMode("board")}
          >
            Board
          </button>
          <button
            type="button"
            style={viewMode === "list" ? styles.activeSegment : styles.segment}
            onClick={() => setViewMode("list")}
          >
            List
          </button>
        </div>

        <label style={styles.controlLabel}>
          Sort
          <select
            value={sortMode}
            onChange={(event) => setSortMode(event.target.value as TaskSort)}
            style={styles.select}
          >
            <option value="createdAt">Newest</option>
            <option value="topic">Topic</option>
            <option value="status">Status</option>
            <option value="dueDate">Due Date</option>
          </select>
        </label>

        <label style={styles.checkboxLabel}>
          <input
            type="checkbox"
            checked={includeArchived}
            onChange={(event) => setIncludeArchived(event.target.checked)}
          />
          Show archived
        </label>

        <button
          type="button"
          style={styles.addButton}
          onClick={() => setShowForm(true)}
        >
          Add Task
        </button>
      </div>

      {error && <div style={styles.error}>{error}</div>}
      {isLoading && <div style={styles.emptyState}>Loading tasks...</div>}
      {!isLoading && tasks.length === 0 && (
        <div style={styles.emptyState}>No tasks yet.</div>
      )}
      {!isLoading && (
        <>{viewMode === "board" ? renderBoard() : renderList()}</>
      )}

      {showForm && (
        <AddTaskForm onSubmit={createNewTask} onClose={() => setShowForm(false)} />
      )}

      {editingTask && (
        <EditTaskForm
          task={editingTask}
          onClose={() => setEditingTask(null)}
          onSubmit={(updates) => saveTaskChanges(editingTask.id, updates)}
        />
      )}

      {popupTask && (
        <div style={styles.overlay}>
          <div style={styles.modal}>
            <h3 style={styles.modalTitle}>
              {popupTask.status === "Todo"
                ? "Are you ready to start the task?"
                : "Have you finished this task?"}
            </h3>
            <div style={styles.actions}>
              <button
                type="button"
                onClick={() => void handleConfirmStatus(true)}
                style={styles.saveButton}
              >
                Yes
              </button>
              <button
                type="button"
                onClick={() => void handleConfirmStatus(false)}
                style={styles.cancelButton}
              >
                No
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

const styles = {
  toolbar: {
    display: "flex",
    alignItems: "center",
    justifyContent: "center",
    gap: "16px",
    flexWrap: "wrap" as const,
    marginBottom: "24px",
  },
  segmented: {
    display: "flex",
    border: "1px solid #bae6fd",
    borderRadius: "8px",
    overflow: "hidden",
    background: "#f8fafc",
  },
  segment: {
    background: "#f8fafc",
    color: "#0f172a",
    border: "none",
    padding: "8px 14px",
    cursor: "pointer",
    fontWeight: "700",
  },
  activeSegment: {
    background: "#0f172a",
    color: "white",
    border: "none",
    padding: "8px 14px",
    cursor: "pointer",
    fontWeight: "700",
  },
  controlLabel: {
    display: "flex",
    alignItems: "center",
    gap: "8px",
    color: "white",
    fontWeight: "700",
  },
  checkboxLabel: {
    display: "flex",
    alignItems: "center",
    gap: "8px",
    color: "white",
    fontWeight: "700",
  },
  select: {
    padding: "8px",
    border: "1px solid #bae6fd",
    borderRadius: "8px",
    color: "#0f172a",
    fontWeight: "700",
  },
  addButton: {
    background: "#0f172a",
    color: "white",
    border: "1px solid #0f172a",
    borderRadius: "8px",
    padding: "8px 14px",
    cursor: "pointer",
    fontWeight: "700",
  },
  board: {
    display: "flex",
    gap: "20px",
    justifyContent: "center",
    alignItems: "stretch",
  },
  list: {
    maxWidth: "760px",
    margin: "0 auto",
  },
  error: {
    maxWidth: "760px",
    margin: "0 auto 16px",
    background: "#fee2e2",
    color: "#991b1b",
    border: "1px solid #fecaca",
    borderRadius: "8px",
    padding: "10px 12px",
    fontWeight: "700",
  },
  emptyState: {
    background: "#f8fafc",
    color: "#0f172a",
    borderRadius: "8px",
    padding: "24px",
    maxWidth: "420px",
    margin: "0 auto",
    textAlign: "center" as const,
    fontWeight: "700",
  },
  overlay: {
    position: "fixed" as const,
    top: 0,
    left: 0,
    width: "100%",
    height: "100%",
    background: "rgba(0,0,0,0.4)",
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    zIndex: 1000,
  },
  modal: {
    background: "#f8fafc",
    padding: "25px",
    borderRadius: "12px",
    boxShadow: "0 10px 25px rgba(0,0,0,0.2)",
    width: "300px",
    textAlign: "center" as const,
  },
  modalTitle: {
    marginBottom: "15px",
    fontSize: "18px",
    fontWeight: "600",
    color: "#0f172a",
  },
  actions: {
    display: "flex",
    justifyContent: "space-between",
    marginTop: "15px",
  },
  saveButton: {
    background: "#0ea5e9",
    color: "white",
    border: "none",
    padding: "8px 16px",
    borderRadius: "8px",
    cursor: "pointer",
    fontWeight: "600",
  },
  cancelButton: {
    background: "#e2e8f0",
    color: "#0f172a",
    border: "none",
    padding: "8px 16px",
    borderRadius: "8px",
    cursor: "pointer",
    fontWeight: "600",
  },
};
