"use client";

import { GERMAN_FEDERAL_STATES } from "@capakraken/shared";
import { createPortal } from "react-dom";
import { formatCents, formatDateLong } from "~/lib/format.js";

function getVacationTitle(vacation: VacationHoverData): string {
  if (vacation.type === "PUBLIC_HOLIDAY" && vacation.note) {
    return vacation.note;
  }
  return vacation.type.replaceAll("_", " ");
}

export type HeatmapHoverData = {
  date: Date;
  totalH: number;
  pct: number;
  breakdown: {
    projectId: string;
    shortCode: string;
    projectName: string;
    orderType: string;
    hoursPerDay: number;
    responsiblePerson?: string | null;
    role?: string | null;
    status?: string;
    startDate?: string;
    endDate?: string;
  }[];
};

export type VacationHoverData = {
  type: string;
  startDate: Date | string;
  endDate: Date | string;
  note?: string | null;
  scope?: string | null;
  calendarName?: string | null;
  sourceType?: string | null;
  countryCode?: string | null;
  countryName?: string | null;
  federalState?: string | null;
  metroCityName?: string | null;
  requestedBy?: { name?: string | null; email: string } | null;
  approvedBy?: { name?: string | null; email: string } | null;
  approvedAt?: Date | string | null;
};

function formatHolidayScope(scope?: string | null): string | null {
  switch (scope) {
    case "COUNTRY":
      return "Country";
    case "STATE":
      return "State";
    case "CITY":
      return "City";
    default:
      return scope ? scope.replaceAll("_", " ") : null;
  }
}

function formatHolidaySourceType(sourceType?: string | null): string | null {
  switch (sourceType) {
    case "SYSTEM":
      return "Built-in";
    case "CALENDAR":
      return "Calendar";
    default:
      return sourceType ? sourceType.replaceAll("_", " ") : null;
  }
}

function formatHolidayStateName(
  federalState?: string | null,
  countryCode?: string | null,
): string | null {
  if (!federalState) {
    return null;
  }

  if (countryCode === "DE") {
    return GERMAN_FEDERAL_STATES[federalState] ?? federalState;
  }

  return federalState;
}

function buildHolidayLocationBasis(vacation: VacationHoverData): string | null {
  const parts = [
    vacation.countryName
      ? `Country: ${vacation.countryName}`
      : vacation.countryCode
        ? `Country: ${vacation.countryCode}`
        : null,
    formatHolidayStateName(vacation.federalState, vacation.countryCode)
      ? `State: ${formatHolidayStateName(vacation.federalState, vacation.countryCode)}`
      : null,
    vacation.metroCityName ? `City: ${vacation.metroCityName}` : null,
  ].filter(Boolean);

  return parts.length > 0 ? parts.join(" · ") : null;
}

export type DemandHoverData = {
  roleName: string;
  roleColor: string;
  projectName: string;
  projectShortCode?: string | null;
  requestedHeadcount: number;
  unfilledHeadcount: number;
  startDate: Date | string;
  endDate: Date | string;
  hoursPerDay: number;
  totalHours: number;
  percentage?: number;
  status?: string;
  totalCostCents?: number;
  dailyCostCents?: number;
};

interface TimelineTooltipProps {
  heatmapTooltipRef: React.RefObject<HTMLDivElement | null>;
  heatmapTooltipPos: { left: number; top: number };
  vacationTooltipRef: React.RefObject<HTMLDivElement | null>;
  vacationTooltipPos: { left: number; top: number };
  heatmapHover: HeatmapHoverData | null;
  vacationHover: VacationHoverData | null;
  demandTooltipRef?: React.RefObject<HTMLDivElement | null>;
  demandTooltipPos?: { left: number; top: number };
  demandHover?: DemandHoverData | null;
}

function renderTooltipPortal(content: React.ReactNode) {
  return typeof document === "undefined" ? content : createPortal(content, document.body);
}

function TooltipSurface({
  children,
  position,
  tooltipRef,
  className,
  dataTestId,
  backgroundColor,
}: {
  children: React.ReactNode;
  position: { left: number; top: number };
  tooltipRef?: React.Ref<HTMLDivElement>;
  className: string;
  dataTestId?: string;
  backgroundColor: string;
}) {
  return (
    <div
      ref={tooltipRef}
      data-testid={dataTestId}
      style={{
        left: position.left,
        top: position.top,
        backgroundColor,
      }}
      className={className}
    >
      {children}
    </div>
  );
}

function TooltipMetric({
  label,
  value,
  valueClassName = "font-medium text-gray-100",
}: {
  label: string;
  value: React.ReactNode;
  valueClassName?: string;
}) {
  return (
    <div>
      <div className="text-gray-500">{label}</div>
      <div className={valueClassName}>{value}</div>
    </div>
  );
}

