import { getGameRating, getUrl, getLanguage } from './getters';
import { cleanHTML } from './strings';

/* HardCoded Start */
const customSchema = {
  // Matrix
  'playcasino.co.za': 'Playcasino',
  'norskespilleautomater.com': 'Norske Spilleautomater',
  'irishluck.ie': 'Irish Luck',
  // Rage PPC
  'bekijksport.nl': 'Bekijk Sport',
  'bestsports.gr': 'Best Sports',
  'sesport.dk': 'Se Sport',
  'watchfooty.co.uk': 'WatchFooty',
  // Rage SEO
  'fotballstreams.com': 'Fotball Streams',
  'fussballstreams.com': 'Fussball Streams',
  'livefotbollonline.se': 'Live Fotboll Online',
  'livestreamsvoetbal.nl': 'Live Streams Voetbal',
  'sefodbold.dk': 'Se Fodbold',
  'verfutbolonline.net': 'Ver Futbol Online',
  'watchsport.gr': 'Watch Sport',
};

const socialLinks = [
  'facebook',
  'instagram',
  'linkedin',
  'spotify',
  'twitter',
  'wikipedia',
  'youtube',
];
/* HardCoded End */

function checkSchemaProp(prop) {
  return (
    (!Array.isArray(prop) || (Array.isArray(prop) && prop.length)) &&
    prop !== undefined &&
    prop !== null &&
    prop !== ''
  );
}

export function generateSchemaObject(schema) {
  return Object.keys(schema).reduce((obj, key) => {
    if (
      Object.prototype.toString.call(schema[key]) === '[object Object]' &&
      Object.keys(schema[key]).length
    ) {
      obj[key] = generateSchemaObject(schema[key]);
    }

    if (checkSchemaProp(schema[key])) {
      obj[key] = schema[key];
    }

    return obj;
  }, {});
}

const prosAndConsData = (pageObj) => {
  const prosAndConstObj =
    pageObj?.sections?.main?.modules?.find((elm) => elm?.name === 'pros_and_cons') || {};

  // There are url keys because it is required
  // otherwise it would throw errors
  return (
    Object.keys(prosAndConstObj).length > 0 && {
      ...(prosAndConstObj?.pros?.length && {
        positiveNotes: {
          '@type': 'ItemList',
          itemListElement:
            prosAndConstObj?.pros?.map((elm, index) => ({
              '@type': 'ListItem',
              position: index + 1,
              url: `${getUrl('/')}#${elm}`,
              name: elm,
            })) || [],
        },
      }),
      ...(prosAndConstObj?.cons?.length && {
        negativeNotes: {
          '@type': 'ItemList',
          itemListElement:
            prosAndConstObj?.cons?.map((elm, index) => ({
              '@type': 'ListItem',
              position: index + 1,
              url: `${getUrl('/')}#${elm}`,
              name: elm,
            })) || [],
        },
      }),
    }
  );
};

export function breadcrumbsSchema({
  path,
  title,
  breadcrumbs = [],
  siteSchema: { site_name: siteName } = {},
}) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: [
      {
        '@type': 'ListItem',
        position: 1,
        name: siteName,
        item: {
          '@type': 'Thing',
          '@id': getUrl('/'),
          url: getUrl('/'),
        },
      },
      ...breadcrumbs.map((breadcrumb, index) => ({
        '@type': 'ListItem',
        position: index + 2,
        name: breadcrumb?.label,
        item: {
          '@type': 'Thing',
          '@id': getUrl(breadcrumb.path),
          url: getUrl(breadcrumb.path),
        },
      })),
      {
        '@type': 'ListItem',
        name: title,
        position: breadcrumbs.length + 2,
        item: {
          '@type': 'Thing',
          '@id': getUrl(path),
          url: getUrl(path),
        },
      },
    ],
  };

  return JSON.stringify(generateSchemaObject(schema));
}

export function processSpeakableModules(modules) {
  const speakAbleModules = [];

  modules.forEach((module) => {
    if (module?.name === 'content' && module.speakable_enabled === '1') {
      const id = module.anchor_slug ? module.anchor_slug : `module_${module.module_value_id}`;
      const htag = module.tag ? module.tag : 'h2';
      const moduleSchema = {
        '@context': 'https://schema.org',
        '@type': 'WebPage',
        name: module.title,
        speakable: {
          '@type': 'SpeakableSpecification',
          cssSelector: [`#${id} ${htag}`, `#${id} p`],
        },
        url: getUrl(module.path),
      };

      speakAbleModules.push(JSON.stringify(generateSchemaObject(moduleSchema)));
    }
  });

  return speakAbleModules;
}

