using System;
using System.Text;
using System.Threading;
using RestSharp;

namespace HorseRacingPredictor.HorseRacing.API
{
    /// <summary>
    /// Client per The Racing API (theracingapi.com)
    /// Utilizza HTTP Basic Authentication
    /// </summary>
    internal class RacingApiClient
    {
        private const string BaseUrl = "https://api.theracingapi.com/v1";
        private const int DefaultDelay = 1100; // Rate limit: 1 req/sec per Free plan

        private readonly string _username;
        private readonly string _password;

        public RacingApiClient(string username, string password)
        {
            _username = username;
            _password = password;
        }

        /// <summary>
        /// Esegue una richiesta GET autenticata con HTTP Basic Auth
        /// </summary>
        private RestResponse ExecuteRequest(string endpoint, int delay = DefaultDelay)
        {
            string url = $"{BaseUrl}/{endpoint}";
            var client = new RestClient(url);
            var request = new RestRequest();

            string credentials = Convert.ToBase64String(
                Encoding.ASCII.GetBytes($"{_username}:{_password}"));
            request.AddHeader("Authorization", $"Basic {credentials}");

            try
            {
                var response = client.Execute(request);
                if (!response.IsSuccessful)
                {
                    throw new Exception(
                        $"Errore API Racing ({(int)response.StatusCode}): {response.StatusDescription}");
                }

                if (delay > 0)
                    Thread.Sleep(delay);

                return response;
            }
            catch (Exception ex) when (!(ex.Message.StartsWith("Errore API Racing")))
            {
                throw new Exception($"Errore durante la richiesta a Racing API: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// Ottiene le racecard (programma corse) per oggi o domani
        /// </summary>
        /// <param name="day">"today" oppure "tomorrow"</param>
        /// <param name="regionCodes">Codici regione opzionali (es. "gb", "ire")</param>
        public RestResponse GetRacecardsFree(string day = "today", string[] regionCodes = null)
        {
            var sb = new StringBuilder("racecards/free?");
            sb.Append($"day={day}");

            if (regionCodes != null && regionCodes.Length > 0)
            {
                foreach (var rc in regionCodes)
                    sb.Append($"&region_codes={rc}");
            }

            return ExecuteRequest(sb.ToString());
        }

        /// <summary>
        /// Ottiene le racecard standard per oggi o domani
        /// </summary>
        public RestResponse GetRacecardsStandard(string day = "today", string[] regionCodes = null)
        {
            var sb = new StringBuilder("racecards/standard?");
            sb.Append($"day={day}");

            if (regionCodes != null && regionCodes.Length > 0)
            {
                foreach (var rc in regionCodes)
                    sb.Append($"&region_codes={rc}");
            }

            return ExecuteRequest(sb.ToString());
        }

        /// <summary>
        /// Ottiene i risultati per un intervallo di date
        /// </summary>
        public RestResponse GetResults(DateTime startDate, DateTime endDate, string[] regionCodes = null)
        {
            var sb = new StringBuilder("results?");
            sb.Append($"start_date={startDate:yyyy-MM-dd}");
            sb.Append($"&end_date={endDate:yyyy-MM-dd}");

            if (regionCodes != null && regionCodes.Length > 0)
            {
                foreach (var rc in regionCodes)
                    sb.Append($"&region={rc}");
            }

            return ExecuteRequest(sb.ToString());
        }

        /// <summary>
        /// Ottiene l'elenco delle regioni disponibili
        /// </summary>
        public RestResponse GetRegions()
        {
            return ExecuteRequest("courses/regions");
        }

        /// <summary>
        /// Ottiene l'elenco dei corsi per le regioni specificate
        /// </summary>
        public RestResponse GetCourses(string[] regionCodes = null)
        {
            var sb = new StringBuilder("courses?");
            if (regionCodes != null && regionCodes.Length > 0)
            {
                foreach (var rc in regionCodes)
                    sb.Append($"&region_codes={rc}");
            }

            return ExecuteRequest(sb.ToString());
        }
    }
}
