#!/usr/bin/env node
const fs = require('fs');
const http = require('http');
const path = require('path');
const { capitalCase } = require('change-case');
const express = require('express');
const yargs = require('yargs');

const app = express();
const server = http.createServer(app);

app.use(express.json());

const HTTP_STATUS = {
  OK: 200,
  CREATED: 201,
  BAD_REQUEST: 400,
  NOT_FOUND: 404,
  INTERNAL_SERVER_ERROR: 500,
};

yargs.option('port', {
  alias: 'p',
  describe: 'Port number',
  demandOption: false,
  type: 'number',
  default: 3000,
});

yargs.option('path', {
  describe: 'path',
  demandOption: false,
  type: 'string',
});

const argv = yargs.argv;
const port = argv.port;

const getAppDetails = () => {
  const currentDirectory = process.cwd();
  const packageJsonPath = path.join(currentDirectory, 'package.json');
  if (fs.existsSync(packageJsonPath)) {
    const packageJsonData = fs.readFileSync(packageJsonPath);
    const { name, dependencies } = JSON.parse(packageJsonData);
    const lastPackageNamePart = name.split('/').pop();
    const formattedAppName = capitalCase(lastPackageNamePart);
    const dsPrefix = dependencies['@genesislcap/rapid-design-system'] ? 'rapid' : 'zero';
    return { name: formattedAppName, dsPrefix };
  }
};

app.use(express.static(path.resolve(__dirname, '../dist')));

const getTokens = (filePath) => {
  try {
    if (!fs.existsSync(filePath)) {
      return { error: `File not found at path: ${filePath}` };
    }
    const tokensData = fs.readFileSync(filePath);
    return JSON.parse(tokensData);
  } catch (error) {
    return { error: `Error parsing tokens data: ${error.message}` };
  }
};

if (argv.path) {
  const tokensFilePath = path.resolve(process.cwd(), argv.path);
  app.use((req, res, next) => {
    const { name, dsPrefix } = getAppDetails();
    req.appName = name;
    req.dsPrefix = dsPrefix;
    if (req.method !== 'PUT') req.body = tokensFilePath ? getTokens(tokensFilePath) : null;
    next();
  });

  app.put('/api/tokens', (req, res) => {
    if (!req.body) {
      res.status(HTTP_STATUS.BAD_REQUEST).json({ message: 'Missing request body' });
    } else {
      const { tokens } = req.body;
      if (!tokens) {
        res.status(HTTP_STATUS.BAD_REQUEST).json({ message: 'Missing tokens' });
      } else {
        try {
          fs.writeFileSync(tokensFilePath, tokens, { encoding: 'utf8', flag: 'w' });
          console.log('Tokens successfully updated');
          res.status(HTTP_STATUS.CREATED).json({ message: JSON.parse(tokens) });
        } catch (error) {
          res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ message: 'Error saving tokens' });
        }
      }
    }
  });

  app.get('/api/tokens', (req, res) => {
    if (req.body) {
      res.status(HTTP_STATUS.OK).json(req.body);
    } else {
      res.status(HTTP_STATUS.NOT_FOUND).json({ message: 'Tokens file not found' });
    }
  });

  app.get('/api/details', (req, res) => {
    if (req.appName && req.dsPrefix) {
      res.status(HTTP_STATUS.OK).json({ appName: req.appName, dsPrefix: req.dsPrefix });
    } else {
      res.status(HTTP_STATUS.NOT_FOUND).json({ message: 'App name not found' });
    }
  });
} else {
  console.log('Tokens file path not specified, skipping API endpoints');
}

server.listen(port, async () => {
  const url = `http://localhost:${port}`;
  console.log(`Running at ${url}`);
  const open = (await import('open')).default;
  open(url);
});
