import query from '../server-utils/query.js';
import { Analytics } from '@segment/analytics-node';

type AnalyticsIdentifyEvent = {
  userId: string;
  traits: {
    email: string;
    name: string;
    plan: string;
    createdAt?: Date;
  };
};

export enum ActivityType {
  Login = 'login',
  IncorrectProviderLogin = 'incorrect provider login',
  Signup = 'signup',
  AlternateProviderLogin = 'alternate provider login',
  AlternateProviderSignup = 'new provider signup',
  ExistingEmailSignupAttempt = 'existing email signup attempt',
  GenerateAudio = 'Generate Audio',
  ConductorOverage = 'conductor overage',
  StripePaymentSucceeded = 'Stripe Payment Succeeded',
  PaddleSubscriptionCreated = 'Paddle Subscription Created',
  PaddleSubscriptionUpdated = 'Paddle Subscription Updated',
}

type AnalyticsTrackEvent =
  | {
      name: ActivityType.Login;
      properties: {};
    }
  | {
      name: ActivityType.IncorrectProviderLogin;
      properties: {};
    }
  | {
      name: ActivityType.Signup;
      properties: {};
    }
  | {
      name: ActivityType.AlternateProviderLogin;
      properties: {};
    }
  | {
      name: ActivityType.AlternateProviderSignup;
      properties: {};
    }
  | {
      name: ActivityType.ExistingEmailSignupAttempt;
      properties: {};
    }
  | {
      name: ActivityType.GenerateAudio;
      properties: {
        prompt: string;
      };
    }
  | {
      name: ActivityType.ConductorOverage;
      properties: {
        requestCount: number;
        userCallLimitPer8Hours: number;
      };
    }
  | {
      name: ActivityType.StripePaymentSucceeded;
      properties: {
        amount: number;
        subscription: string;
        plan: string;
      };
    }
  | {
      name: ActivityType.PaddleSubscriptionCreated;
      properties: {
        plan: string;
        isTrial: boolean;
      };
    }
  | {
      name: ActivityType.PaddleSubscriptionUpdated;
      properties: {
        previousPlan: string;
        change: string;
      };
    };

const analytics = new Analytics({ writeKey: process.env.SEGMENT_NODE_KEY });

// Segment best practices: https://segment.com/docs/connections/sources/catalog/libraries/server/node/quickstart/
// When you’re using the Node library, you don’t need to identify a user on every request they make to your servers.
// Instead, Segment recommends calling identify a single time when the user’s account is first created,
// and only identifying again later when their traits change.
export const identifyUser = (identifyEvent: AnalyticsIdentifyEvent) => {
  if (process.env.NODE_ENV !== 'production') {
    console.log('Would identify:', identifyEvent);
    return;
  }

  if (analytics) {
    analytics.identify({
      userId: identifyEvent.userId,
      traits: {
        ...identifyEvent.traits,
      },
    });
  } else {
    console.error('event tracking failed - analytics not set');
  }
};

const sendActivityToSegment = (userId: string, event: AnalyticsTrackEvent) => {
  setTimeout(() => {
    if (process.env.NODE_ENV !== 'production') {
      console.log('Would track:', event);
      return;
    }

    if (analytics) {
      analytics.track({
        userId: userId,
        event: event.name,
        properties: {
          ...event.properties,
        },
      });
    } else {
      console.error('event tracking failed - analytics not set');
    }
  });
};

const insertActivityIntoDatabase = async (userId, activityType: string, isFrontend: boolean) => {
  await query(`INSERT INTO activity (user_id, action, is_frontend) VALUES ($1, $2, $3)`, [
    userId,
    activityType,
    isFrontend,
  ]);
};

const trackServerEvent = async (userId, event: AnalyticsTrackEvent) => {
  await sendActivityToSegment(userId.toString(), event);
  await insertActivityIntoDatabase(userId, event.name, false);
};

export default trackServerEvent;