function HeatmapBreakdownList({ breakdown }: { breakdown: HeatmapHoverData["breakdown"] }) {
  if (breakdown.length === 0) {
    return <div className="text-[11px] text-gray-400">No bookings on this day.</div>;
  }

  return (
    <>
      {breakdown.slice(0, 6).map((entry) => (
        <div
          key={`${entry.projectId}-${entry.shortCode}`}
          className="flex items-start justify-between gap-3"
        >
          <div className="min-w-0">
            <div className="truncate font-medium text-white">
              {entry.shortCode ? `${entry.shortCode} · ` : ""}
              {entry.projectName}
            </div>
            <div className="truncate text-[11px] text-gray-400">
              {[
                entry.role,
                entry.responsiblePerson ? `Lead: ${entry.responsiblePerson}` : null,
                entry.orderType,
              ].filter(Boolean).join(" · ")}
            </div>
            {entry.startDate && entry.endDate ? (
              <div className="text-[10px] text-gray-500">
                {entry.startDate} → {entry.endDate}
                {entry.status && entry.status !== "CONFIRMED" ? (
                  <span className="ml-1 uppercase text-amber-400">{entry.status}</span>
                ) : null}
              </div>
            ) : null}
          </div>
          <span className="whitespace-nowrap text-[11px] font-semibold text-gray-200">
            {entry.hoursPerDay}h
          </span>
        </div>
      ))}
    </>
  );
}

function VacationSummary({
  vacation,
  title,
  className,
}: {
  vacation: VacationHoverData;
  title: string;
  className?: string;
}) {
  const isPublicHoliday = vacation.type === "PUBLIC_HOLIDAY";
  const scopeLabel = formatHolidayScope(vacation.scope);
  const sourceLabel = formatHolidaySourceType(vacation.sourceType);
  const holidayMeta = [scopeLabel, sourceLabel].filter(Boolean).join(" · ");
  const holidayLocationBasis = isPublicHoliday ? buildHolidayLocationBasis(vacation) : null;

  return (
    <div className={className}>
      <div className="flex items-center gap-1.5">
        <span className="inline-block h-2 w-2 flex-shrink-0 rounded-full bg-amber-500" />
        <span className="font-semibold text-amber-300">{title}</span>
      </div>
      <div className="mt-0.5 text-[11px] text-amber-200/80">
        {formatDateLong(vacation.startDate)} to {formatDateLong(vacation.endDate)}
      </div>
      {holidayMeta ? (
        <div className="mt-1 text-[11px] text-amber-100/75">{holidayMeta}</div>
      ) : null}
      {holidayLocationBasis ? (
        <div className="mt-1 text-[11px] text-amber-100/85">{holidayLocationBasis}</div>
      ) : null}
      {isPublicHoliday && vacation.calendarName ? (
        <div className="mt-1 text-[11px] text-amber-200/60">
          Calendar: {vacation.calendarName}
        </div>
      ) : null}
      {vacation.note && !isPublicHoliday ? (
        <div className="mt-1 text-[11px] text-amber-200/60">{vacation.note}</div>
      ) : null}
    </div>
  );
}

