import type { SchemaBreadcrumbList } from '~/src/lib/utils/toStructuredData/toBreadcrumb';
import type { OrganizationSchema } from '~/src/lib/utils/toStructuredData/toOrganization';
import type { WebsiteSchema } from '~/src/lib/utils/toStructuredData/toWebsite';

import {
  SONGWHIP_FACEBOOK_URL,
  SONGWHIP_INSTAGRAM_URL,
  SONGWHIP_TWITTER_URL,
} from '~/lib/constants';
import { toPublicEndpoint } from '~/src/lib/getPublicEndpoint';
import toBreadcrumb from '~/src/lib/utils/toStructuredData/toBreadcrumb';
import toOrganization from '~/src/lib/utils/toStructuredData/toOrganization';
import toSearchAction from '~/src/lib/utils/toStructuredData/toSearchAction';
import toWebsite from '~/src/lib/utils/toStructuredData/toWebsite';

const noop = () => [];

export type ToStructuredDataExtraProps = {
  pagePath: string;
  pageUrl: string;
  organization: OrganizationSchema;
  toBreadcrumb: (items: any[]) => SchemaBreadcrumbList;
  website: WebsiteSchema;
  [key: string]: any;
};

export type ToStructuredDataExtra = (
  props: ToStructuredDataExtraProps
) => any[] | undefined;

export interface ToStructuredDataProps {
  toStructuredDataExtra?: ToStructuredDataExtra;
  pagePath: string;
  [key: string]: any;
}

const toStructuredData = ({
  toStructuredDataExtra = noop,
  pagePath,
  ...rest
}: ToStructuredDataProps) => {
  const pageUrl = toPublicEndpoint(pagePath);

  const organization = toOrganization({
    url: toPublicEndpoint('/'),
    name: 'Songwhip',
    description:
      'Smart music links that reach every platform. Make free links to your music instantly.',
    imageUrl: toPublicEndpoint(`/static/icons/icon-512x512.png`),
    links: [
      SONGWHIP_FACEBOOK_URL,
      SONGWHIP_TWITTER_URL,
      SONGWHIP_INSTAGRAM_URL,
    ],
  });

  const website = toWebsite({
    url: organization.url,
    name: organization.name,
    organizationId: organization['@id'],
    action: toSearchAction({
      url: toPublicEndpoint('/create?q='),
    }),
  });

  /**
   * A higher-level abstraction around toBreadcrumb()
   */
  const toBreadcrumbWithHome = (items) => {
    return toBreadcrumb({
      ...rest,
      websiteId: website['@id'],
      pageUrl,
      items,
    });
  };

  const items = [
    organization,
    website,

    // extra/page-specific items
    ...(
      toStructuredDataExtra({
        ...rest,
        pagePath,
        pageUrl,
        organization,
        toBreadcrumb: toBreadcrumbWithHome,
        website,
        // guard against returning undefined
      }) || []
    ).filter(Boolean),
  ];

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{
        __html: JSON.stringify({
          '@context': 'https://schema.org',
          '@graph': items,
        }),
      }}
    />
  );
};

export default toStructuredData;
