package main

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

const (
	sharedSecret = "AliceInWonderland"   // Replace with your shared secret
	dendriteURL  = "https://chihaya.one" // Replace with your Dendrite server URL
)

type NonceResponse struct {
	Nonce string `json:"nonce"`
}

type RegistrationRequest struct {
	Nonce       string `json:"nonce"`
	Username    string `json:"username"`
	Displayname string `json:"displayname,omitempty"`
	Password    string `json:"password"`
	Admin       bool   `json:"admin"`
	Mac         string `json:"mac"`
}

func fetchNonce() (string, error) {
	resp, err := http.Get(fmt.Sprintf("%s/_synapse/admin/v1/register", dendriteURL))
	if err != nil {
		return "", fmt.Errorf("failed to fetch nonce: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("failed to read response body: %v", err)
	}

	var nonceResponse NonceResponse
	err = json.Unmarshal(body, &nonceResponse)
	if err != nil {
		return "", fmt.Errorf("failed to unmarshal nonce response: %v", err)
	}

	return nonceResponse.Nonce, nil
}

func generateMAC(nonce, username, password, admin, sharedSecret string) string {
	mac := hmac.New(sha1.New, []byte(sharedSecret))
	mac.Write([]byte(nonce))
	mac.Write([]byte{0})
	mac.Write([]byte(username))
	mac.Write([]byte{0})
	mac.Write([]byte(password))
	mac.Write([]byte{0})
	mac.Write([]byte(admin))

	return hex.EncodeToString(mac.Sum(nil))
}

func registerUser(nonce, username, password, displayname string, admin bool) error {
	adminStr := "notadmin"
	if admin {
		adminStr = "admin"
	}

	mac := generateMAC(nonce, username, password, adminStr, sharedSecret)

	reqBody := RegistrationRequest{
		Nonce:       nonce,
		Username:    username,
		Displayname: displayname,
		Password:    password,
		Admin:       admin,
		Mac:         mac,
	}

	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return fmt.Errorf("failed to marshal request: %v", err)
	}

	resp, err := http.Post(fmt.Sprintf("%s/_synapse/admin/v1/register", dendriteURL), "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		return fmt.Errorf("failed to make request: %v", err)
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return fmt.Errorf("failed to read response body: %v", err)
	}

	fmt.Println("Response Body:", string(body))

	if resp.StatusCode != http.StatusOK {
		return fmt.Errorf("registration failed with status: %s", resp.Status)
	}

	fmt.Println("User registered successfully")
	return nil
}

func main() {
	if len(os.Args) != 4 {
		fmt.Printf("Usage: %s <username> <password> <displayname>\n", os.Args[0])
		return
	}

	username := os.Args[1]
	password := os.Args[2]
	displayname := os.Args[3]

	nonce, err := fetchNonce()
	if err != nil {
		fmt.Printf("Error fetching nonce: %v\n", err)
		return
	}

	if err := registerUser(nonce, username, password, displayname, false); err != nil {
		fmt.Printf("Error: %v\n", err)
	}
}
