import { OnlineSession } from '../entities/online-session.entity';
import { OnlineTypeEnum } from '../enum/online-type.enum';
import { ZoomWebinarStatus } from '../enum/zoom-webinar-status.enum';
import {
  MeetingDetails,
  WebinarDetails,
  StreamDetails,
  OnlineDetailsInput,
} from '../interfaces/online-details.interface';
import { WEBINAR_COLUMN_KEYS } from '../constants/online-session.constants';

function webinarExtras(w: WebinarDetails): Record<string, unknown> | null {
  const extras: Record<string, unknown> = {};
  for (const key of Object.keys(w) as (keyof WebinarDetails)[]) {
    if (!WEBINAR_COLUMN_KEYS.includes(key) && w[key] !== undefined) {
      extras[key] = w[key];
    }
  }
  return Object.keys(extras).length ? extras : null;
}

/**
 * Maps whichever legacy detail shape is present onto OnlineSession columns.
 * Returns `null` when no online details are supplied.
 */
export function mapDetailsToOnlineSession(input: OnlineDetailsInput): Partial<OnlineSession> | null {
  if (input.meetingDetails) {
    const m = input.meetingDetails;
    return {
      type: OnlineTypeEnum.MEETING,
      provider: m.provider ?? null,
      externalId: m.meetingId ?? null,
      joinUrl: m.meetingLink ?? null,
      password: m.meetingPassword ?? null,
      registrationUrl: m.registrationLink ?? null,
      requireRegistration: m.requireRegistration ?? null,
      hostEmail: m.hostEmail ?? null,
      startUrl: m.startUrl ?? null,
      status: m.status ?? null,
      actualMeetingEndsAt: m.actualMeetingEndsAt ? new Date(m.actualMeetingEndsAt) : null,
    };
  }
  if (input.webinarDetails) {
    const w = input.webinarDetails;
    return {
      type: OnlineTypeEnum.WEBINAR,
      provider: w.provider ?? null,
      externalId: w.webinarId ?? null,
      joinUrl: w.webinarLink ?? null,
      password: w.webinarPassword ?? null,
      registrationUrl: w.registrationLink ?? null,
      panelistUrl: w.panelistLink ?? null,
      hostEmail: w.hostEmail ?? null,
      startUrl: w.startUrl ?? null,
      status: w.status ?? null,
      actualMeetingEndsAt: w.actualMeetingEndsAt ? new Date(w.actualMeetingEndsAt) : null,
      details: webinarExtras(w),
    };
  }
  if (input.streamDetails) {
    const s = input.streamDetails;
    return {
      type: OnlineTypeEnum.LIVE_STREAM,
      streamUrl: s.streamUrl ?? null,
      backupStreamUrl: s.backupStreamUrl ?? null,
      chatUrl: s.chatUrl ?? null,
    };
  }
  return null;
}

/** Reconstructs the MeetingDetails shape from an OnlineSession row (for responses). */
export function toMeetingDetails(os: OnlineSession | null | undefined): MeetingDetails | null {
  if (!os || os.type !== OnlineTypeEnum.MEETING) return null;
  return {
    provider: os.provider ?? undefined,
    meetingId: os.externalId ?? '',
    meetingLink: os.joinUrl ?? '',
    meetingPassword: os.password ?? '',
    registrationLink: os.registrationUrl ?? undefined,
    requireRegistration: os.requireRegistration ?? undefined,
    hostEmail: os.hostEmail ?? undefined,
    startUrl: os.startUrl ?? undefined,
    status: (os.status as ZoomWebinarStatus) ?? undefined,
    actualMeetingEndsAt: os.actualMeetingEndsAt ? os.actualMeetingEndsAt.toISOString() : null,
    hostStartOpensMinutesBefore: os.hostStartOpensMinutesBefore ?? undefined,
  };
}

/** Reconstructs the WebinarDetails shape from an OnlineSession row (for responses). */
export function toWebinarDetails(os: OnlineSession | null | undefined): WebinarDetails | null {
  if (!os || os.type !== OnlineTypeEnum.WEBINAR) return null;
  return {
    provider: os.provider ?? undefined,
    webinarId: os.externalId ?? '',
    webinarLink: os.joinUrl ?? '',
    webinarPassword: os.password ?? '',
    panelistLink: os.panelistUrl ?? '',
    registrationLink: os.registrationUrl ?? '',
    hostEmail: os.hostEmail ?? undefined,
    startUrl: os.startUrl ?? undefined,
    status: (os.status as ZoomWebinarStatus) ?? undefined,
    actualMeetingEndsAt: os.actualMeetingEndsAt ? os.actualMeetingEndsAt.toISOString() : null,
    hostStartOpensMinutesBefore: os.hostStartOpensMinutesBefore ?? undefined,
    ...(os.details ?? {}),
  };
}

/** Reconstructs the StreamDetails shape from an OnlineSession row (for responses). */
export function toStreamDetails(os: OnlineSession | null | undefined): StreamDetails | null {
  if (!os || os.type !== OnlineTypeEnum.LIVE_STREAM) return null;
  return {
    streamUrl: os.streamUrl ?? '',
    backupStreamUrl: os.backupStreamUrl ?? undefined,
    chatUrl: os.chatUrl ?? undefined,
  };
}
