import { ChallengeToken , AchievementType } from 'common' ; import { getMySQLInstance } from './db/mysql' ; const bonus_condition_sql = { sign_up_first_three_days : `
    SELECT enrolled_at < TIMESTAMPADD(DAY, 3, challenges.start_date) AS win_bonus, client_id AS bonus_winner
    FROM enroll
    LEFT JOIN challenges ON enroll.challenge_id = challenges.id AND challenges.url_token = ?
    WHERE client_id = ?
    ` , invite_signup : `
    SELECT (invitee.id IS NOT NULL) AND (NOW() < TIMESTAMPADD(WEEK, 3, start_date)) AS win_bonus, invitor.client_id AS bonus_winner
    FROM challenges
    LEFT JOIN enroll invitee ON invitee.client_id = ?
        AND invitee.invited_by = ?
        AND invitee.challenge_id = challenges.id
        AND invitee.enrolled_at < TIMESTAMPADD(WEEK, 3, start_date)
    LEFT JOIN enroll invitor ON invitor.url_token = ?
        AND invitor.challenge_id = challenges.id
    WHERE challenges.url_token = ?
    ` , three_day_streak : `
    SELECT MAX(win_bonus) AS win_bonus, bonus_winner
    FROM (
        SELECT
            (enroll.client_id IS NOT NULL) AND (earn.client_id IS NULL) AND (custom_goals.id IS NOT NULL) AND (streaks.id IS NOT NULL) AS win_bonus,
            ? AS bonus_winner
        FROM challenges
        LEFT JOIN achievements ON achievements.name = 'three_day_streak' AND challenges.id = achievements.challenge_id
        LEFT JOIN enroll ON enroll.client_id = ?
            AND challenges.id = enroll.challenge_id
            AND enroll.enrolled_at BETWEEN start_date AND TIMESTAMPADD(WEEK, 3, start_date)
        LEFT JOIN custom_goals ON custom_goals.client_id = enroll.client_id
            AND custom_goals.created_at BETWEEN start_date AND TIMESTAMPADD(WEEK, 3, start_date)
        LEFT JOIN streaks ON streaks.client_id = enroll.client_id
            AND streaks.started_at BETWEEN start_date AND TIMESTAMPADD(DAY, 18, start_date)  # 18 days = 3 weeks - 3 days.
            AND TIMESTAMPDIFF(DAY, streaks.started_at, streaks.last_activity_at) >= 3
            AND TIMESTAMPDIFF(DAY, custom_goals.created_at, streaks.last_activity_at) >= 3
        LEFT JOIN earn ON enroll.client_id = earn.client_id
            AND earn.achievement_id = achievements.id
            AND earned_at BETWEEN TIMESTAMPADD(DAY, -3, streaks.last_activity_at) AND streaks.last_activity_at
        WHERE challenges.url_token = ?
    ) bonus
    GROUP BY bonus_winner
  ` , first_contribution : `
    SELECT count(distinct clips.id) + count(distinct votes.id) = 1 AS win_bonus, user_clients.client_id AS bonus_winner
    FROM user_clients
    LEFT JOIN challenges ON url_token = ?
    LEFT JOIN clips ON clips.client_id = user_clients.client_id AND clips.created_at BETWEEN start_date AND TIMESTAMPADD(WEEK, 3, start_date)
    LEFT JOIN votes ON votes.client_id = user_clients.client_id AND votes.created_at BETWEEN start_date AND TIMESTAMPADD(WEEK, 3, start_date)
    WHERE user_clients.client_id = ?
    GROUP BY user_clients.client_id
    ` , invite_send : `
    SELECT (earn.id IS NULL) AND (NOW() < TIMESTAMPADD(WEEK, 3, start_date)) AS win_bonus, ? AS bonus_winner
    FROM challenges
    LEFT JOIN achievements ON achievements.name = 'invite_send' AND achievements.challenge_id = challenges.id
    LEFT JOIN earn ON earn.client_id = ?
        AND achievement_id = achievements.id
        AND earn.earned_at < TIMESTAMPADD(WEEK, 3, start_date)
    WHERE challenges.url_token = ?
    ` , invite_contribute_same_session : `
    SELECT (earn.id IS NULL) AND (NOW() < TIMESTAMPADD(WEEK, 3, start_date)) AS win_bonus, ? AS bonus_winner
    FROM challenges
    LEFT JOIN achievements ON achievements.name = 'invite_contribute_same_session' AND achievements.challenge_id = challenges.id
    LEFT JOIN earn ON earn.client_id = ?
        AND achievement_id = achievements.id
        AND earn.earned_at < TIMESTAMPADD(WEEK, 3, start_date)
    WHERE challenges.url_token = ?
    ` , } ; const db = getMySQLInstance ( ) ; export const earnBonus = async ( type , args ) => { let earned = false ; const [ [ res ] ] = await db . query ( bonus_condition_sql [ type ] , args ) ; const { win_bonus = false , bonus_winner = '' } = res || { } ; if ( win_bonus && bonus_winner ) { const ret = await db . query ( `
            INSERT INTO earn (achievement_id, client_id) VALUES ((SELECT id FROM achievements WHERE name = ?), ?)
          ` , [ type , bonus_winner ] ) ; earned = ret ?. [ 0 ] ?. affectedRows > 0 ; } return earned ; } ; export const hasEarnedBonus = async ( type , client_id , challenge ) : Promise < boolean > => { const earned = await db . query ( `
      SELECT earn.client_id IS NOT NULL AS earned
      FROM challenges
      LEFT JOIN achievements ON challenges.id = achievements.challenge_id AND achievements.name = ?
      LEFT JOIN earn ON achievements.id = earn.achievement_id
          AND earn.client_id = ?
          AND earn.earned_at < TIMESTAMPADD(WEEK, 3, start_date)
      WHERE challenges.url_token = ?
      ` , [ type , client_id , challenge ] ) ; return ! ! earned ?. [ 0 ] ?. [ 0 ] ?. earned ; } ;