using System.Net;
using System.Text;
using MySql.Data.MySqlClient;
using System.Security.Cryptography;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Server
{
    public class Register : Route
    {
        private static string HashPassword(string password)
        {
            // Generate a salt
            byte[] salt = new byte[16];
            RandomNumberGenerator.Fill(salt);
            // Create a PBKDF2 instance to hash the password
            using (var pbkdf2 = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256))
            {
                byte[] hash = pbkdf2.GetBytes(32);

                // Combine the salt and the hash together
                byte[] hashBytes = new byte[48]; // 16 (salt) + 32 (hash)
                Array.Copy(salt, 0, hashBytes, 0, 16);
                Array.Copy(hash, 0, hashBytes, 16, 32);

                // Return the final hash as a Base64 encoded string
                return Convert.ToBase64String(hashBytes);
            }
        }
        public static void HandleRequest(HttpListenerRequest request, HttpListenerResponse response)
        {
            MySqlTransaction? transaction = null;
            try
            {
                // extract parameters from req body
                string body;
                using (StreamReader bodyReader = new StreamReader(request.InputStream, request.ContentEncoding))
                {
                    body = bodyReader.ReadToEnd();
                }
                JObject jsonObject = JObject.Parse(body);
                string f_name = jsonObject["f_name"]?.ToString() ?? "";
                string l_name = jsonObject["l_name"]?.ToString() ?? "";
                string password = jsonObject["password"]?.ToString() ?? "";
                string mail = jsonObject["mail"]?.ToString() ?? "";

                // validate parameters
                if (string.IsNullOrEmpty(f_name) || f_name.Length > 30 || f_name.Length < 2 ||
                    string.IsNullOrEmpty(l_name) || l_name.Length > 30 || l_name.Length < 2 ||
                    string.IsNullOrEmpty(mail) || mail.Length > 50 || mail.Length < 6 ||
                    string.IsNullOrEmpty(password) || password.Length > 30 || password.Length < 10)
                {
                    throw new Exception("Wrong parameters");
                }
                // open connection
                // prepare SQL query
                MySqlCommand cmd = new MySqlCommand();

                // Insert into User
                cmd.CommandText = "INSERT INTO User(f_name,l_name,mail) VALUES(@f_name,@l_name,@mail)";
                cmd.Parameters.AddWithValue("@f_name", f_name);
                cmd.Parameters.AddWithValue("@l_name", l_name);
                cmd.Parameters.AddWithValue("@mail", mail);

                using (MySqlConnection conn = new MySqlConnection(connectionString))
                {
                    conn.Open();
                    transaction = conn.BeginTransaction();
                    cmd.Connection = conn;
                    cmd.ExecuteNonQuery();

                    // Get user ID
                    cmd.CommandText = "SELECT id FROM User WHERE mail=@mail;";
                    MySqlDataReader reader = cmd.ExecuteReader();
                    reader.Read();
                    var id = reader["id"];
                    reader.Close();

                    // Insert into password
                    cmd.CommandText = "INSERT INTO Password(user,password) VALUES(@id,@password)";
                    cmd.Parameters.AddWithValue("@password", HashPassword(password));
                    cmd.Parameters.AddWithValue("@id", id);
                    cmd.ExecuteNonQuery();
                    transaction.Commit();

                    SendSuccess(response);
                }
            }
            catch (Exception ex)
            {
                if (transaction != null)
                    transaction.Rollback();
                SendError(response, ex);
            }
        }
    }
}
