"use client";

import * as React from "react";
import dynamic from "next/dynamic";
import { useSession } from "next-auth/react";
import { CalendarDays, RefreshCw } from "lucide-react";
import {
  CALENDAR_EVENT_SOURCE_TYPES,
  useGetCalendarEventsQuery,
  type CalendarEvent,
  type CalendarEventSourceType,
} from "@/api/rtk/calendar-api";
import { useGetTaskQuery } from "@/api/rtk";
import type { Deal } from "@/api/rtk/deals-api";
import { CalendarEventFilters } from "@/components/calendar/calendar-event-filters";
import { CalendarEventDetail } from "@/components/calendar/calendar-event-detail";
import { TaskViewModal } from "@/components/tasks/task-view-modal";
import { QaVerifyLeadViewDialog } from "@/components/qa-verify/qa-verify-lead-view-dialog";
import { Button } from "@/components/ui/button";
import { APILoader } from "@/components/shadix-ui/components/loader";
import { useAuthToken } from "@/hooks/use-auth-token";
import {
  canAccessResource,
  canVerifyClientMeetingVerification,
  hasFullCalendarVisibility,
  type PermissionSource,
} from "@/lib/permissions";
import { useGetProfileQuery } from "@/api/rtk/auth-api";

const CalendarBoard = dynamic(
  () =>
    import("@/components/calendar/calendar-board").then(
      (mod) => mod.CalendarBoard,
    ),
  {
    ssr: false,
    loading: () => (
      <div className="flex min-h-[480px] items-center justify-center rounded-xl border bg-card">
        <APILoader />
      </div>
    ),
  },
);

function defaultEnabledTypes(): CalendarEventSourceType[] {
  return [...CALENDAR_EVENT_SOURCE_TYPES];
}

function apiEventTypes(showTaskFilters: boolean): CalendarEventSourceType[] {
  const types: CalendarEventSourceType[] = [
    "qa_meeting",
    "deal_reminder",
    "milestone",
  ];
  if (showTaskFilters) {
    types.unshift("task_due", "task_reminder");
  }
  return types;
}

