using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Percent___Qualification_work.Classes
{
    public class api_scrape_game
    {
        // IGDB API credentials 
        string clientId = "isk0e8z2vpss2pzmgyctkgkaurfij3";
        string clientSecret = "7qfim9q0qa93khn12fwm6lwjoo98iu";

        // Method to retrieve the access token from the Twitch/IGDB OAuth2 endpoint
        public async Task<string> GetToken()
        {
            string url = $"https://id.twitch.tv/oauth2/token?client_id={clientId}&client_secret={clientSecret}&grant_type=client_credentials";

            using (HttpClient httpClient = new HttpClient())
            {
                try
                {
                    // Send a POST request to retrieve the access token
                    HttpResponseMessage response = await httpClient.PostAsync(url, null);

                    if (response.IsSuccessStatusCode)
                    {
                        // Deserialize the JSON response to extract the access token
                        string responseContent = await response.Content.ReadAsStringAsync();
                        var tokenData = JsonSerializer.Deserialize<JsonElement>(responseContent);
                        string token = tokenData.GetProperty("access_token").GetString();

                        // Return the extracted access token
                        return token;
                    }
                    else
                    {
                        // Handle errors by throwing an exception with the error response
                        string errorContent = await response.Content.ReadAsStringAsync();
                        throw new Exception($"Error fetching token: {errorContent}");
                    }
                }
                catch (Exception ex)
                {
                    // Catch any exceptions and rethrow with additional context
                    throw new Exception($"Exception occurred: {ex.Message}");
                }
            }
        }

        // Method to fetch game information by name from the IGDB API
        public async Task<Game> GetGame(string gameName)
        {
            // Retrieve the access token
            string token = await GetToken();

            if (string.IsNullOrEmpty(token))
            {
                // Notify the user if the token could not be retrieved
                MessageBox.Show("Failed to retrieve an access token.");
                return null;
            }

            // IGDB API endpoint for fetching game data
            string url = "https://api.igdb.com/v4/games";

            using (HttpClient httpClient = new HttpClient())
            {
                try
                {
                    // Add necessary headers for authorization and client identification
                    httpClient.DefaultRequestHeaders.Add("Client-ID", clientId);
                    httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}");

                    // Construct the query to fetch game data with the specified fields
                    string query = $"fields id, name, genres.name, involved_companies.company.name, first_release_date, cover.image_id; " +
                                   $"search \"{gameName}\";";

                    // Send a POST request with the query as the content
                    StringContent content = new StringContent(query, Encoding.UTF8, "application/json");
                    HttpResponseMessage response = await httpClient.PostAsync(url, content);

                    if (response.IsSuccessStatusCode)
                    {
                        // Deserialize the JSON response into an array of JsonElement objects
                        string jsonResponse = await response.Content.ReadAsStringAsync();
                        var gamesData = JsonSerializer.Deserialize<JsonElement[]>(jsonResponse);

                        if (gamesData != null && gamesData.Length > 0)
                        {
                            // Extract the first game from the response
                            var gameData = gamesData[0];

                            // Extract game fields safely with proper error handling
                            int? id = gameData.GetProperty("id").GetInt32();
                            string name = gameData.GetProperty("name").GetString();
                            string genre = gameData.TryGetProperty("genres", out var genres) && genres.GetArrayLength() > 0
                                ? genres[0].GetProperty("name").GetString()
                                : "Unknown"; // Default to "Unknown" if no genre is provided
                            string developer = gameData.TryGetProperty("involved_companies", out var companies) && companies.GetArrayLength() > 0
                                ? companies[0].GetProperty("company").GetProperty("name").GetString()
                                : "Unknown"; // Default to "Unknown" if no developer is provided
                            int releaseYear = gameData.TryGetProperty("first_release_date", out var releaseDate)
                                ? DateTimeOffset.FromUnixTimeSeconds(releaseDate.GetInt64()).Year
                                : 0; // Default to 0 if release date is missing
                            byte[] coverImage = gameData.TryGetProperty("cover", out var cover)
                                ? await GetCoverImage(cover.GetProperty("image_id").GetString())
                                : ImageToByteArray(Properties.Resources.no_image);

                            // Map the extracted data to a Game object and return it
                            return new Game(id, name, genre, developer, releaseYear, coverImage);
                        }
                        else
                        {
                            // return nothing if no game found
                            return null;
                        }
                    }
                    else
                    {
                        // Handle API errors 
                        string errorResponse = await response.Content.ReadAsStringAsync();
                        MessageBox.Show($"API Error: {errorResponse}");
                        return null;
                    }
                }
                catch (Exception ex)
                {
                    // Catch and handle any exceptions that occur during the request
                    MessageBox.Show($"Exception occurred: {ex.Message}");
                    return null;
                }
            }
        }

        // Method to fetch a game's cover image from the IGDB 
        private async Task<byte[]> GetCoverImage(string imageId)
        {
            if (string.IsNullOrEmpty(imageId))
                return null; // Return null if the image ID is not provided

            // Construct the URL for fetching the cover image
            string coverUrl = $"https://images.igdb.com/igdb/image/upload/t_cover_big/{imageId}.jpg";

            using (HttpClient httpClient = new HttpClient())
            {
                try
                {
                    // Fetch the cover image as a byte array
                    return await httpClient.GetByteArrayAsync(coverUrl);
                }
                catch (Exception ex)
                {
                    // Handle exceptions during the image fetch process
                    return null;
                }
            }
        }
        byte[] ImageToByteArray(System.Drawing.Image image)
        {
            using (var ms = new MemoryStream())
            {
                image.Save(ms, image.RawFormat);
                return ms.ToArray();
            }
        }
    }
}
