"use client";

import { useEffect, useMemo, useState } from "react";
import { Sparkles, Trophy, X } from "lucide-react";
import { ConfirmModal } from "@/components/confirm-modal/confirm-modal";
import { DailyMoodBanner } from "@/features/mood/components/daily-mood-banner";
import { DailyMoodSheet } from "@/features/mood/components/daily-mood-sheet";
import {
  useDailyMood,
  useUpsertDailyMoodMutation,
} from "@/features/mood/hooks/use-mood";
import { HabitLogSheet } from "@/features/habits/components/habit-log-sheet";
import { HabitSheet } from "@/features/habits/components/habit-sheet";
import {
  useCreateHabitLogMutation,
  useCreateHabitMutation,
  useHabitLogs,
  useHabitsCalendar,
  useUpdateHabitLogMutation,
} from "@/features/habits/hooks/use-habits";
import type { HabitFormValues } from "@/features/habits/types";
import {
  formValuesToPayload,
  isQuantitativeHabit,
  logFormToPayload,
  logFormToUpdatePayload,
  normalizeLocalDate,
} from "@/features/habits/utils/habit-helpers";
import { useBooleanHabitToggle } from "@/features/tasks/hooks/use-boolean-habit-toggle";
import { CalendarCarousel } from "@/features/tasks/components/calendar-carousel";
import { TaskCalendarSheet } from "@/features/tasks/components/task-calendar-sheet";
import { TaskCard } from "@/features/tasks/components/task-card";
import { TaskHabitCard } from "@/features/tasks/components/task-habit-card";
import {
  TaskCreatePickerSheet,
  type CreateItemChoice,
} from "@/features/tasks/components/task-create-picker-sheet";
import { TaskSheet } from "@/features/tasks/components/task-sheet";
import { TasksFab } from "@/features/tasks/components/tasks-fab";
import { TasksHeader } from "@/features/tasks/components/tasks-header";
import { tasksDict } from "@/features/tasks/dict";
import {
  useCreateTaskMutation,
  useDeleteTaskMutation,
  useTasks,
  useToggleTaskCompletionMutation,
  useUpdateTaskMutation,
} from "@/features/tasks/hooks/use-tasks";
import type { Task, TaskFormValues } from "@/features/tasks/types";
import { selectionToPayload } from "@/features/categories/utils/category-helpers";
import {
  filterTasksByDay,
  formatProgressLabel,
  getDaysWithTasks,
  getHabitSectionTitle,
  getNextTaskStatus,
  getSectionTitle,
  getTaskProgress,
} from "@/features/tasks/utils/task-helpers";
import {
  getCalendarRangeBounds,
  getCombinedDayProgress,
  getDaysWithScheduledHabits,
  getScheduledHabitsForDay,
  type ScheduledHabitForDay,
} from "@/features/tasks/utils/habit-calendar-helpers";
import {
  combineDateAndTime,
  generateCalendarDays,
  getJalaliDayNumber,
  getToday,
  isToday,
  isFutureDay,
  type JalaliDay,
} from "@/features/tasks/utils/jalali";

