const fs = require("fs");
const path = require("path");
const csv = require("csv-parser");
const React = require("react");
const dotenv = require("dotenv");
const ReactDOMServer = require("react-dom/server");
const TemplatePageModule = require("./build/components/jamtracks/JKJamTracksLandingTemplatePage");
const ArtistTemplatePageModule = require("./build/components/jamtracks/JKJamTracksArtistLandingTemplatePage");

var csvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui.${process.env.USER}.csv`
var artistCsvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui_artists.${process.env.USER}.csv`

var sitemapPath = path.join(__dirname, "..", "public", "sitemap.xml");
const clear_sitemap = () => {
    fs.writeFileSync(sitemapPath, "");

    // Add the root element
    fs.writeFileSync(sitemapPath, `<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n`, { flag: 'a' }); 

    // Add the root url
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}</loc></url>\n`, { flag: 'a' });

    // Add standard URLs specific to this site, such as:
    // All prefix with /public
 

    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/</loc></url>\n`, { flag: 'a' });
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/privacy</loc></url>\n`, { flag: 'a' } );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/help</loc></url>\n`, { flag: 'a' }    );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/knowledge-base</loc></url>\n`, { flag: 'a' }  );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/help-desk</loc></url>\n`, { flag: 'a' } );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/forum</loc></url>\n`, { flag: 'a' } );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/unsubscribe</loc></url>\n`, { flag: 'a' } );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/downloads</loc></url>\n`, { flag: 'a' } );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/public/downloads-legacy</loc></url>\n`, { flag: 'a' } );
    
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/auth/login</loc></url>\n`, { flag: 'a' });
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/auth/signup</loc></url>\n`, { flag: 'a' }  );
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/auth/forget-password</loc></url>\n`, { flag: 'a' } );

    // Add the closing root element
}

const add_song_to_sitemap = (artistSlug, songSlug) => {
    fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/backing-tracks/${artistSlug}/${songSlug}</loc></url>\n`, { flag: 'a' });
}

const add_artist_to_sitemap = (artistSlug) => {
     fs.writeFileSync(sitemapPath, `<url><loc>${process.env.REACT_APP_BASE_URL}/backing-tracks/${artistSlug}</loc></url>\n`, { flag: 'a' });
}

const close_sitemap = () => {
    fs.writeFileSync(sitemapPath, "</urlset>", { flag: 'a' } );
}

/**
 * Loads a CSV file into an array of objects.
 * @param {string} csvPath - The path to the CSV file.
 * @returns {Promise<Array<Object>>} - A promise that resolves with the parsed CSV data.
 */
const load_csv = (csvPath) => {
    return new Promise((resolve, reject) => {
      const results = [];
      fs.createReadStream(csvPath)
        .pipe(csv())
        .on('data', (data) => results.push(data))
        .on('end', () => resolve(results))
        .on('error', (error) => reject(error));
    });
  };

/**
 * Finds all songs for a given artist based on the original_artist_slug
 * and sorts them alphabetically by the `slug` field.
 * @param {string} artistSlug - The original_artist_slug to match.
 * @param {Array<Object>} songsCsv - The songs CSV data.
 * @returns {Array<Object>} - A sorted array of matching song objects.
 */
const collect_songs_for_artist = (artistSlug, songsCsv) => {
    return songsCsv
      .filter((song) => song.original_artist_slug === artistSlug)
      .sort((a, b) => a.slug.localeCompare(b.slug)); // Sort alphabetically by slug
  };

  
