import { APIError, APIHandler } from 'api/helpers/endpoint'
import { createSupabaseDirectClient } from 'shared/supabase/init'
import { log, getUser } from 'shared/utils'
import {HOUR_MS, MINUTE_MS, sleep} from 'common/util/time'
import { removePinnedUrlFromPhotoUrls } from 'shared/profiles/parse-photos'
import { track } from 'shared/analytics'
import { updateUser } from 'shared/supabase/users'
import { tryCatch } from 'common/util/try-catch'
import { insert } from 'shared/supabase/utils'
import {sendDiscordMessage} from "common/discord/core";
import {jsonToMarkdown} from "common/md";

export const createProfile: APIHandler<'create-profile'> = async (body, auth) => {
  const pg = createSupabaseDirectClient()

  const { data: existingUser } = await tryCatch(
    pg.oneOrNone<{ id: string }>('select id from profiles where user_id = $1', [
      auth.uid,
    ])
  )
  if (existingUser) {
    throw new APIError(400, 'User already exists')
  }

  await removePinnedUrlFromPhotoUrls(body)
  const user = await getUser(auth.uid)
  if (!user) throw new APIError(401, 'Your account was not found')
  if (user.createdTime > Date.now() - HOUR_MS) {
    // If they just signed up, set their avatar to be their pinned photo
    updateUser(pg, auth.uid, { avatarUrl: body.pinned_url })
  }

  console.debug('body', body)

  const { data, error } = await tryCatch(
    insert(pg, 'profiles', { user_id: auth.uid, ...body })
  )

  if (error) {
    log.error('Error creating user: ' + error.message)
    throw new APIError(500, 'Error creating user')
  }

  log('Created profile', data)

  const continuation = async () => {
    try {
      await track(auth.uid, 'create profile', {username: user.username})
    } catch (e) {
      console.error('Failed to track create profile', e)
    }
    try {
      // Let the user fill in the optional form with all their info and pictures before notifying discord of their arrival.
      // So we can sse their full profile as soon as we get the notif on discord. And that allows OG to pull their pic for the link preview.
      // Regardless, you need to wait for at least 5 seconds that the profile is fully in the db—otherwise ISR may cache "profile not created yet"
      await sleep(10 * MINUTE_MS)
      let message: string = `[**${user.name}**](https://www.compassmeet.com/${user.username}) just created a profile`
      if (body.bio) {
        const bioText = jsonToMarkdown(body.bio)
        if (bioText) message += `\n${bioText}`
      }
      await sendDiscordMessage(message, 'members')
    } catch (e) {
      console.error('Failed to send discord new profile', e)
    }
    try {
      const nProfiles = await pg.one<number>(
        `SELECT count(*) FROM profiles`,
        [],
        (r) => Number(r.count)
      )

      const isMilestone = (n: number) => {
        return (
          [15, 20, 30, 40].includes(n) || // early milestones
          n % 50 === 0
        )
      }
      console.debug(nProfiles, isMilestone(nProfiles))
      if (isMilestone(nProfiles)) {
        await sendDiscordMessage(
          `We just reached **${nProfiles}** total profiles! 🎉`,
          'general',
        )
      }

    } catch (e) {
      console.error('Failed to send discord user milestone', e)
    }
  }

  return {
    result: data,
    continue: continuation,
  }
}