export function TimelineTooltip({
  heatmapTooltipRef,
  heatmapTooltipPos,
  vacationTooltipRef,
  vacationTooltipPos,
  heatmapHover,
  vacationHover,
  demandTooltipRef,
  demandTooltipPos,
  demandHover,
}: TimelineTooltipProps) {
  const vacationTitle = vacationHover ? getVacationTitle(vacationHover) : null;

  if (demandHover && demandTooltipRef && demandTooltipPos) {
    return renderTooltipPortal(
      <TooltipSurface
        tooltipRef={demandTooltipRef}
        dataTestId="timeline-demand-tooltip"
        position={demandTooltipPos}
        backgroundColor="rgba(3, 7, 18, 0.96)"
        className="fixed z-40 max-w-sm pointer-events-none rounded-xl border border-gray-800 bg-gray-950/96 px-3 py-2 text-xs text-white shadow-2xl"
      >
        <div className="flex items-start justify-between gap-3">
          <div className="min-w-0">
            <div className="flex items-center gap-1.5">
              <span
                className="inline-block h-2 w-2 rounded-full flex-shrink-0"
                style={{ backgroundColor: demandHover.roleColor }}
              />
              <span className="truncate font-semibold">{demandHover.roleName}</span>
            </div>
            <div className="truncate text-[11px] text-gray-400">
              {demandHover.projectShortCode ? `${demandHover.projectShortCode} · ` : ""}
              {demandHover.projectName}
            </div>
          </div>
          {demandHover.status ? (
            <span className="text-[10px] uppercase tracking-wide text-amber-300">
              {demandHover.status}
            </span>
          ) : null}
        </div>

        <div className="mt-2 grid grid-cols-2 gap-x-4 gap-y-1.5 text-[11px]">
          <TooltipMetric
            label="Requested"
            value={`${demandHover.requestedHeadcount} ${demandHover.requestedHeadcount === 1 ? "seat" : "seats"}`}
          />
          <TooltipMetric
            label="Open"
            value={`${demandHover.unfilledHeadcount} ${demandHover.unfilledHeadcount === 1 ? "seat" : "seats"}`}
            valueClassName="font-medium text-amber-300"
          />
          <TooltipMetric
            label="Range"
            value={`${formatDateLong(demandHover.startDate)} to ${formatDateLong(demandHover.endDate)}`}
          />
          <TooltipMetric
            label="Load"
            value={`${demandHover.hoursPerDay}h/day · ${demandHover.totalHours}h`}
          />
          {typeof demandHover.percentage === "number" && demandHover.percentage > 0 ? (
            <TooltipMetric label="Allocation" value={`${demandHover.percentage}%`} />
          ) : null}
          {typeof demandHover.totalCostCents === "number" && demandHover.totalCostCents > 0 ? (
            <TooltipMetric
              label="Cost"
              value={`${formatCents(demandHover.totalCostCents)} EUR${
                typeof demandHover.dailyCostCents === "number" && demandHover.dailyCostCents > 0
                  ? ` · ${formatCents(demandHover.dailyCostCents)}/d`
                  : ""
              }`}
            />
          ) : null}
        </div>

        <div className="mt-2 border-t border-gray-800/90 pt-2 text-[10px] uppercase tracking-[0.14em] text-gray-500">
          Click for details and actions
        </div>
      </TooltipSurface>,
    );
  }

  // When both are active, render a single merged tooltip using the heatmap position
  if (heatmapHover && vacationHover) {
    return renderTooltipPortal(
      <TooltipSurface
        tooltipRef={(el) => {
          (heatmapTooltipRef as React.MutableRefObject<HTMLDivElement | null>).current = el;
          // Keep the merged tooltip attached to the heatmap pointer path only.
          (vacationTooltipRef as React.MutableRefObject<HTMLDivElement | null>).current = null;
        }}
        position={heatmapTooltipPos}
        backgroundColor="rgba(3, 7, 18, 0.96)"
        className="fixed z-40 max-w-sm pointer-events-none rounded-xl border border-gray-800 bg-gray-950/96 px-3 py-2 text-xs text-white shadow-2xl"
      >
        <div className="flex items-center justify-between gap-3">
          <span className="font-semibold">{formatDateLong(heatmapHover.date)}</span>
          <span className="text-[11px] text-gray-300">
            {heatmapHover.totalH.toFixed(1)}h · {Math.round(heatmapHover.pct)}%
          </span>
        </div>

        <div className="mt-2 space-y-1.5">
          <HeatmapBreakdownList breakdown={heatmapHover.breakdown} />
        </div>

        <VacationSummary
          vacation={vacationHover}
          title={vacationTitle ?? "Vacation"}
          className="mt-2 border-t border-amber-700/40 pt-2"
        />
      </TooltipSurface>,
    );
  }

  // Heatmap only
  if (heatmapHover) {
    return renderTooltipPortal(
      <TooltipSurface
        tooltipRef={heatmapTooltipRef}
        position={heatmapTooltipPos}
        backgroundColor="rgba(3, 7, 18, 0.96)"
        className="fixed z-40 max-w-sm pointer-events-none rounded-xl border border-gray-800 bg-gray-950/96 px-3 py-2 text-xs text-white shadow-2xl"
      >
        <div className="flex items-center justify-between gap-3">
          <span className="font-semibold">{formatDateLong(heatmapHover.date)}</span>
          <span className="text-[11px] text-gray-300">
            {heatmapHover.totalH.toFixed(1)}h · {Math.round(heatmapHover.pct)}%
          </span>
        </div>
        <div className="mt-2 space-y-1.5">
          <HeatmapBreakdownList breakdown={heatmapHover.breakdown} />
        </div>
      </TooltipSurface>,
    );
  }

  // Vacation only
  if (vacationHover) {
    return renderTooltipPortal(
      <TooltipSurface
        tooltipRef={vacationTooltipRef}
        position={vacationTooltipPos}
        backgroundColor="rgba(120, 53, 15, 0.95)"
        className="fixed z-40 max-w-xs pointer-events-none rounded-xl border border-amber-700/50 bg-amber-950/95 px-3 py-2 text-xs text-amber-50 shadow-2xl"
      >
        <VacationSummary vacation={vacationHover} title={vacationTitle ?? "Vacation"} />
      </TooltipSurface>,
    );
  }

  return null;
}