const init = () => {
    const node_env = process.env.NODE_ENV || 'development';
    const environment = process.env.ENVIRONMENT || 'development';
    console.log(`environment=${environment} node_env=${node_env}`);
    console.log(dotenv.config({ path: `../.env.${environment}` }));

    if (environment === "production" || environment === "staging") {
        csvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui.${environment}.csv`;
        artistCsvFilePath = `jamtracks-for-env/jam_tracks_for_jam_ui_artists.${environment}.csv`;
    }

    console.log("Song csv file", csvFilePath);
    console.log("Artist csv file", artistCsvFilePath);

    if (!process.env.PUBLIC_URL) {
        console.log("setting public url", process.env.REACT_APP_BASE_URL);
        process.env.PUBLIC_URL =  process.env.REACT_APP_BASE_URL;
    }

    clear_sitemap();


//const __dirname = path.resolve(path.dirname(''));

    console.log("init done successfully")
}

const generateSongPages = async (render) => {
    const rows = [];

    const OUTPUT_DIR = path.join(__dirname, "..", "public", "backing-tracks");

    if (!fs.existsSync(OUTPUT_DIR)) {
        fs.mkdirSync(OUTPUT_DIR, { recursive: true });
    }

    console.log("generatPages starting")


    const TemplatePage = TemplatePageModule.default;

    fs.createReadStream(csvFilePath)
        .pipe(csv())
        .on("data", (row) => rows.push(row))
        .on("end", async () => {
            console.log(`Processing ${rows.length} rows...`);

            for (const row of rows) {
                // id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, URL, licensor, vendor_id
                const { id, original_artist, name, original_artist_slug, name_slug, plan_code, slug, allow_free } = row;
                const artist = original_artist;
                const song = name;
                const location = `/backing-tracks/${original_artist_slug}/${name_slug}`;
                const fullPath = process.env.REACT_APP_BASE_URL + location;
                const logoPath = process.env.REACT_APP_BASE_URL + "/favicon.svg";

                add_song_to_sitemap(original_artist_slug, name_slug);

                console.log(`Generating ${artist} - ${song}`);

                const html = render
                    ? ReactDOMServer.renderToStaticMarkup(
                        React.createElement(TemplatePage, { id, plan_code, slug, artist, song, location })
                    )
                    : "";
                const fullHtml = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="shortcut icon" href="/favicon.svg">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>${artist} - ${song} - Free Backing Track</title>
    <link rel="stylesheet" href="${process.env.REACT_APP_BASE_URL}/css/theme.css">
    <meta name="description" content="Get free ${song} by ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
    <meta name="keywords" content="Backing Track, ${artist}, ${song}, Instrumental">
    <meta name="author" content="JamKazam">
    
    <!-- Open Graph (Facebook, LinkedIn, etc.) -->
    <meta property="og:title" content="${artist} - ${song} | Free Backing Track">
    <meta property="og:description" content="Get free ${song} by ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
    <meta property="og:image" content="${logoPath}">
    <meta property="og:url" content="${fullPath}">
    <meta property="og:type" content="music.song">
    
    <!-- Twitter Cards -->
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="${artist} - ${song} | Free Backing Track">
    <meta name="twitter:description" content="Get free ${song} by ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
    <meta name="twitter:image" content="${logoPath}">
    
    <!-- Canonical URL -->
    <link rel="canonical" href="${fullPath}" />
    
    <!-- Structured Data (Schema.org) -->
    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "MusicRecording",
      "name": "${song}",
      "byArtist": {
        "@type": "MusicGroup",
        "name": "${artist}"
      },
      "url": "${fullPath}",
      "image": "${logoPath}"
    }
    </script>
    <script>
        window.jamtrack_data = {
            id: "${id}",
            plan_code: "${plan_code}",
            slug: "${slug}",
            artist: "${artist}",
            song: "${song}",
            location: "${location}"
        }
    </script>
</head>
<body>
    <div id="root">${html}</div>
    <script src="/js/client-hydrate.bundle.js"></script>
</body>
</html>`;

                const ARTIST_DIR = path.join(OUTPUT_DIR, original_artist_slug);

                if (!fs.existsSync(ARTIST_DIR)) {
                    fs.mkdirSync(ARTIST_DIR, { recursive: false });
                }

                const finalOutputPath = process.env.NODE_ENV === "development" ? `${name_slug}.html` : `${name_slug}.html`;
                const outputFilePath = path.join(ARTIST_DIR, finalOutputPath);
                fs.writeFileSync(outputFilePath, fullHtml);
                console.log(`Generated: ${outputFilePath}`);
            }

            console.log("All pages generated!");
        });
};

