/**
 * DEPENDENCIES NEEDED (not installed — convention fork):
 *   @fullcalendar/react@^6
 *   @fullcalendar/daygrid@^6
 *   @fullcalendar/timegrid@^6
 *   @fullcalendar/interaction@^6
 *
 * Rationale for FullCalendar over react-big-calendar:
 * - More mature accessibility (ARIA roles, keyboard nav)
 * - Better drag-drop support via @fullcalendar/interaction
 * - Built-in month/week/day views with consistent API
 * - Active maintenance and large community
 */

import { useState } from "react";
import { Text, Stack, Skeleton, Alert, Button, SegmentedControl } from "@mantine/core";
import { IconAlertCircle } from "@tabler/icons-react";
import { useTranslation } from "react-i18next";
import { useDisclosure } from "@mantine/hooks";
// FullCalendar imports — these will resolve once the deps are installed.
import FullCalendar from "@fullcalendar/react";
import dayGridPlugin from "@fullcalendar/daygrid";
import timeGridPlugin from "@fullcalendar/timegrid";
import interactionPlugin, { EventDropArg } from "@fullcalendar/interaction";
import { EventClickArg } from "@fullcalendar/core";
import { useViewData } from "../hooks/use-view-data";
import { useUpdateRow } from "../hooks/use-update-row";
import { useDatabaseRealtimeUpdates } from "../hooks/use-database-realtime-updates";
import { usePermissions } from "../hooks/use-permissions";
import { RowDetailModal } from "../components/row-detail-modal";
import type { BridgeRow, BridgeField } from "../types/database-view.types";
import styles from "./calendar-renderer.module.css";

const PAGE_SIZE = 500;

type CalendarView = "dayGridMonth" | "timeGridWeek" | "timeGridDay";

interface CalendarRendererProps {
  tableId: string;
  viewId: string;
  bridgeUrl?: string | null;
}

/** Resolve the date field used to position events on the calendar. */
function resolveDateField(
  fields: BridgeField[],
  viewMeta?: { dateFieldId?: string },
): BridgeField | undefined {
  if (viewMeta?.dateFieldId) {
    return fields.find((f) => f.id === viewMeta.dateFieldId);
  }
  return fields.find((f) => f.type === "date" || f.type === "created_on");
}

/** Convert a row to a FullCalendar EventInput. Returns null when no date. */
function rowToEvent(
  row: BridgeRow,
  dateField: BridgeField,
  primaryField?: BridgeField,
): { id: string; title: string; start: string; extendedProps: { row: BridgeRow; fields: BridgeField[] } } | null {
  const rawDate = row.fields[dateField.name] ?? row.fields[dateField.id];
  if (!rawDate) return null;

  const dateStr = typeof rawDate === "string" ? rawDate : String(rawDate);
  // Validate the date string.
  if (isNaN(new Date(dateStr).getTime())) return null;

  const primaryValue = primaryField
    ? (row.fields[primaryField.name] ?? row.fields[primaryField.id])
    : row.id;

  const title =
    typeof primaryValue === "string"
      ? primaryValue
      : typeof primaryValue === "number"
        ? String(primaryValue)
        : row.id;

  return {
    id: row.id,
    title: title || row.id,
    start: dateStr,
    extendedProps: { row, fields: [] },
  };
}

function CalendarSkeleton() {
  return (
    <Stack gap="xs">
      <Skeleton height={32} width={200} />
      <Skeleton height={400} radius="sm" />
    </Stack>
  );
}

export function CalendarRenderer({ tableId, viewId, bridgeUrl }: CalendarRendererProps) {
  const { t } = useTranslation();
  const [calView, setCalView] = useState<CalendarView>("dayGridMonth");
  const [selectedRow, setSelectedRow] = useState<BridgeRow | null>(null);
  const [selectedFields, setSelectedFields] = useState<BridgeField[]>([]);
  const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);

  const { data, isLoading, isError, error, refetch } = useViewData({
    viewId,
    bridgeUrl,
    page: 1,
    size: PAGE_SIZE,
  });

  const { canWriteRows } = usePermissions();
  const updateRow = useUpdateRow({ tableId, viewId, bridgeUrl });
  useDatabaseRealtimeUpdates(tableId, viewId, bridgeUrl);

  if (isLoading) return <CalendarSkeleton />;

  if (isError) {
    const status = (error as { response?: { status?: number } })?.response?.status;
    let message = t("database_view.error.generic");
    if (status === 403) message = t("database_view.error.permission_denied");
    else if (status === 404) message = t("database_view.error.view_not_found");

    return (
      <Alert
        icon={<IconAlertCircle size={16} />}
        color="red"
        title={t("database_view.error.title")}
      >
        <Stack gap="xs">
          <Text size="sm">{message}</Text>
          <Button size="xs" variant="subtle" onClick={() => refetch()}>
            {t("database_view.error.retry")}
          </Button>
        </Stack>
      </Alert>
    );
  }

  const { rows, fields } = data ?? { rows: [], fields: [] };
  const dateField = resolveDateField(fields);

  if (!dateField) {
    return (
      <Alert icon={<IconAlertCircle size={16} />} color="yellow">
        <Text size="sm">{t("database_view.calendar.no_date_field")}</Text>
      </Alert>
    );
  }

  const primaryField = fields.find((f) => f.primary) ?? fields[0];

  const events = rows
    .map((row) => rowToEvent(row, dateField, primaryField))
    .filter((e): e is NonNullable<typeof e> => e !== null)
    .map((e) => ({ ...e, extendedProps: { ...e.extendedProps, fields } }));

  function handleEventClick(arg: EventClickArg) {
    const row = arg.event.extendedProps.row as BridgeRow;
    const eventFields = arg.event.extendedProps.fields as BridgeField[];
    setSelectedRow(row);
    setSelectedFields(eventFields);
    openModal();
  }

  function handleEventDrop(arg: EventDropArg) {
    if (!canWriteRows) {
      arg.revert();
      return;
    }

    const rowId = arg.event.id;
    const newStart = arg.event.start;
    if (!newStart) {
      arg.revert();
      return;
    }

    updateRow.mutate(
      {
        rowId,
        payload: {
          fields: {
            [dateField.name]: newStart.toISOString(),
          },
        },
      },
      {
        onError: () => {
          arg.revert();
        },
      },
    );
  }

  const viewOptions = [
    { label: t("database_view.calendar.view_month"), value: "dayGridMonth" },
    { label: t("database_view.calendar.view_week"), value: "timeGridWeek" },
    { label: t("database_view.calendar.view_day"), value: "timeGridDay" },
  ];

  return (
    <div>
      <div className={styles.toolbar}>
        <SegmentedControl
          size="xs"
          value={calView}
          onChange={(v) => setCalView(v as CalendarView)}
          data={viewOptions}
        />
      </div>

      <div className={styles.calendarWrapper}>
        <FullCalendar
          plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin]}
          initialView={calView}
          key={calView}
          events={events}
          editable={canWriteRows}
          droppable={canWriteRows}
          eventClick={handleEventClick}
          eventDrop={handleEventDrop}
          headerToolbar={{
            left: "prev,next today",
            center: "title",
            right: "",
          }}
          height="auto"
          eventClassNames={() => [styles.calendarEvent]}
        />
      </div>

      <RowDetailModal
        row={selectedRow}
        fields={selectedFields}
        opened={modalOpened}
        onClose={closeModal}
      />
    </div>
  );
}
