import type {
  ProgressReportCalendarEvent,
  ProgressReportCalendarEventDetail,
} from "./progress-report-calendar-data";
import type { UploadedFileMetadata } from "@/lib/document-file";

export type ProgressReportCalendarMeetingStatus = "DRAFT" | "SENT";

// What the report list returns for a meeting. The heavier detail fields are
// loaded on demand when an event card is opened.
export type ProgressReportCalendarMeetingSource = {
  id: number;
  title: string;
  meetingDate: string;
  startTime: string;
  endTime: string;
  status: ProgressReportCalendarMeetingStatus;
};

// Everything a single meeting endpoint returns, used to fill the popup.
export type ProgressReportCalendarMeetingDetailSource =
  ProgressReportCalendarMeetingSource & {
    description: unknown | null;
    location: string;
    documentReference: UploadedFileMetadata | null;
  };

function mapMeetingStatus(
  status: ProgressReportCalendarMeetingStatus,
): "Draft" | "Sent" {
  return status === "SENT" ? "Sent" : "Draft";
}

function parseDateKey(value: string) {
  if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) return null;

  const date = new Date(`${value}T00:00:00.000Z`);

  if (Number.isNaN(date.getTime())) return null;
  if (date.toISOString().slice(0, 10) !== value) return null;

  return date;
}

function decodeHtmlEntities(value: string) {
  return value
    .replaceAll("&nbsp;", " ")
    .replaceAll("&amp;", "&")
    .replaceAll("&lt;", "<")
    .replaceAll("&gt;", ">")
    .replaceAll("&quot;", '"')
    .replaceAll("&#39;", "'");
}

export function formatProgressReportDescription(value: unknown) {
  if (value === null || value === undefined) return "-";

  const text = typeof value === "string" ? value : JSON.stringify(value);
  const plainText = decodeHtmlEntities(text)
    .replace(/<[^>]*>/g, " ")
    .replace(/\s+/g, " ")
    .trim();

  return plainText || "-";
}

export function mapProgressReportMeetingToCalendarEvent(
  meeting: ProgressReportCalendarMeetingSource,
): ProgressReportCalendarEvent | null {
  const meetingDate = parseDateKey(meeting.meetingDate);

  if (!meetingDate) return null;

  return {
    id: meeting.id,
    title: meeting.title,
    dateKey: meeting.meetingDate,
    startTime: meeting.startTime,
    endTime: meeting.endTime,
    status: mapMeetingStatus(meeting.status),
  };
}

// Fills the popup fields once the full meeting has been fetched.
export function mapProgressReportMeetingDetailToCalendarEvent(
  meeting: ProgressReportCalendarMeetingDetailSource,
): ProgressReportCalendarEventDetail {
  return {
    locationName: meeting.location.trim() || "-",
    locationAddress: "-",
    status: mapMeetingStatus(meeting.status),
    description: formatProgressReportDescription(meeting.description),
    document: meeting.documentReference,
    documentName: meeting.documentReference?.name || "-",
    documentSize: meeting.documentReference?.size ?? null,
  };
}

export function mapProgressReportMeetingsToCalendarEvents(
  meetings: ProgressReportCalendarMeetingSource[],
) {
  return meetings
    .map(mapProgressReportMeetingToCalendarEvent)
    .filter((event): event is ProgressReportCalendarEvent => event !== null);
}
