import type { Course } from '@/payload-types'
import { enrolUrl, feedUrl, platform } from './config'

/**
 * The course catalogue, read from the learning platform.
 *
 * The platform owns it: which courses exist, their names, what they cover, what they cost and where they
 * stand are set on each course there, and this site prints them. The CMS keeps only what is about how the
 * site shows a course — its picture, the card colour, the free-lesson videos on its page — and it stands in
 * for the platform when the platform cannot be reached, so a page never goes blank for want of it.
 */

type Lang = { title: string; titleShort: string; tagline: string; audience: string; level: string; instruction: string;
  facts: string[]; includes: string[]; outcomes: string[]; availability: string; priceNote: string;
  units: { n: number; name: string; kind: 'lessons' | 'labs' | 'projects'; source: 'book' | 'added';
    lessons: number; book: number | null }[] }

export type FeedCourse = {
  id: number
  slug: string
  status: 'live' | 'partial' | 'soon'
  visible: boolean
  category: number
  image: string | null
  // Who the course is for, at the top: school, work, or either. The finer audience under it is `stages` for a
  // school course and `audiences` for a work one — a course has one or the other, not both.
  track: 'school' | 'pro' | 'both'
  stages: string[]
  audiences: string[]
  enrolUrl: string
  price: { cost: number; offer: number | null; offerEnds: string | null; currency: string } | null
  ar: Lang
  en: Lang
}

export type FeedCategory = { id: number; slug: string; name: { ar: string; en: string }; order: number }

export type Feed = { generated: number; categories: FeedCategory[]; courses: FeedCourse[] }

/**
 * The catalogue, or null when there is no platform to ask or it did not answer in time.
 *
 * Where the platform is, what its catalogue endpoint is called, how long an answer may be reused and how
 * long to wait for one all come from env/cms.env through `lib/config`. No address is written in this file.
 */
export async function catalogueFeed(): Promise<Feed | null> {
  const url = feedUrl()
  if (!url) return null
  try {
    const res = await fetch(url, {
      next: { revalidate: platform.feedTtl(), tags: ['catalogue'] },
      signal: AbortSignal.timeout(platform.feedTimeout()),
    })
    if (!res.ok) return null
    const feed = (await res.json()) as Feed
    return feed && Array.isArray(feed.courses) ? feed : null
  } catch {
    return null
  }
}

/** A list of lines as the CMS shapes a list, so every page that already prints one keeps working. */
const rows = (slug: string, key: string, items: string[]) =>
  items.map((text, i) => ({ id: `${slug}-${key}-${i}`, text }))

/**
 * One platform course as the site's Course, in one language, wearing the CMS row of the same slug for the
 * things only the site decides. A course the CMS has never heard of still gets a page: it simply shows no
 * picture and the default card colour until someone gives it one.
 */
export type FeedExtras = { categoryId: number; image: string | null; track: FeedCourse['track']; stages: string[]; audiences: string[] }

export function fromFeed(fc: FeedCourse, order: number, locale: 'ar' | 'en', cms?: Course): Course & FeedExtras {
  const t = fc[locale]
  const fallback = locale === 'en' ? fc.ar : null        // an English field left empty borrows the Arabic one
  const pick = (k: keyof Lang) => (t[k] as string) || (fallback ? (fallback[k] as string) : '')
  return {
    ...(cms || ({} as Course)),
    id: cms?.id ?? (`p${fc.id}` as unknown as number),
    slug: fc.slug,
    status: fc.status,
    order,
    title: pick('title'),
    titleShort: t.titleShort || null,
    tagline: pick('tagline'),
    audience: pick('audience'),
    level: pick('level'),
    instruction: pick('instruction'),
    availability: pick('availability'),
    facts: rows(fc.slug, 'f', t.facts.length ? t.facts : fallback?.facts || []),
    includes: rows(fc.slug, 'i', t.includes.length ? t.includes : fallback?.includes || []),
    outcomes: rows(fc.slug, 'o', t.outcomes.length ? t.outcomes : fallback?.outcomes || []),
    units: t.units.map((u, i) => ({ id: `${fc.slug}-u-${i}`, ...u })),
    price: {
      amount: fc.price ? fc.price.cost : null,
      offer: fc.price?.offer ?? null,
      // a plain «2026-10-15» from the platform, read as that day wherever this runs
      offerEnds: fc.price?.offerEnds ? `${fc.price.offerEnds}T00:00:00.000Z` : null,
      note: pick('priceNote') || null,
    },
    // What the platform said to use; PLATFORM_ENROL_URL in env/cms.env stands in when it said nothing.
    platformUrl: enrolUrl(fc.slug, fc.enrolUrl),
    tone: cms?.tone || 'royal-700',
    categoryId: fc.category,
    // the course picture set on the platform, used when the CMS row has no poster of its own
    image: fc.image ?? null,
    // Who it is for. The catalogue filters by these rather than grouping by them: a course sits under one
    // subject and a heading can say so, but it can serve several stages, or none in particular.
    // A feed from a platform that predates the track answers for school, which is what every course was then.
    track: fc.track === 'pro' || fc.track === 'both' ? fc.track : 'school',
    stages: Array.isArray(fc.stages) ? fc.stages : [],
    audiences: Array.isArray(fc.audiences) ? fc.audiences : [],
  } as Course & FeedExtras
}
