import { type Request, type Response } from "express";
import UserModel, { values } from '../models/userModel';
import MediaModel, { Table } from '../models/mediaModel';


function fromStringToTable(value: string): (Table | undefined) {
  if (value.localeCompare("games") == 0) return Table.games;
  if (value.localeCompare("movies") == 0) return Table.movies;
  if (value.localeCompare("series") == 0) return Table.series;
  return;
}

async function createMed(req: Request, res: Response) {
  const mediaCode: string = req.body.code;

  const omdb_key = await UserModel.getValue(values.omdb_key);

  if (!omdb_key) {
    return res.status(500).json({ message: 'Error when creating media' });
  }

  // remove the tt in front in DB its stored as number
  const sub = mediaCode.substring(2);
  const cleanCode = parseInt(sub);

  try {

    const seriesFound = await MediaModel.findOne(Table.series, cleanCode);
    if (seriesFound.length != 0) {
      return res.status(409).json({ message: 'Media already exists' });
    }

    const moviesFound = await MediaModel.findOne(Table.movies, cleanCode);
    if (moviesFound.length != 0) {
      return res.status(409).json({ message: 'Media already exists' });
    }

    const uri = `http://www.omdbapi.com/?i=${mediaCode}&apikey=${omdb_key}`;
    const mJson = await fetch(uri);
    const mData = await mJson.json();

    if (mData.Response == 'False') {
      return res.status(404).json({ message: 'wrong code' });
    }

    const media = {
      code: mediaCode,
      title: mData.Title,
      released: mData.Released,
      webImg: mData.Poster,
    };

    if (mData.Type.localeCompare("movie") == 0) {
      const savedMedia = await MediaModel.save(Table.movies, cleanCode, mData.Title, mData.Released, mData.Poster);
    }
    else if (mData.Type.localeCompare("series") == 0) {
      const savedMedia = await MediaModel.save(Table.series, cleanCode, mData.Title, mData.Released, mData.Poster);
    }

    return res.status(201).json(media);
  } catch (err) {
    return res.status(500).json({ message: 'Error when creating media' });
  }
}

async function createGame(req: Request, res: Response) {
  var gameCode = req.body.code;

  const twitch_client_id = await UserModel.getValue(values.twitch_client_id);
  const twitch_client_secret = await UserModel.getValue(values.twitch_client_secret);

  if (!twitch_client_id || !twitch_client_secret) {
    return res.status(500).json({ message: 'Error when creating game' });
  }

  try {
    const gameFound = await MediaModel.findOne(Table.games, gameCode);
    if (gameFound) {
      return res.status(409).json({ message: 'Game already exists' });
    }

    const uri = "https://id.twitch.tv/oauth2/token?client_id=" + twitch_client_id + "&client_secret=" + twitch_client_secret + "&grant_type=client_credentials";
    var response = await fetch(uri, { method: 'POST' });
    const mData = await response.json();

    const mheaders: HeadersInit = {
      'Accept': 'application/json',
      'Client-ID': twitch_client_id,
      'Authorization': 'Bearer ' + mData.access_token
    }

    gameCode = parseInt(gameCode)

    response = await fetch(
      "https://api.igdb.com/v4/games",
      {
        method: 'POST',
        headers: mheaders,
        body: `fields name, first_release_date; where id = ${gameCode};`
      }
    )
    const gameData = await response.json()
    if (gameData.length == 0) {
      return res.status(404).json({ message: 'wrong code' });
    }

    const date = new Date(gameData[0].first_release_date * 1000);
    const options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'short', year: 'numeric' }
    const dateStr = date.toLocaleDateString(undefined, options);


    response = await fetch(
      "https://api.igdb.com/v4/covers",
      {
        method: 'POST',
        headers: mheaders,
        body: `fields image_id; where game = ${gameCode};`
      }
    )
    const coverData = await response.json()

    const game = {
      code: gameCode,
      title: gameData[0].name,
      released: dateStr,
      webImg: `https://images.igdb.com/igdb/image/upload/t_cover_big/${coverData[0].image_id}.jpg`,
    };

    const savedGame = await MediaModel.save(Table.games, game.code, game.title, game.released, game.webImg);
    return res.status(201).json(game);

  } catch (error) {

    return res.status(500).json({ message: 'Error when creating game', error: error });
  }
}

export default {

  /**
   * mediaController.list()
   */
  list: function (req: Request, res: Response) {
    const mediaTable = fromStringToTable(req.params.mediaType);
    if (!mediaTable) {
      return res.status(500).json({
        message: 'Error when getting media.'
      });
    }

    MediaModel.find(mediaTable)
      .then(media => {
        return res.json(media);
      })
      .catch(err => {
        return res.status(500).json({
          message: 'Error when getting media.',
          error: err
        });
      });
  },

  create: async function (req: Request, res: Response) {
    const mediaCode: string = req.body.code;
    if (mediaCode.startsWith("t")) {
      return await createMed(req, res);
    } else {
      return await createGame(req, res);
    }
  },

  /**
   * mediaController.delete()
   */
  remove: async function (req: Request, res: Response) {
    const mediaTable = fromStringToTable(req.params.mediaType);
    if (!mediaTable) {
      return res.status(500).json({
        message: 'Error when deleting the media.'
      });
    }

    const code = req.body.code;

    try {
      const mediaTable = req.baseUrl.includes('movies') ? Table.movies : Table.series;
      const media = await MediaModel.findOneAndDelete(mediaTable, code);
      if (!media) {
        return res.status(404).json({ message: 'No such media' });
      }

      return res.status(204).json();
    }
    catch (err) {
      return res.status(500).json({ message: 'Error when deleting the media.' });
    }
  },
};
