import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { Song } from '../models/Song.js';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

// Path to the built Vue app's index.html (see frontend/README for the build step).
const INDEX_HTML_PATH = path.resolve(__dirname, '../../../frontend/dist/index.html');

function escapeHtml(str = '') {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;');
}

function buildMetaTags(song, siteUrl) {
  const pageUrl = `${siteUrl}/song/${song.slug}`;
  const title = `${song.title} by ${song.artist} | BMMG Records`;
  const description = `Stream "${song.title}" by ${song.artist} on Spotify and Apple Music. Promoted by BMMG Records.`;
  const artwork = song.artwork_url;

  const structuredData = {
    '@context': 'https://schema.org',
    '@type': 'MusicRecording',
    name: song.title,
    byArtist: { '@type': 'MusicGroup', name: song.artist },
    ...(song.album ? { inAlbum: { '@type': 'MusicAlbum', name: song.album } } : {}),
    ...(song.release_date ? { datePublished: song.release_date } : {}),
    image: artwork,
    url: pageUrl,
    recordLabel: { '@type': 'Organization', name: 'BMMG Records' },
  };

  return `
    <title>${escapeHtml(title)}</title>
    <meta name="description" content="${escapeHtml(description)}" />
    <link rel="canonical" href="${pageUrl}" />

    <meta property="og:type" content="music.song" />
    <meta property="og:title" content="${escapeHtml(title)}" />
    <meta property="og:description" content="${escapeHtml(description)}" />
    <meta property="og:image" content="${escapeHtml(artwork)}" />
    <meta property="og:url" content="${pageUrl}" />
    <meta property="og:site_name" content="BMMG Records" />

    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="${escapeHtml(title)}" />
    <meta name="twitter:description" content="${escapeHtml(description)}" />
    <meta name="twitter:image" content="${escapeHtml(artwork)}" />

    <script type="application/ld+json">${JSON.stringify(structuredData)}</script>
  `;
}

/**
 * Builds per-song marketing pixel snippets. Each song owns its own pixel
 * IDs (see backend/database/migrations/001_add_marketing_pixels.sql) since
 * different artists' fanlinks run separate ad campaigns and need their own
 * attribution — there's no site-wide fallback pixel.
 *
 * Sets `window.__bmmgPixelsInjectedServerSide = true` so the client-side
 * fallback in SongLanding.vue (used when the SPA is navigated to client-side
 * rather than freshly requested) knows not to load the base snippets again.
 */
function buildPixelScripts(song) {
  const scripts = [];

  if (song.meta_pixel_id) {
    const id = escapeHtml(song.meta_pixel_id);
    scripts.push(`
    <script>
    !function(f,b,e,v,n,t,s)
    {if(f.fbq)return;n=f.fbq=function(){n.callMethod?
    n.callMethod.apply(n,arguments):n.queue.push(arguments)};
    if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
    n.queue=[];t=b.createElement(e);t.async=!0;
    t.src=v;s=b.getElementsByTagName(e)[0];
    s.parentNode.insertBefore(t,s)}(window, document,'script',
    'https://connect.facebook.net/en_US/fbevents.js');
    fbq('init', '${id}');
    fbq('track', 'PageView');
    </script>
    <noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=${id}&ev=PageView&noscript=1" /></noscript>`);
  }

  if (song.tiktok_pixel_id) {
    const id = escapeHtml(song.tiktok_pixel_id);
    scripts.push(`
    <script>
    !function (w, d, t) {
      w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<e.length;n++)ttq.setAndDefer(e,e[n]);return e},ttq.load=function(e,n){var i="https://analytics.tiktok.com/i18n/pixel/events.js",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=i,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};n=document.createElement("script");n.type="text/javascript",n.async=!0,n.src=i+"?sdkid="+e+"&lib="+t;e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
      ttq.load('${id}');
      ttq.page();
    }(window, document, 'ttq');
    </script>`);
  }

  if (song.custom_head_script) {
    // Trusted input — only authenticated admins can set this, same trust
    // level as any other admin-controlled field. Injected verbatim.
    scripts.push(song.custom_head_script);
  }

  if (scripts.length === 0) return '';

  return `\n<script>window.__bmmgPixelsInjectedServerSide = true;</script>\n${scripts.join('\n')}`;
}

/**
 * For GET /song/:slug requests, injects real meta tags into the built
 * index.html before it's sent, so link previews on Facebook, X, WhatsApp,
 * Telegram and Discord — and search engine crawlers — see accurate,
 * per-song data even though the app itself is a client-rendered SPA.
 * Falls through to next() (serving the plain SPA shell) for drafts,
 * missing songs, or if the production build isn't present yet.
 */
export async function injectSongMeta(req, res, next) {
  try {
    if (!fs.existsSync(INDEX_HTML_PATH)) return next();

    const song = await Song.findBySlug(req.params.slug);
    if (!song || song.status !== 'published') return next();

    const siteUrl = process.env.SITE_URL || `${req.protocol}://${req.get('host')}`;
    const html = fs.readFileSync(INDEX_HTML_PATH, 'utf-8');
    const tags = buildMetaTags(song, siteUrl) + buildPixelScripts(song);

    const injected = html.replace('</head>', `${tags}\n</head>`);
    res.set('Content-Type', 'text/html');
    res.send(injected);
  } catch (err) {
    next(err);
  }
}
