package keybase

import (
	"context"
	"fmt"
)

type NewAccountInput struct {
	KeyShareID   int64  `json:"key_share_id"`
	Address      string `json:"address"`
	ChainID      string `json:"chain_id"`
	CoinType     int64  `json:"coin_type"`
	AccountIndex int64  `json:"account_index"`
	AddressIndex int64  `json:"address_index"`
	Label        string `json:"label,omitempty"`
}

func (am *ActionManager) CreateAccount(ctx context.Context, params NewAccountInput) (*AccountResult, error) {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

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

	var label *string
	if params.Label != "" {
		label = &params.Label
	}

	acc, err := am.kb.queries.CreateAccount(ctx, CreateAccountParams{
		DidID:        am.kb.didID,
		KeyShareID:   params.KeyShareID,
		Address:      params.Address,
		ChainID:      params.ChainID,
		CoinType:     params.CoinType,
		AccountIndex: params.AccountIndex,
		AddressIndex: params.AddressIndex,
		Label:        label,
	})
	if err != nil {
		return nil, fmt.Errorf("create account: %w", err)
	}

	labelStr := ""
	if acc.Label != nil {
		labelStr = *acc.Label
	}

	return &AccountResult{
		ID:           acc.ID,
		Address:      acc.Address,
		ChainID:      acc.ChainID,
		CoinType:     acc.CoinType,
		AccountIndex: acc.AccountIndex,
		AddressIndex: acc.AddressIndex,
		Label:        labelStr,
		IsDefault:    acc.IsDefault == 1,
		CreatedAt:    acc.CreatedAt,
	}, nil
}

func (am *ActionManager) ListAccountsByChain(ctx context.Context, chainID string) ([]AccountResult, error) {
	am.kb.mu.RLock()
	defer am.kb.mu.RUnlock()

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

	accounts, err := am.kb.queries.ListAccountsByChain(ctx, ListAccountsByChainParams{
		DidID:   am.kb.didID,
		ChainID: chainID,
	})
	if err != nil {
		return nil, fmt.Errorf("list accounts by chain: %w", err)
	}

	results := make([]AccountResult, len(accounts))
	for i, acc := range accounts {
		label := ""
		if acc.Label != nil {
			label = *acc.Label
		}
		results[i] = AccountResult{
			ID:           acc.ID,
			Address:      acc.Address,
			ChainID:      acc.ChainID,
			CoinType:     acc.CoinType,
			AccountIndex: acc.AccountIndex,
			AddressIndex: acc.AddressIndex,
			Label:        label,
			IsDefault:    acc.IsDefault == 1,
			CreatedAt:    acc.CreatedAt,
		}
	}

	return results, nil
}

func (am *ActionManager) GetDefaultAccount(ctx context.Context, chainID string) (*AccountResult, error) {
	am.kb.mu.RLock()
	defer am.kb.mu.RUnlock()

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

	acc, err := am.kb.queries.GetDefaultAccount(ctx, GetDefaultAccountParams{
		DidID:   am.kb.didID,
		ChainID: chainID,
	})
	if err != nil {
		return nil, fmt.Errorf("get default account: %w", err)
	}

	label := ""
	if acc.Label != nil {
		label = *acc.Label
	}

	return &AccountResult{
		ID:           acc.ID,
		Address:      acc.Address,
		ChainID:      acc.ChainID,
		CoinType:     acc.CoinType,
		AccountIndex: acc.AccountIndex,
		AddressIndex: acc.AddressIndex,
		Label:        label,
		IsDefault:    acc.IsDefault == 1,
		CreatedAt:    acc.CreatedAt,
	}, nil
}

func (am *ActionManager) SetDefaultAccount(ctx context.Context, accountID int64, chainID string) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

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

	return am.kb.queries.SetDefaultAccount(ctx, SetDefaultAccountParams{
		ID:      accountID,
		DidID:   am.kb.didID,
		ChainID: chainID,
	})
}

func (am *ActionManager) UpdateAccountLabel(ctx context.Context, accountID int64, label string) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	var labelPtr *string
	if label != "" {
		labelPtr = &label
	}

	return am.kb.queries.UpdateAccountLabel(ctx, UpdateAccountLabelParams{
		Label: labelPtr,
		ID:    accountID,
	})
}

func (am *ActionManager) DeleteAccount(ctx context.Context, accountID int64) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

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

	return am.kb.queries.DeleteAccount(ctx, DeleteAccountParams{
		ID:    accountID,
		DidID: am.kb.didID,
	})
}
