package keydirectory

import (
	"context"
	"crypto"
	"crypto/x509"
	"database/sql"

	"github.com/common-fate/httpsig/verifier"
	_ "github.com/mattn/go-sqlite3"
)

type dbWrapper struct {
	db *sql.DB
}

func InitSqlite(dbPath string) (*dbWrapper, error) {
	db, err := sql.Open("sqlite3", dbPath)

	if err != nil {
		return &dbWrapper{}, err
	}

	createStmt := `
	create table
	if not exists
	keys(keyId text not null primary key, userId text, publicKey blob)
	`

	_, err = db.Exec(createStmt)

	if err != nil {
		return &dbWrapper{}, err
	}

	return &dbWrapper{db}, nil
}

func (dir *dbWrapper) GetKey(ctx context.Context, keyId string, _ string) (verifier.Algorithm, error) {
	db := dir.db

	query := "select userId, publicKey from keys where keyId = ?"

	stmt, err := db.Prepare(query)

	if err != nil {
		return nil, err
	}

	defer stmt.Close()

	var userId string
	var keyBytes []byte

	row := stmt.QueryRow(keyId)

	err = row.Scan(&userId, &keyBytes)

	if err != nil {
		return nil, err
	}

	publicKey, err := x509.ParsePKIXPublicKey(keyBytes)

	if err != nil {
		return nil, err
	}

	keyEntry := keyEntry{
		UserId:    userId,
		PublicKey: publicKey,
	}

	return keyEntry.toAlg()
}

func (dir *dbWrapper) RegisterKey(key crypto.PublicKey, userId string) (string, error) {
	db := dir.db

	keyId, err := generateKeyId()

	if err != nil {
		return "", err
	}

	stmt := "insert into keys(keyId, userId, publicKey) values (?, ?, ?)"

	keyBytes, err := x509.MarshalPKIXPublicKey(key)

	if err != nil {
		return "", err
	}

	_, err = db.Exec(stmt, keyId, userId, keyBytes)

	if err != nil {
		return "", err
	}

	return keyId, nil
}