export function webPageSchema(page, pageImage) {
  const speakAbleModules = processSpeakableModules(page?.sections?.main?.modules || []);

  const schema = {
    '@context': 'https://schema.org',
    '@type': 'WebPage',
    '@id': `${getUrl(page?.path)}#webpage`,
    url: getUrl(page?.path),
    name: page?.meta_title || '',
    description: page?.meta_description || '',
    inLanguage: getLanguage(page?.language),
    datePublished: page?.created_at,
    dateModified: page?.updated_at,
    isPartOf: {
      '@type': 'WebSite',
      '@id': `${process.env.GATSBY_SITE_URL}#website`,
      url: `${process.env.GATSBY_SITE_URL}`,
      inLanguage: getLanguage(page?.language),
    },
    reviewedBy: page?.reviewer_id
      ? {
          '@type': 'Person',
          name: page?.reviewer?.name,
          jobTitle: page?.reviewer?.author_title,
          image: page?.reviewer?.image_object?.url,
          email: page?.reviewer?.email_address,
          nationality: {
            '@type': 'Country',
            name: page?.reviewer?.country?.name,
          },

          knowsAbout: page?.reviewer?.knows_abouts?.map((item) => ({
            '@type': item?.type,
            name: item?.name,
            sameAs: item?.links.map((link) => link?.link).filter((link) => link),
          })),
        }
      : '',
    publisher: {
      '@type': 'Organization',
      name: page?.siteSchema?.site_name || '',
      alternateName: page?.siteSchema?.alias_site_name || '',
      foundingDate: page?.siteSchema?.organization_founding_date || '',
      publishingPrinciples: page?.siteSchema?.publishing_principles,
      logo: {
        '@type': 'ImageObject',
        url: pageImage,
      },
      contactPoint: page?.authors?.map((author) => ({
        '@type': 'ContactPoint',
        contactType: 'Author',
        name: author.name || '',
        email: author.email_address || '',
        url: getUrl(author.profile_page_path || '/'),
      })),
      sameAs: socialLinks
        .map((socialLink) => page?.siteSchema?.[socialLink])
        .filter((socialLink) => socialLink),
      ...(page?.knowsAbout ? { knowsAbout: page?.knowsAbout } : {}),
    },
    author: {
      '@type': 'Person',
      name: page?.author?.name,
      jobTitle: page?.author?.author_title,
      image: page?.author?.image_object?.url,
      email: page?.author?.email_address,
      nationality: {
        '@type': 'Country',
        name: page?.author?.country?.name,
      },

      knowsAbout: page?.author?.knows_abouts?.map((item) => ({
        '@type': item?.type,
        name: item?.name,
        sameAs: item?.links.map((link) => link?.link).filter((link) => link),
      })),
    },
  };
  if (speakAbleModules.length > 0) {
    schema['@speakAbleModules'] = speakAbleModules.map((module) => JSON.parse(module));
  }

  if (pageImage) {
    schema.primaryImageOfPage = {
      '@type': 'ImageObject',
      '@id': `${getUrl(page.path)}#primaryimage`,
      url: pageImage,
      inLanguage: getLanguage(page.language),
    };
  }

  if (page?.seo_keywords) {
    schema.keywords = page.seo_keywords;
  }

  return JSON.stringify(generateSchemaObject(schema));
}

export function organizationSchema(page, pageImage) {
  const schema = {
    '@context': 'https://schema.org',
    '@type': 'Organization',
    '@id': `${getUrl(page.path)}#organization`,
    url: process.env.GATSBY_SITE_URL,
    name: page.siteSchema?.site_name,
    logo: pageImage,
    sameAs: socialLinks
      .map((socialLink) => page.siteSchema?.[socialLink])
      .filter((socialLink) => socialLink),
  };

  return JSON.stringify(generateSchemaObject(schema));
}

export function moduleSchemas(modules, path, page, pageImage) {
  const schema = modules.map((module, index) => {
    switch (module.name) {
      case 'faq': {
        if (module?.render_schema === '1') {
          const moduleSchema = {
            '@context': 'https://schema.org',
            '@type': 'FAQPage',
            '@id': `${getUrl(path)}#faqpage${index === 0 ? '' : index}`,
            mainEntity: module.items?.map((item) => ({
              '@type': 'Question',
              acceptedAnswer: {
                '@type': 'Answer',
                text: cleanHTML(item.answer),
              },
              name: cleanHTML(item.question),
            })),
          };

          return JSON.stringify(generateSchemaObject(moduleSchema));
        }
        return null;
      }
      case 'iframe': {
        if (module?.iframe_source) {
          const IframeModule = module?.iframe_video_object;
          const moduleSchema = {
            '@context': 'https://schema.org',
            '@type': 'VideoObject',
            name: IframeModule?.description,
            thumbnailUrl: IframeModule?.thumbnailUrl,
            duration: IframeModule?.duration,
            contentUrl: IframeModule?.contentUrl,
            embedUrl: IframeModule?.embedUrl,
            publisher: {
              '@type': 'Organization',
              name:
                page.siteSchema?.owned_by ||
                customSchema[process.env.GATSBY_SITE_NAME] ||
                page.siteInfo?.site_name ||
                process.env.GATSBY_SITE_NAME,
              logo: {
                '@type': 'ImageObject',
                url:
                  (page.siteInfo?.site_logo &&
                    `${process.env.IMAGE_CDN_URL}/${page.siteInfo.site_logo}`) ||
                  page.featured_image_object?.url ||
                  pageImage,
                width: 200,
                height: 31,
              },
            },
            hasPart: module?.iframe_clips?.map((clip) => ({
              '@type': 'Clip',
              name: clip?.name,
              startOffset: clip?.startOffset,
              endOffset: clip?.endOffset,
              url: clip?.url,
            })),
          };
          return JSON.stringify(generateSchemaObject(moduleSchema));
        }
      }
      default: {
        return null;
      }
    }
  });

  const filteredSchema = schema.filter((item) => item !== null);

  return filteredSchema;
}

