import { initialApplicantsByPosition, initialPositions } from "@/components/initialPositionsData";

export type AtsEvent = {
  eventId: string;
  eventType: string;
  occurredAt: string;
  traceId: string;
  payload: Record<string, unknown>;
};

export const EVENTS_STORAGE_KEY = "ats.events.v1";
const EVENTS_SEED_VERSION_KEY = "ats.events.seedVersion";
const CURRENT_EVENTS_SEED_VERSION = "4";

function getSeedOccurredAt(offsetSeconds: number) {
  return new Date(Date.UTC(2026, 1, 20, 0, 0, offsetSeconds)).toISOString();
}

function getApplicantSeedStages(finalStageId: string) {
  switch (finalStageId) {
    case "new_applied":
      return ["new_applied", "resume_review_screening", "new_applied"];
    case "resume_review_screening":
      return ["new_applied", "resume_review_screening", "new_applied", "resume_review_screening"];
    case "offer_letter_sent":
      return ["new_applied", "resume_review_screening", "offer_letter_sent"];
    case "hired_or_closed":
      return ["new_applied", "resume_review_screening", "hired_or_closed"];
    default:
      return ["new_applied", "resume_review_screening", "new_applied"];
  }
}

function createSeedEvents(): AtsEvent[] {
  let timeOffset = 0;

  const positionEvents = initialPositions.map((position, index) => ({
    eventId: `seed-pos-${String(index + 1).padStart(3, "0")}`,
    eventType: "PositionDeclared",
    occurredAt: getSeedOccurredAt(timeOffset++),
    traceId: position.id,
    payload: {
      streamCategory: "positions_stream",
      streamId: `positions:${position.id}`,
      positionId: position.id,
      title: position.title,
      department: position.department,
      location: position.location,
      openings: position.openings,
      employmentType: position.employmentType,
    },
  }));

  const applicantEvents: AtsEvent[] = [];
  let applicantCounter = 1;
  let applicantMoveCounter = 1;
  for (const [positionId, applicants] of Object.entries(initialApplicantsByPosition)) {
    for (const applicant of applicants) {
      const stageTimeline = getApplicantSeedStages(applicant.stageId);

      applicantEvents.push({
        eventId: `seed-app-${String(applicantCounter).padStart(3, "0")}`,
        eventType: "ApplicantDeclared",
        occurredAt: getSeedOccurredAt(timeOffset++),
        traceId: positionId,
        payload: {
          streamCategory: "applicants_stream",
          streamId: `applicants:${positionId}`,
          positionId,
          applicantId: applicant.id,
          applicantName: applicant.name,
          role: applicant.role,
          stageId: stageTimeline[0],
        },
      });

      for (let i = 1; i < stageTimeline.length; i += 1) {
        applicantEvents.push({
          eventId: `seed-move-${String(applicantMoveCounter).padStart(3, "0")}`,
          eventType: "ApplicantStageMoved",
          occurredAt: getSeedOccurredAt(timeOffset++),
          traceId: positionId,
          payload: {
            streamCategory: "applicants_stream",
            streamId: `applicants:${positionId}`,
            positionId,
            applicantId: applicant.id,
            applicantName: applicant.name,
            role: applicant.role,
            fromStageId: stageTimeline[i - 1],
            toStageId: stageTimeline[i],
          },
        });
        applicantMoveCounter += 1;
      }

      applicantCounter += 1;
    }
  }

  return [...positionEvents, ...applicantEvents];
}

export function initializeEventStreamStorage() {
  if (typeof window === "undefined") {
    return;
  }

  const raw = window.localStorage.getItem(EVENTS_STORAGE_KEY);
  const currentSeedVersion = window.localStorage.getItem(EVENTS_SEED_VERSION_KEY);
  if (!raw || currentSeedVersion !== CURRENT_EVENTS_SEED_VERSION) {
    window.localStorage.setItem(EVENTS_STORAGE_KEY, JSON.stringify(createSeedEvents()));
    window.localStorage.setItem(EVENTS_SEED_VERSION_KEY, CURRENT_EVENTS_SEED_VERSION);
  }
}

export function resetEventStreamStorage() {
  if (typeof window === "undefined") {
    return;
  }

  window.localStorage.removeItem(EVENTS_STORAGE_KEY);
  window.localStorage.removeItem(EVENTS_SEED_VERSION_KEY);
}

export function readEventsFromStorage() {
  if (typeof window === "undefined") {
    return createSeedEvents();
  }

  initializeEventStreamStorage();
  const raw = window.localStorage.getItem(EVENTS_STORAGE_KEY);
  if (!raw) {
    return createSeedEvents();
  }

  try {
    const parsed = JSON.parse(raw);
    if (Array.isArray(parsed)) {
      return parsed as AtsEvent[];
    }
  } catch {
    return createSeedEvents();
  }

  return createSeedEvents();
}

export function appendEventToStorage(event: Omit<AtsEvent, "eventId" | "occurredAt">) {
  if (typeof window === "undefined") {
    return;
  }

  const events = readEventsFromStorage();
  const nextEvent: AtsEvent = {
    eventId: window.crypto?.randomUUID?.() ?? `evt-${Date.now()}`,
    occurredAt: new Date().toISOString(),
    ...event,
  };
  window.localStorage.setItem(EVENTS_STORAGE_KEY, JSON.stringify([...events, nextEvent]));
}

export function readEventsForPosition(positionId: string) {
  return readEventsFromStorage()
    .filter((event) => event.traceId === positionId)
    .sort((a, b) => (a.occurredAt < b.occurredAt ? 1 : -1));
}

export function readEventsForApplicant(applicantId: string) {
  return readEventsFromStorage()
    .filter((event) => {
      const payloadApplicantId =
        typeof event.payload.applicantId === "string" ? event.payload.applicantId : undefined;
      return payloadApplicantId === applicantId;
    })
    .sort((a, b) => (a.occurredAt < b.occurredAt ? 1 : -1));
}