export function TasksPageContent() {
  const [selectedDay, setSelectedDay] = useState<JalaliDay>(() => getToday());
  const [calendarCenter, setCalendarCenter] = useState<JalaliDay>(() =>
    getToday(),
  );
  const [calendarOpen, setCalendarOpen] = useState(false);
  const [pickerOpen, setPickerOpen] = useState(false);
  const [sheetOpen, setSheetOpen] = useState(false);
  const [habitSheetOpen, setHabitSheetOpen] = useState(false);
  const [habitLogOpen, setHabitLogOpen] = useState(false);
  const [activeHabitLogItem, setActiveHabitLogItem] =
    useState<ScheduledHabitForDay | null>(null);
  const [sheetMode, setSheetMode] = useState<"create" | "edit">("create");
  const [activeTask, setActiveTask] = useState<Task | null>(null);
  const [taskToDelete, setTaskToDelete] = useState<Task | null>(null);
  const [moodSheetOpen, setMoodSheetOpen] = useState(false);
  const [achievementOpen, setAchievementOpen] = useState(false);

  const todayKey = getToday().format("YYYY-MM-DD");
  const showMoodBanner = isToday(selectedDay);
  const {
    data: dailyMood,
    isLoading: isLoadingMood,
    refetch: refetchDailyMood,
  } = useDailyMood(showMoodBanner ? todayKey : "");
  const upsertDailyMoodMutation = useUpsertDailyMoodMutation(todayKey);

  const { data: tasks = [], isLoading } = useTasks();
  const createTaskMutation = useCreateTaskMutation();
  const createHabitMutation = useCreateHabitMutation();
  const createHabitLogMutation = useCreateHabitLogMutation();
  const updateHabitLogMutation = useUpdateHabitLogMutation();
  const updateTaskMutation = useUpdateTaskMutation();
  const deleteTaskMutation = useDeleteTaskMutation();
  const toggleTaskMutation = useToggleTaskCompletionMutation();

  const calendarDays = useMemo(
    () => generateCalendarDays(calendarCenter, 30),
    [calendarCenter],
  );

  const { fromDate, toDate } = useMemo(
    () => getCalendarRangeBounds(calendarDays),
    [calendarDays],
  );

  const { data: habitsCalendar = [], isLoading: isLoadingHabitsCalendar } =
    useHabitsCalendar(fromDate, toDate);

  const activeHabitLogId = activeHabitLogItem?.habit.id ?? "";
  const { data: activeHabitLogs = [] } = useHabitLogs(activeHabitLogId);

  const dayTasks = useMemo(
    () => filterTasksByDay(tasks, selectedDay),
    [tasks, selectedDay],
  );

  const scheduledHabits = useMemo(
    () => getScheduledHabitsForDay(habitsCalendar, selectedDay),
    [habitsCalendar, selectedDay],
  );

  const taskProgress = getTaskProgress(dayTasks);

  const daysWithTasks = useMemo(
    () => getDaysWithTasks(tasks, calendarDays),
    [tasks, calendarDays],
  );

  const daysWithHabits = useMemo(
    () => getDaysWithScheduledHabits(habitsCalendar, calendarDays),
    [habitsCalendar, calendarDays],
  );

  const selectedDayKey = selectedDay.format("YYYY-MM-DD");
  const { getDisplayDayReport, toggleBooleanHabit } = useBooleanHabitToggle({
    localDate: selectedDayKey,
  });

  const scheduledHabitsForDisplay = useMemo(
    () =>
      scheduledHabits.map((item) => ({
        ...item,
        dayReport: getDisplayDayReport(item),
      })),
    [scheduledHabits, getDisplayDayReport],
  );

  const combinedProgress = getCombinedDayProgress(
    taskProgress.completed,
    taskProgress.total,
    scheduledHabitsForDisplay,
  );
  const activeHabitLog = useMemo(
    () =>
      activeHabitLogs.find(
        (log) => normalizeLocalDate(log.localDate) === selectedDayKey,
      ) ?? null,
    [activeHabitLogs, selectedDayKey],
  );

  const handleSelectDay = (day: JalaliDay) => {
    setSelectedDay(day);

    const dayKey = day.format("YYYY-MM-DD");
    const inRange = calendarDays.some(
      (item) => item.format("YYYY-MM-DD") === dayKey,
    );

    if (!inRange) {
      setCalendarCenter(day);
    }
  };

  const handleCalendarSelect = (day: JalaliDay) => {
    setSelectedDay(day);
    setCalendarCenter(day);
    setCalendarOpen(false);
  };

  const openCreatePicker = () => {
    setPickerOpen(true);
  };

  const closeCreatePicker = () => {
    setPickerOpen(false);
  };

  const openCreateSheet = () => {
    setSheetMode("create");
    setActiveTask(null);
    setSheetOpen(true);
  };

  const openCreateHabitSheet = () => {
    setHabitSheetOpen(true);
  };

  const closeHabitSheet = () => {
    setHabitSheetOpen(false);
  };

  const handleCreatePickerSelect = (choice: CreateItemChoice) => {
    if (choice === "task") {
      openCreateSheet();
      return;
    }

    openCreateHabitSheet();
  };

  const handleHabitSubmit = (values: HabitFormValues) => {
    createHabitMutation.mutate(formValuesToPayload(values), {
      onSuccess: () => {
        closeHabitSheet();
      },
    });
  };

  const openHabitLogSheet = (item: ScheduledHabitForDay) => {
    if (!isQuantitativeHabit(item.habit)) {
      return;
    }

    setActiveHabitLogItem(item);
    setHabitLogOpen(true);
  };

  const closeHabitLogSheet = () => {
    setHabitLogOpen(false);
    setActiveHabitLogItem(null);
  };

  const handleHabitLogSubmit = (
    payload:
      | ReturnType<typeof logFormToPayload>
      | ReturnType<typeof logFormToUpdatePayload>,
  ) => {
    if (!activeHabitLogItem) {
      return;
    }

    const habitId = activeHabitLogItem.habit.id;

    if (activeHabitLog) {
      updateHabitLogMutation.mutate(
        {
          habitId,
          logId: activeHabitLog.id,
          payload: payload as ReturnType<typeof logFormToUpdatePayload>,
        },
        {
          onSuccess: () => {
            closeHabitLogSheet();
            if (activeHabitLog?.status === "COMPLETED") {
              openTrophyModal();
            }
          },
        },
      );
      return;
    }

    createHabitLogMutation.mutate(
      { habitId, payload: payload as ReturnType<typeof logFormToPayload> },
      {
        onSuccess: () => {
          closeHabitLogSheet();
        },
      },
    );
  };

  const openEditSheet = (task: Task) => {
    setSheetMode("edit");
    setActiveTask(task);
    setSheetOpen(true);
  };

  const closeSheet = () => {
    setSheetOpen(false);
    setActiveTask(null);
  };

  const handleSubmit = (values: TaskFormValues) => {
    const scheduledDate = combineDateAndTime(selectedDay, values.time);
    const payload = {
      title: values.title.trim(),
      description: values.description.trim() || undefined,
      scheduledDate,
      dueDate: scheduledDate,
      isUrgent: values.isUrgent,
      isImportant: values.isImportant,
      ...selectionToPayload(values.category),
    };

    if (sheetMode === "create") {
      createTaskMutation.mutate(payload, {
        onSuccess: () => closeSheet(),
      });
      return;
    }

    if (!activeTask) {
      return;
    }

    updateTaskMutation.mutate(
      { id: activeTask.id, payload },
      { onSuccess: () => closeSheet() },
    );
  };

  const handleDeleteRequest = (task: Task) => {
    setTaskToDelete(task);
  };

  const handleConfirmDelete = () => {
    if (!taskToDelete) {
      return;
    }

    deleteTaskMutation.mutate(taskToDelete.id, {
      onSuccess: () => {
        setTaskToDelete(null);
        if (activeTask?.id === taskToDelete.id) {
          closeSheet();
        }
      },
    });
  };

  const handleToggleComplete = (task: Task) => {
    const nextStatus = getNextTaskStatus(task.status);

    toggleTaskMutation.mutate(
      {
        id: task.id,
        status: nextStatus,
      },
      {
        onSuccess: () => {
          if (nextStatus !== "COMPLETED") {
            return;
          }
          openTrophyModal();
        },
      },
    );
  };

  const openTrophyModal = () => {
    const todayKey = getToday().format("YYYY-MM-DD");
    const achievementKey = "tasks:first-completion-achievement";

    try {
      if (window.localStorage.getItem(achievementKey) === todayKey) {
        return;
      }

      window.localStorage.setItem(achievementKey, todayKey);
      setAchievementOpen(true);
    } catch {
      // Showing the achievement should never interrupt task completion.
    }
  };

  useEffect(() => {
    if (!achievementOpen) {
      return;
    }

    const timeoutId = window.setTimeout(() => {
      setAchievementOpen(false);
    }, 3600);

    return () => window.clearTimeout(timeoutId);
  }, [achievementOpen]);

  const isFutureSelectedDay = isFutureDay(selectedDay);

  const habitSectionTitle = getHabitSectionTitle(
    isToday(selectedDay),
    getJalaliDayNumber(selectedDay),
  );

  const sectionTitle = getSectionTitle(
    isToday(selectedDay),
    getJalaliDayNumber(selectedDay),
  );

  const isLoadingContent = isLoading || isLoadingHabitsCalendar;
  const hasHabits = scheduledHabits.length > 0;
  const hasTasks = dayTasks.length > 0;
  const isDayEmpty = !hasHabits && !hasTasks;

  const deleteDescription = useMemo(() => {
    if (!taskToDelete) {
      return "";
    }

    return tasksDict.deleteConfirmDescription.replace(
      "{title}",
      taskToDelete.title,
    );
  }, [taskToDelete]);

  return (
    <div className="mx-auto flex w-full min-w-0 max-w-3xl flex-1 flex-col overflow-x-hidden pb-8">
      <TasksHeader onOpenCalendar={() => setCalendarOpen(true)} />

      <div className="w-full min-w-0 max-w-full overflow-x-clip">
        <CalendarCarousel
          days={calendarDays}
          selectedDay={selectedDay}
          daysWithTasks={daysWithTasks}
          daysWithHabits={daysWithHabits}
          onSelectDay={handleSelectDay}
        />
      </div>

      <section className="mt-6 px-4 sm:px-6">
        {showMoodBanner ? (
          <DailyMoodBanner
            entry={dailyMood}
            isLoading={isLoadingMood}
            onClick={() => {
              void refetchDailyMood();
              setMoodSheetOpen(true);
            }}
          />
        ) : null}

        <div className="mb-4 flex items-center justify-between gap-3">
          <h2 className="text-lg font-bold text-[#1D2D50] dark:text-foreground sm:text-xl">
            {hasHabits && !hasTasks ? habitSectionTitle : sectionTitle}
          </h2>
          <span className="text-sm font-semibold text-[#2EC4B6]">
            {formatProgressLabel(
              combinedProgress.completed,
              combinedProgress.total,
            )}
          </span>
        </div>

        <div className="space-y-3">
          {isLoadingContent ? (
            <div className="rounded-[1.75rem] bg-card px-5 py-8 text-center text-sm text-muted-foreground shadow-soft-sm">
              در حال بارگذاری...
            </div>
          ) : isDayEmpty ? (
            <div className="rounded-[1.75rem] bg-card px-5 py-8 text-center text-sm text-muted-foreground shadow-soft-sm">
              {tasksDict.dayEmpty}
            </div>
          ) : (
            <div className="space-y-3">
              {scheduledHabitsForDisplay.map((item) => (
                <TaskHabitCard
                  key={item.habit.id}
                  item={item}
                  isFutureDay={isFutureSelectedDay}
                  onLog={openHabitLogSheet}
                  onToggle={() => toggleBooleanHabit(item, openTrophyModal)}
                  isLogPending={
                    createHabitLogMutation.isPending ||
                    updateHabitLogMutation.isPending
                  }
                />
              ))}
              {dayTasks.map((task) => (
                <TaskCard
                  key={task.id}
                  task={task}
                  onToggleComplete={handleToggleComplete}
                  onEdit={openEditSheet}
                  onDelete={handleDeleteRequest}
                  isFutureDay={isFutureSelectedDay}
                  isTogglePending={toggleTaskMutation.isPending}
                />
              ))}
            </div>
          )}
        </div>
      </section>

      <TasksFab onClick={openCreatePicker} />

      <TaskCreatePickerSheet
        open={pickerOpen}
        onClose={closeCreatePicker}
        onSelect={handleCreatePickerSelect}
      />

      <TaskCalendarSheet
        open={calendarOpen}
        selectedDay={selectedDay}
        onClose={() => setCalendarOpen(false)}
        onSelectDay={handleCalendarSelect}
      />

      <TaskSheet
        open={sheetOpen}
        mode={sheetMode}
        selectedDay={selectedDay}
        task={activeTask}
        isSubmitting={
          createTaskMutation.isPending || updateTaskMutation.isPending
        }
        isDeleting={deleteTaskMutation.isPending}
        onClose={closeSheet}
        onSubmit={handleSubmit}
        onDelete={
          sheetMode === "edit" && activeTask
            ? () => handleDeleteRequest(activeTask)
            : undefined
        }
      />

      <HabitSheet
        open={habitSheetOpen}
        mode="create"
        habit={null}
        isSubmitting={createHabitMutation.isPending}
        onClose={closeHabitSheet}
        onSubmit={handleHabitSubmit}
      />

      <HabitLogSheet
        open={habitLogOpen}
        mode={activeHabitLog ? "edit" : "create"}
        habit={activeHabitLogItem?.habit ?? null}
        log={activeHabitLog}
        existingLogs={activeHabitLogs}
        initialLocalDate={selectedDayKey}
        lockLocalDate
        isSubmitting={
          createHabitLogMutation.isPending || updateHabitLogMutation.isPending
        }
        onClose={closeHabitLogSheet}
        onSubmit={handleHabitLogSubmit}
      />

      <ConfirmModal
        open={Boolean(taskToDelete)}
        title={tasksDict.deleteConfirmTitle}
        description={deleteDescription}
        confirmLabel={tasksDict.delete}
        cancelLabel={tasksDict.cancel}
        isConfirming={deleteTaskMutation.isPending}
        onConfirm={handleConfirmDelete}
        onCancel={() => setTaskToDelete(null)}
      />

      {achievementOpen ? (
        <div
          className="fixed inset-0 z-[120] flex items-center justify-center bg-[#1D2D50]/35 p-4 backdrop-blur-[2px]"
          role="status"
          aria-live="polite"
        >
          <div className="relative w-full max-w-sm overflow-hidden rounded-[2rem] bg-card px-6 py-8 text-center shadow-soft">
            <button
              type="button"
              aria-label="بستن"
              onClick={() => setAchievementOpen(false)}
              className="absolute end-4 top-4 rounded-full p-2 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
            >
              <X className="size-5" />
            </button>

            <div className="pointer-events-none absolute -inset-12 animate-pulse bg-[radial-gradient(circle_at_center,rgba(242,153,74,0.2),transparent_58%)]" />
            <div className="relative mx-auto flex size-28 animate-bounce items-center justify-center rounded-full bg-gradient-to-br from-[#F2994A] to-[#F2C94C] text-white shadow-[0_12px_30px_rgba(242,153,74,0.35)]">
              <Trophy className="size-14" strokeWidth={1.7} />
              <Sparkles className="absolute -right-2 -top-1 size-8 text-[#F2C94C]" />
              <Sparkles className="absolute -bottom-1 -left-2 size-6 text-[#F2994A]" />
            </div>

            <h2 className="relative mt-6 text-2xl font-black text-[#1D2D50] dark:text-foreground">
              آفرین!
            </h2>
            <p className="relative mt-2 text-sm leading-7 text-muted-foreground">
              اولین وظیفه امروزت را انجام دادی
            </p>
          </div>
        </div>
      ) : null}

      <DailyMoodSheet
        open={moodSheetOpen}
        localDate={todayKey}
        entry={dailyMood}
        isLoadingEntry={
          moodSheetOpen && isLoadingMood && dailyMood === undefined
        }
        isSubmitting={upsertDailyMoodMutation.isPending}
        onClose={() => setMoodSheetOpen(false)}
        onSubmit={(payload) =>
          upsertDailyMoodMutation.mutate(payload, {
            onSuccess: () => setMoodSheetOpen(false),
          })
        }
      />
    </div>
  );
}
