'use client';

import React, { useEffect } from 'react';
import Script from 'next/script';

import type {
  DecrementPayload,
  IdentifyPayload,
  IncrementPayload,
  OpenPanelMethodNames,
  OpenPanelOptions,
  TrackProperties,
} from '@openpanel/web';

export * from '@openpanel/web';

const CDN_URL = 'https://openpanel.dev/op.js';

type OpenPanelComponentProps = Omit<OpenPanelOptions, 'filter'> & {
  profileId?: string;
  cdnUrl?: string;
  filter?: string;
};

const stringify = (obj: unknown) => {
  if (typeof obj === 'object' && obj !== null && obj !== undefined) {
    const entries = Object.entries(obj).map(([key, value]) => {
      if (key === 'filter') {
        return `"${key}":${value}`;
      }
      return `"${key}":${JSON.stringify(value)}`;
    });
    return `{${entries.join(',')}}`;
  }

  return JSON.stringify(obj);
};

export function OpenPanelComponent({
  profileId,
  cdnUrl,
  ...options
}: OpenPanelComponentProps) {
  const methods: { name: OpenPanelMethodNames; value: unknown }[] = [
    {
      name: 'init',
      value: {
        ...options,
        sdk: 'nextjs',
        sdkVersion: process.env.NEXTJS_VERSION!,
      },
    },
  ];
  if (profileId) {
    methods.push({
      name: 'identify',
      value: {
        profileId,
      },
    });
  }
  return (
    <>
      <Script src={cdnUrl ?? CDN_URL} async defer />
      <Script
        dangerouslySetInnerHTML={{
          __html: `window.op = window.op || function(...args) {(window.op.q = window.op.q || []).push(args)};
          ${methods
            .map((method) => {
              return `window.op('${method.name}', ${stringify(method.value)});`;
            })
            .join('\n')}`,
        }}
      />
    </>
  );
}

type IdentifyComponentProps = IdentifyPayload;

export function IdentifyComponent(props: IdentifyComponentProps) {
  return (
    <>
      <Script
        dangerouslySetInnerHTML={{
          __html: `window.op('identify', ${JSON.stringify(props)});`,
        }}
      />
    </>
  );
}

export function useOpenPanel() {
  return {
    track,
    screenView,
    identify,
    increment,
    decrement,
    clear,
  };
}

function track(name: string, properties?: TrackProperties) {
  window.op('track', name, properties);
}

function screenView(properties: TrackProperties) {
  track('screen_view', properties);
}

function identify(payload: IdentifyPayload) {
  window.op('identify', payload);
}

function increment(payload: IncrementPayload) {
  window.op('increment', payload);
}

function decrement(payload: DecrementPayload) {
  window.op('decrement', payload);
}

function clear() {
  window.op('clear');
}
