using System.IdentityModel.Tokens.Jwt;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.IdentityModel.Tokens;
using MySql.Data.MySqlClient;
using Newtonsoft.Json.Linq;

namespace Server;

public class CreateLog : Route
{
    private static string secretKey =
        "stronk-key-much-sercret-much-more-stronk-stronk-key-much-sercret-much-more-stronk";

    private static bool ValidateToken(string token)
    {
        try
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));
            var tokenHandler = new JwtSecurityTokenHandler();
            var validationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidIssuer = "TimeLogServer",
                ValidAudience = "TimeLogWebsite",
                IssuerSigningKey = key,
            };

            var principal = tokenHandler.ValidateToken(
                token,
                validationParameters,
                out SecurityToken validatedToken
            );
            return validatedToken != null;
        }
        catch
        {
            return false;
        }
    }

    public static void HandleRequest(
        HttpListenerRequest request,
        HttpListenerResponse response,
        HttpListenerContext context
    )
    {
        try
        {
            // check header
            var headers = request.Headers;
            string? token = headers["token"];
            if (!string.IsNullOrEmpty(token) && !ValidateToken(token))
            {
                throw new Exception("Invalid token");
            }
            // prepare SQL query
            MySqlCommand cmd = new MySqlCommand();
            // extact data from body
            string body;
            using (
                StreamReader bodyReader = new StreamReader(
                    request.InputStream,
                    request.ContentEncoding
                )
            )
            {
                body = bodyReader.ReadToEnd();
            }
            JObject jsonObject = JObject.Parse(body);
            string project = jsonObject["project"]?.ToString() ?? "";
            string time = jsonObject["time"]?.ToString() ?? "";
            string date = jsonObject["date"]?.ToString() ?? "";

            // TODO check if the hours on given date don't combine to more
            // than 8

            // validate time
            if (!int.TryParse(time, out int myInt) || myInt < 0 || myInt > 8)
                throw new Exception("Incorect ammount of hours");
            // validate date
            Regex regex = new Regex(@"^\d{4}-\d{2}-\d{2}$");
            if (string.IsNullOrEmpty(date) || !regex.IsMatch(date))
            {
                throw new Exception("Incorrect date format");
            }
            // validate user
            // extract user from jwt
            var handler = new JwtSecurityTokenHandler();
            var jwtToken = handler.ReadJwtToken(token);
            string? usernameClaim =
                jwtToken.Claims.FirstOrDefault(c => c.Type == "user")?.Value ?? "";
            if (string.IsNullOrEmpty(usernameClaim))
            {
                throw new Exception("wrong user id");
            }

            // validate project
            // TODO better project validation
            if (string.IsNullOrEmpty(project))
            {
                throw new Exception("wrong project");
            }
            using (MySqlConnection conn = new MySqlConnection(connectionString))
            {
                conn.Open();
                cmd.Connection = conn;
                cmd.CommandText =
                    @"INSERT INTO Timelog(user,project,date,time) 
                                        VALUES(@user,@project,@date,@time);";
                cmd.Parameters.AddWithValue("@user", usernameClaim);
                cmd.Parameters.AddWithValue("@project", project);
                cmd.Parameters.AddWithValue("@time", time);
                cmd.Parameters.AddWithValue("@date", date);
                // execute query and read results
                cmd.ExecuteNonQuery();

                SendSuccess(response);
            }
        }
        catch (Exception ex)
        {
            SendError(response, ex);
        }
    }
}