export default function CalendarPage() {
  const { token } = useAuthToken();
  const { data: session } = useSession();
  const { data: profile } = useGetProfileQuery(undefined, { skip: !token });

  const permissionSource = React.useMemo<PermissionSource>(() => {
    const backendUser = session?.backendUser;
    if (
      backendUser &&
      (backendUser.role?.permissions || backendUser.customPermissions)
    ) {
      return backendUser;
    }
    return profile ?? backendUser ?? null;
  }, [session?.backendUser, profile]);

  const [range, setRange] = React.useState<{ start: string; end: string } | null>(
    null,
  );
  const [enabledTypes, setEnabledTypes] = React.useState<CalendarEventSourceType[]>(
    defaultEnabledTypes,
  );
  const [selectedEvent, setSelectedEvent] = React.useState<CalendarEvent | null>(
    null,
  );
  const [detailOpen, setDetailOpen] = React.useState(false);
  const [taskId, setTaskId] = React.useState<string | null>(null);
  const [qaLead, setQaLead] = React.useState<Deal | null>(null);

  const showQaFilter =
    canVerifyClientMeetingVerification(permissionSource) ||
    hasFullCalendarVisibility(permissionSource);
  const showTaskFilters =
    canAccessResource(permissionSource, "task") ||
    hasFullCalendarVisibility(permissionSource);

  const hiddenFilterTypes = React.useMemo(() => {
    const hidden: CalendarEventSourceType[] = [];
    if (!showTaskFilters) {
      hidden.push("task_due", "task_reminder");
    }
    if (!showQaFilter) {
      hidden.push("qa_meeting");
    }
    return hidden;
  }, [showQaFilter, showTaskFilters]);

  const requestTypes = React.useMemo(
    () => apiEventTypes(showTaskFilters),
    [showTaskFilters],
  );

  const activeTypes = React.useMemo(
    () => enabledTypes.filter((type) => requestTypes.includes(type)),
    [enabledTypes, requestTypes],
  );

  const {
    data: events = [],
    isLoading,
    isFetching,
    refetch,
  } = useGetCalendarEventsQuery(
    {
      start: range?.start ?? new Date().toISOString(),
      end:
        range?.end ??
        new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(),
      types: requestTypes,
    },
    { skip: !token || !range || requestTypes.length === 0 },
  );

  const visibleEvents = React.useMemo(
    () =>
      events.filter((event) =>
        activeTypes.includes(event.extendedProps.sourceType),
      ),
    [events, activeTypes],
  );

  const { data: selectedTask } = useGetTaskQuery(taskId ?? "", {
    skip: !taskId,
  });

  const handleDatesChange = React.useCallback((start: string, end: string) => {
    setRange((prev) => {
      if (prev?.start === start && prev?.end === end) return prev;
      return { start, end };
    });
  }, []);

  const handleToggleType = React.useCallback((type: CalendarEventSourceType) => {
    setEnabledTypes((prev) =>
      prev.includes(type) ? prev.filter((t) => t !== type) : [...prev, type],
    );
  }, []);

  const handleEventClick = React.useCallback((event: CalendarEvent) => {
    const sourceType = event.extendedProps.sourceType;
    const resourceId = event.extendedProps.resourceId;

    if (sourceType === "task_due" || sourceType === "task_reminder") {
      setTaskId(resourceId);
      return;
    }

    if (sourceType === "qa_meeting") {
      const leadId = event.extendedProps.dealId ?? resourceId;
      setQaLead({
        id: leadId,
        customerName: event.extendedProps.customerName,
      } as Deal);
      return;
    }

    setSelectedEvent(event);
    setDetailOpen(true);
  }, []);

  return (
    <div className="flex flex-col gap-6 p-4 md:p-6">
      <div className="flex flex-wrap items-start justify-between gap-4">
        <div>
          <div className="flex items-center gap-2">
            <CalendarDays className="size-6 text-[#1d1d39]" />
            <h1 className="font-['Lexend'] text-2xl font-bold text-[#101828]">
              Calendar
            </h1>
          </div>
          <p className="mt-1 text-sm text-muted-foreground">
            Tasks, QA discovery meetings, deal reminders, and payment milestones
            in one view.
          </p>
        </div>
        <Button
          type="button"
          variant="outline"
          size="sm"
          onClick={() => void refetch()}
          disabled={isFetching}
        >
          <RefreshCw
            className={isFetching ? "mr-2 size-4 animate-spin" : "mr-2 size-4"}
          />
          Refresh
        </Button>
      </div>

      <div className="overflow-hidden rounded-xl border bg-card shadow-sm">
        <div className="border-b bg-muted/30 px-4 py-3">
          <h2 className="text-sm font-semibold text-foreground">Filters</h2>
          <p className="mt-0.5 text-xs text-muted-foreground">
            Choose which event types appear on the calendar.
          </p>
        </div>
        <div className="p-4">
          <CalendarEventFilters
            enabledTypes={activeTypes}
            onToggle={handleToggleType}
            onSelectAll={() =>
              setEnabledTypes(
                CALENDAR_EVENT_SOURCE_TYPES.filter(
                  (type) => !hiddenFilterTypes.includes(type),
                ),
              )
            }
            onClearAll={() => setEnabledTypes([])}
            hiddenTypes={hiddenFilterTypes}
          />
        </div>
      </div>

      <div className="rounded-xl border bg-card p-4 shadow-sm">
        {isLoading && !visibleEvents.length ? (
          <div className="flex min-h-[480px] items-center justify-center">
            <APILoader />
          </div>
        ) : activeTypes.length === 0 ? (
          <div className="flex min-h-[480px] items-center justify-center text-sm text-muted-foreground">
            Select at least one event type to display on the calendar.
          </div>
        ) : (
          <CalendarBoard
            events={visibleEvents}
            onDatesChange={handleDatesChange}
            onEventClick={handleEventClick}
            isLoading={isFetching}
          />
        )}
      </div>

      <CalendarEventDetail
        event={selectedEvent}
        open={detailOpen}
        onOpenChange={setDetailOpen}
      />

      <TaskViewModal
        task={selectedTask ?? null}
        open={Boolean(taskId && selectedTask)}
        onClose={() => setTaskId(null)}
      />

      <QaVerifyLeadViewDialog
        lead={qaLead}
        open={Boolean(qaLead)}
        onOpenChange={(open) => {
          if (!open) setQaLead(null);
        }}
      />
    </div>
  );
}
