/**
 * User activities can be logged either as a backend activity or frontend activity.
 *
 * This file contains route handlers for logging frontend activities.
 * Backend activities are logged in trackServerEvent.ts.
 */

import query from '../server-utils/query.js';
import { declareHandler } from '../server-utils/routesHandler.js';

/**
 * There is no good way to sync this automatically
 * This needs to be synced with the AnalyticsTrackEvent type trackAnalyticsEvent.ts
 *
 * Sections:
 * 1. Arrangement Panel, General Controls
 * 2. Other Controls
 * 3. Onboarding
 * 4. Conversion and Account
 * 5. Export and Share
 * 6. Skills
 * 7. Library
 * 8. Playback
 * 9. Meta
 */
const acceptedActivityTypes = [
  // 1. Arrangement Panel, General Controls
  'New Project',
  'Set Audio Input',
  'Add Track',
  'Move Track',
  'Rename Track',
  'Create Clip(s)',
  'Toggle MIDI Overdub',
  'Grid Size Changed',
  'Grid Lock Toggled',
  'Grid Snap Toggled',
  'Grid Triplets Toggled',
  'Started New Clip',
  'Extended Clip',
  'Set Buffer Size',
  'Toggle Auto Layout',
  'Reset Layout',
  'Connect Node',
  'Replace Device',
  'Adjust Relative Control',
  'Toggled Omnibar',
  'Adjusted Project Loop',
  'Toggle Metronome',
  'Tap BPM Set',
  'BPM Set',
  'Invalid BPM Set',
  'Set Time Signature',
  'Start Recording',
  'Set Count-in',

  // 2. Other Controls
  'Rename Project',
  'Archived Project',
  'Deleted Project',
  'Top Level Menu Clicked',
  'Menu Item Clicked',
  'Action Menu Item Clicked',
  'Auto Color',
  'Open Keyboard Bindings',
  'Change Tooltip Behaviour',

  // 3. Onboarding
  'User categorisation response',
  'Saw Tutorial Modal',
  'Closed Tutorial Modal',
  'Finish Tutorial Clicked',
  'Skip Tutorial Clicked',
  'Clicked Tutorials Link',
  'Sample Project Opened',
  'Open Welcome & Help Skills',
  'Welcome Skill Clicked',
  'Set Welcome Flow Step',
  'Finished Welcome Flow',
  'Skipped Welcome Flow',
  'Loaded Project',
  'Remixed Demo Project',
  'Created Empty Project',
  'Selected Guide Category',
  'Selected Guide',
  'Viewed More Guides',
  'Completed Checklist Step',
  'Completed Checklist',
  'Try Another Checklist Clicked',
  'Checklist Skill View More Guides Button Clicked',
  'New Project Template Selected',
  'Dismissed New Project Modal',
  'Toggled New Project Modal Show Every Time Checkbox',
  'Submitted Welcome Survey',

  // 4. Conversion and Account
  'Open Pro Modal',
  'Click Pro Checkout Button',
  'Close Pro Modal',
  'Upgrade Plan CTA in Skill Clicked',
  'Clicked Discord Link',
  'Clicked Email Us Link',
  'User Reset Password Request',
  'User Delete Account Request',

  // 5. Export and Share
  'Save Project',
  'Save Project As',
  'Export as .wav',
  'Export as .mp3',
  'Download Project as .zip',
  'Opened Generate Sharing Link Modal',
  'Generated Sharing Link',
  'Open Share Modal',
  'Copied Share URL',
  'Updated Shared Track Name',
  'Published to Song Page',
  'Sent Shareable Video to Phone',

  // 6. Skills
  'Activate Skill',
  'Exit Skill',
  'Skill Stack Expand Button Clicked',
  'Send Conductor Message',
  'Click Conductor Button',
  'Conductor Error',
  'Conductor Error Dismissed',
  'Generate Audio',
  'Accept Generated Audio',
  'Reject Generated Audio',
  'Ask for help',
  'Fetched MIDI AI Suggestions',
  'Chose MIDI AI Suggestion',
  'Clicked Composer "Tips & Tricks" Button',

  // 7. Library
  'Open Library Button Clicked',
  'Use Sample',
  'Search for Sample',
  'Select Sample Pack',
  'Unlock Device Code',
  'Select Preset',

  // 8. Playback
  'Toggled Playback',
  'Auditioned Suggested Notes for 1s',
  'Played for 30 seconds continuously',
  'Note On',
  'Clicked Add Instrument Button',
  'Selected "Add Instrument" Role',
  'Added preset instrument',
  'Changed preset instrument',
  'Unlocked chain editor',

  // 9. Meta
  'No-op click on empty selection',
  'Double Clicked on Empty Part Of Arrangement',
  'Mobile Capture Triggered',
  'Missing Browser Features',
  'Entered Experiment',
  'Experiment Branch Assigned',
];

export const logFrontendActivity = declareHandler({
  func: async (req, res) => {
    const userId = req.user.id;
    const activities = req.body;

    if (!Array.isArray(activities)) {
      res.status(400);
      res.send({ success: false, error: 'Invalid activities format' });
      return;
    }

    const activitiesToPush = [];

    let error = false;
    for (const activity of activities) {
      const activityType = activity.name;
      // Check if activity is in whitelist
      if (!acceptedActivityTypes.includes(activityType)) {
        continue;
      }

      const activityParameters = activity.properties;
      if (!activityParameters) {
        error = true;
        continue;
      }
      activitiesToPush.push({ activityType, activityParameters });
    }

    if (error) {
      res.status(400);
      res.send({ success: false, error: 'Invalid activities format' });
      return;
    }

    for (const activity of activitiesToPush) {
      const { activityType, activityParameters } = activity;

      query(`INSERT INTO activity (user_id, action, properties, is_frontend) VALUES ($1, $2, $3::jsonb, true)`, [
        userId,
        activityType,
        JSON.stringify(activityParameters),
      ]);
    }

    res.status(200);
    res.send({ success: true, error: null });
  },
});
