// shapes.ts
// Strongly-typed SHAPES with per-collection document + hydrated types,
// and exports you can reuse inside AiService.

export type MongoProjection = Record<string, 0 | 1>;

export type WithId = { _id: unknown };

// ---- Attraction ----
export type AttractionDoc = WithId & {
  title?: string | null;
  description?: string | null;
  formatted_address?: string | null;
  thumbnail?: string | null;
  venue?: string | null;
  city_level?: string | null;
  country_short?: string | null;
};

export type AttractionHydrated = {
  collection: 'attraction';
  _id: string;
  title: string | null;
  description: string | null;
  formatted_address: string | null;
  venue: string | null;
  city_level: string | null;
  country_short: string | null;
  thumbnail: string | null;
};

// ---- Event ----
export type EventDoc = WithId & {
  title?: string | null;
  description?: string | null;
  formatted_address?: string | null;
  venue?: string | null;
  start_date?: string | null;
  end_date?: string | null;
  start_time?: string | null;
  end_time?: string | null;
  thumbnail?: string | null;
};

export type EventHydrated = {
  collection: 'event';
  _id: string;
  title: string | null;
  description: string | null;
  formatted_address: string | null;
  venue: string | null;
  start_date: string | null;
  end_date: string | null;
  start_time: string | null;
  end_time: string | null;
  thumbnail: string | null;
};

// ---- Generic shape definition ----
export type ShapeDef<Doc, Hydrated> = {
  projection: MongoProjection;
  hydrate: (d: Doc) => Hydrated;
  toContext: (h: Hydrated, idx: number) => string;
  defaultTitle: string;
};

// ---- All collections typing ----
export type CollectionName = 'attraction' | 'event';

export type ShapesMap = {
  attraction: ShapeDef<AttractionDoc, AttractionHydrated>;
  event: ShapeDef<EventDoc, EventHydrated>;
};

export const SHAPES: ShapesMap = {
  attraction: {
    projection: {
      title: 1,
      description: 1,
      formatted_address: 1,
      thumbnail: 1,
      venue: 1,
      city_level: 1,
      country_short: 1,
    },
    hydrate: (d) => ({
      collection: 'attraction',
      _id: String(d._id),
      title: d.title ?? null,
      description: d.description ?? null,
      formatted_address: d.formatted_address ?? null,
      venue: d.venue ?? null,
      city_level: d.city_level ?? null,
      country_short: d.country_short ?? null,
      thumbnail: d.thumbnail ?? null,
    }),
    toContext: (h, idx) => {
      const where = [
        h.venue,
        h.formatted_address,
        h.city_level,
        h.country_short,
      ]
        .filter(Boolean)
        .join(', ');
      return `${idx}. [attraction#${h._id}] ${h.title ?? ''}\n${
        h.description ?? ''
      }\n${where}`;
    },
    defaultTitle: 'Must-See Attractions',
  },

  event: {
    projection: {
      title: 1,
      description: 1,
      formatted_address: 1,
      venue: 1,
      start_date: 1,
      end_date: 1,
      start_time: 1,
      end_time: 1,
      thumbnail: 1,
    },
    hydrate: (d) => ({
      collection: 'event',
      _id: String(d._id),
      title: d.title ?? null,
      description: d.description ?? null,
      formatted_address: d.formatted_address ?? null,
      venue: d.venue ?? null,
      start_date: d.start_date ?? null,
      end_date: d.end_date ?? null,
      start_time: d.start_time ?? null,
      end_time: d.end_time ?? null,
      thumbnail: d.thumbnail ?? null,
    }),
    toContext: (h, idx) => {
      const when = [h.start_date, h.start_time, h.end_date, h.end_time]
        .filter(Boolean)
        .join(' ');
      const where = [h.venue, h.formatted_address].filter(Boolean).join(', ');
      return `${idx}. [event#${h._id}] ${h.title ?? ''}\n${
        h.description ?? ''
      }\n${when}\n${where}`;
    },
    defaultTitle: 'Upcoming Events',
  },
};