const generateArtistPages = async (render) => {
    const rows = [];

    const OUTPUT_DIR = path.join(__dirname, "..", "public", "backing-tracks");

    if (!fs.existsSync(OUTPUT_DIR)) {
        fs.mkdirSync(OUTPUT_DIR, { recursive: true });
    }

    console.log("generatPages starting")


    const TemplatePage = TemplatePageModule.default;

    const songs_csv = await load_csv(csvFilePath);

    fs.createReadStream(artistCsvFilePath)
        .pipe(csv())
        .on("data", (row) => rows.push(row))
        .on("end", async () => {
            console.log(`Processing ${rows.length} rows...`);

            for (const row of rows) {
                const { original_artist, original_artist_slug, url } = row;
                const artist = original_artist;
                
                const matchingSongs = collect_songs_for_artist(original_artist_slug, songs_csv);
                console.log(`Found ${matchingSongs.length} songs for ${artist}`);

                const location = `/backing-tracks/${original_artist_slug}`;
                const fullPath = process.env.REACT_APP_BASE_URL + location;
                const logoPath = process.env.REACT_APP_BASE_URL + "/favicon.svg";

                add_artist_to_sitemap(original_artist_slug);
                console.log(`Generating ${artist}`);

                const songs = matchingSongs.map((song) => {
                    return {
                        name: song.name,
                        plan_code: song.plan_code,
                        url: process.env.REACT_APP_BASE_URL + "/backing-tracks/" + song.original_artist_slug + "/" + song.name_slug
                    }
                });
                const html = render
                    ? ReactDOMServer.renderToStaticMarkup(
                        React.createElement(ArtistTemplatePage, { artist, original_artist_slug, location })
                    )
                    : "";
                const fullHtml = `<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="shortcut icon" href="/favicon.svg">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>${artist} - Free Backing Track</title>
    <link rel="stylesheet" href="${process.env.REACT_APP_BASE_URL}/css/theme.css">
    <meta name="description" content="Get a free ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
    <meta name="keywords" content="Backing Track, ${artist}, Instrumental">
    <meta name="author" content="JamKazam">
    
    <!-- Open Graph (Facebook, LinkedIn, etc.) -->
    <meta property="og:title" content="${artist} | Free Backing Track">
    <meta property="og:description" content="Get a free ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
    <meta property="og:image" content="${logoPath}">
    <meta property="og:url" content="${fullPath}">
    <meta property="og:type" content="music.song">
    
    <!-- Twitter Cards -->
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="${artist} | Free Backing Track">
    <meta name="twitter:description" content="Get a free ${artist} backing track, plus free tools to mute any part, slow down for practice, record yourself, more">
    <meta name="twitter:image" content="${logoPath}">
    
    <!-- Canonical URL -->
    <link rel="canonical" href="${fullPath}" />
    
    <script>
        window.jamtrack_data = {
            artist: "${artist}",
            original_artist_slug: "${original_artist_slug}",
            location: "${location}",
            songs: ${JSON.stringify(songs)}
        }
    </script>
</head>
<body>
    <div id="root">${html}</div>
    <script src="/js/client-hydrate.bundle.js"></script>
</body>
</html>`;

                const finalOutputPath = process.env.NODE_ENV === "development" ? `${original_artist_slug}.html` : `${original_artist_slug}.html`;
                const outputFilePath = path.join(OUTPUT_DIR, finalOutputPath);
                fs.writeFileSync(outputFilePath, fullHtml);
                console.log(`Generated: ${outputFilePath}`);
            }

            close_sitemap();

            console.log("All pages generated!");
        });
};

let render = false;
if (process.argv.length > 2) {
    render = process.argv[2] === "true" || process.argv[2] === "yes" || process.argv[2] === "1";
}

init()
generateSongPages(render);

generateArtistPages(render);
