package keybase

import (
	"context"
	"fmt"
)

type EnclaveResult struct {
	ID           int64  `json:"id"`
	EnclaveID    string `json:"enclave_id"`
	PublicKeyHex string `json:"public_key_hex"`
	Curve        string `json:"curve"`
	Status       string `json:"status"`
	CreatedAt    string `json:"created_at"`
	RotatedAt    string `json:"rotated_at,omitempty"`
}

type NewEnclaveInput struct {
	EnclaveID    string `json:"enclave_id"`
	PublicKeyHex string `json:"public_key_hex"`
	PublicKey    []byte `json:"public_key"`
	ValShare     []byte `json:"val_share"`
	UserShare    []byte `json:"user_share"`
	Nonce        []byte `json:"nonce"`
	Curve        string `json:"curve"`
}

func (am *ActionManager) CreateEnclave(ctx context.Context, params NewEnclaveInput) (*EnclaveResult, error) {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	if am.kb.didID == 0 {
		return nil, fmt.Errorf("DID not initialized")
	}

	enc, err := am.kb.queries.CreateEnclave(ctx, CreateEnclaveParams{
		DidID:        am.kb.didID,
		EnclaveID:    params.EnclaveID,
		PublicKeyHex: params.PublicKeyHex,
		PublicKey:    params.PublicKey,
		ValShare:     params.ValShare,
		UserShare:    params.UserShare,
		Nonce:        params.Nonce,
		Curve:        params.Curve,
	})
	if err != nil {
		return nil, fmt.Errorf("create enclave: %w", err)
	}

	return enclaveToResult(&enc), nil
}

func (am *ActionManager) ListEnclaves(ctx context.Context) ([]EnclaveResult, error) {
	am.kb.mu.RLock()
	defer am.kb.mu.RUnlock()

	if am.kb.didID == 0 {
		return []EnclaveResult{}, nil
	}

	enclaves, err := am.kb.queries.ListEnclavesByDID(ctx, am.kb.didID)
	if err != nil {
		return nil, fmt.Errorf("list enclaves: %w", err)
	}

	results := make([]EnclaveResult, len(enclaves))
	for i, enc := range enclaves {
		results[i] = *enclaveToResult(&enc)
	}

	return results, nil
}

func (am *ActionManager) GetEnclaveByID(ctx context.Context, enclaveID string) (*EnclaveResult, error) {
	am.kb.mu.RLock()
	defer am.kb.mu.RUnlock()

	enc, err := am.kb.queries.GetEnclaveByID(ctx, enclaveID)
	if err != nil {
		return nil, fmt.Errorf("get enclave: %w", err)
	}

	return enclaveToResult(&enc), nil
}

func (am *ActionManager) RotateEnclave(ctx context.Context, enclaveID string) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	enc, err := am.kb.queries.GetEnclaveByID(ctx, enclaveID)
	if err != nil {
		return fmt.Errorf("get enclave: %w", err)
	}

	return am.kb.queries.RotateEnclave(ctx, enc.ID)
}

func (am *ActionManager) ArchiveEnclave(ctx context.Context, enclaveID string) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	enc, err := am.kb.queries.GetEnclaveByID(ctx, enclaveID)
	if err != nil {
		return fmt.Errorf("get enclave: %w", err)
	}

	return am.kb.queries.ArchiveEnclave(ctx, enc.ID)
}

func (am *ActionManager) DeleteEnclave(ctx context.Context, enclaveID string) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	if am.kb.didID == 0 {
		return fmt.Errorf("DID not initialized")
	}

	enc, err := am.kb.queries.GetEnclaveByID(ctx, enclaveID)
	if err != nil {
		return fmt.Errorf("get enclave: %w", err)
	}

	return am.kb.queries.DeleteEnclave(ctx, DeleteEnclaveParams{
		ID:    enc.ID,
		DidID: am.kb.didID,
	})
}

func enclaveToResult(enc *MpcEnclafe) *EnclaveResult {
	rotatedAt := ""
	if enc.RotatedAt != nil {
		rotatedAt = *enc.RotatedAt
	}

	return &EnclaveResult{
		ID:           enc.ID,
		EnclaveID:    enc.EnclaveID,
		PublicKeyHex: enc.PublicKeyHex,
		Curve:        enc.Curve,
		Status:       enc.Status,
		CreatedAt:    enc.CreatedAt,
		RotatedAt:    rotatedAt,
	}
}
