const express = require('express');
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');

let channelsPath = path.resolve(__dirname, 'channels.json');
let channels = JSON.parse(fs.readFileSync(channelsPath, 'utf8'));

fs.watch(channelsPath, (eventType, filename) => {
    if (eventType === 'change') {
        console.log(`channels.json was updated, reloading...`);
        channels = JSON.parse(fs.readFileSync(channelsPath, 'utf8'));
    }
});

const app = express();
const port = 8080;
const tmp_folder = '/tmp/ramdisk/mpegts'

async function startStreamlink(channel) {
    const useragent = channel.useragent;
    const authorization = channel.authorization;
    const proxy = channel.proxy;
    const key1 = channel.key1;
    const key2 = channel.key2;
    const key3 = channel.key3;
    let resolution = channel.resolution;
    resolution = 'res=' + resolution;

    let args = [
        channel.url,
        '--header', `User-Agent:${useragent}`,
        '--use-shaka-packager',
        '--log-level', 'INFO',
        '--live-real-time-merge',
        '--live-pipe-mux',
        '--live-keep-segments', 'false',
        '-sv', 'best',
        '-sa', 'best2',
        '--tmp-dir', tmp_folder,
        '--del-after-done', 'true'
    ];
    if (authorization) {
        args.splice(2, 0, '--header', `Authorization=${authorization}`);
    }
    if (proxy) {
        args.splice(2, 0, '--custom-proxy', proxy);
    }
    if (key1) {
        args.splice(4, 0, '--key', key1);
    }
    if (key2) {
        args.splice(6, 0, '--key', key2);
    }
    if (key3) {
        args.splice(6, 0, '--key', key3);
    }
    return spawn('N_m3u8DL-RE', args);
}

app.get('/stream/:channelName', async (req, res) => {
    const channelName = req.params.channelName;
    console.log(`Received request for /stream/${channelName}`);

    const channel = channels[channelName];

    if (!channel) {
        res.status(404).send('Channel not found');
        return;
    }

    console.log(`Starting Streamlink command for channel: ${channelName}`);

    try {
        let streamlinkProcess = await startStreamlink(channel);
        res.setHeader('Content-Type', 'video/MP2T');
        streamlinkProcess.stdout.pipe(res);
        streamlinkProcess.stderr.on('data', data => {
            console.error(`Streamlink: ${data}`);
        });
        streamlinkProcess.on('close', code => {
            console.log(`Streamlink process exited with code ${code}`);
            res.end();
        });
        res.on('close', () => {
            console.log(`Response closed, killing Streamlink process`);
            streamlinkProcess.kill();
            if (fs.existsSync(tmp_folder)) {
                fs.rmSync(tmp_folder, { recursive: true });
            }
        });
        req.on('abort', () => {
            console.log(`Request aborted, killing Streamlink process`);
            streamlinkProcess.kill();
        });
    } catch (error) {
        console.error(`Streamlink failed: ${error}`);
        res.status(500).send('Streamlink failed');
    }
});

app.listen(port, () => {
    console.log(`Server listening on port ${port}`);
});