export function templateSchemas(page, pageImage) {
  const sharedProps = {
    author: {
      '@type': 'Person',
      name: page.author?.name?.substring(0, 100),
      url: getUrl(page.author?.profile_page_path || '/'),
      ...(page?.author?.knowsAbout ? { knowsAbout: page?.author?.knowsAbout } : {}),
    },
    publisher: {
      '@type': 'Organization',
      name:
        page.siteSchema?.owned_by ||
        customSchema[process.env.GATSBY_SITE_NAME] ||
        page.siteInfo?.site_name ||
        process.env.GATSBY_SITE_NAME,
      logo:
        (page.siteInfo?.site_logo && `${process.env.IMAGE_CDN_URL}/${page.siteInfo.site_logo}`) ||
        page.featured_image_object?.url ||
        pageImage,
    },
  };
  switch (page.relation_type) {
    case 'article': {
      const schema = {
        '@context': 'https://schema.org',
        '@type': 'Article',
        '@id': `${getUrl(page.path)}#article`,
        url: getUrl(page.path),
        headline: page.title,
        datePublished: page.created_at,
        dateModified: page.updated_at,
        mainEntityOfPage: {
          '@type': 'WebPage',
          url: process.env.GATSBY_SITE_URL,
        },
        ...sharedProps,
      };

      return JSON.stringify(generateSchemaObject(schema));
    }
    case 'operator': {
      const schema = {
        '@context': 'https://schema.org',
        '@type': 'Review',
        '@id': `${getUrl(page.path)}#review`,
        ...prosAndConsData(page),
        name: page.relation?.name || '',
        reviewBody: page.extra_fields?.operator_summary || '',
        itemReviewed: {
          '@type': 'Organization',
          url: getUrl(page.path),
          name: page.title || '',
          image: page.relation?.logo_url_object?.url,
        },
        reviewRating: {
          '@type': 'Rating',
          bestRating: '5',
          worstRating: '0',
          ratingValue: page.relation?.rating?.toString() || '',
        },
        ...sharedProps,
      };

      return JSON.stringify(generateSchemaObject(schema));
    }
    case 'game': {
      const rating = Math.floor(getGameRating(page.relation) * 2);
      const schema = {
        '@context': 'https://schema.org',
        '@type': 'VideoGame',
        '@id': `${getUrl(page.path)}#videogame`,
        url: getUrl(page.path),
        name: page.relation?.name || '',
        description: page.extra_fields?.game_summary || '',
        operatingSystem: 'Multi-platform',
        applicationCategory: ['Game'],
        author: {
          '@type': 'Organization',
          name: process.env.GATSBY_SITE_NAME,
          url: process.env.GATSBY_SITE_URL,
        },
        review: {
          '@type': 'Review',
          ...prosAndConsData(page),
          name: page.relation?.name || '',
          reviewRating: {
            '@type': 'Rating',
            bestRating: '10',
            worstRating: '0',
            ratingValue: rating?.toString() || '',
          },
          ...sharedProps,
        },
      };

      return JSON.stringify(generateSchemaObject(schema));
    }
    default:
      return null;
  }
}

export function schemaGenerator(page = {}, pageImage) {
  const isHomepage = page.path === '/';

  const jsonSchema = [
    // Page Schema
    ...(page.seo_json_schemas && page.seo_json_schemas.length
      ? page.seo_json_schemas
      : [page.seo_json_schema]),
    // Breadcrumbs Schema
    !isHomepage ? breadcrumbsSchema(page) : null,
    // Modules Schemas
    webPageSchema(page, pageImage),
    organizationSchema(page, pageImage),
    templateSchemas(page, pageImage),
    ...(page.sections?.main?.modules
      ? moduleSchemas(page.sections.main.modules, page.path, page, pageImage)
      : [null]),
  ];

  return jsonSchema;
}
