package keybase

import (
	"context"
	"encoding/json"
	"fmt"
)

type ServiceResult struct {
	ID          int64           `json:"id"`
	Origin      string          `json:"origin"`
	Name        string          `json:"name"`
	Description string          `json:"description,omitempty"`
	LogoURL     string          `json:"logo_url,omitempty"`
	DID         string          `json:"did,omitempty"`
	IsVerified  bool            `json:"is_verified"`
	Metadata    json.RawMessage `json:"metadata,omitempty"`
	CreatedAt   string          `json:"created_at"`
}

type NewServiceInput struct {
	Origin      string          `json:"origin"`
	Name        string          `json:"name"`
	Description string          `json:"description,omitempty"`
	LogoURL     string          `json:"logo_url,omitempty"`
	DID         string          `json:"did,omitempty"`
	IsVerified  bool            `json:"is_verified"`
	Metadata    json.RawMessage `json:"metadata,omitempty"`
}

type UpdateServiceInput struct {
	ID          int64           `json:"id"`
	Name        string          `json:"name"`
	Description string          `json:"description,omitempty"`
	LogoURL     string          `json:"logo_url,omitempty"`
	Metadata    json.RawMessage `json:"metadata,omitempty"`
}

func (am *ActionManager) CreateService(ctx context.Context, params NewServiceInput) (*ServiceResult, error) {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	var description, logoURL, did *string
	if params.Description != "" {
		description = &params.Description
	}
	if params.LogoURL != "" {
		logoURL = &params.LogoURL
	}
	if params.DID != "" {
		did = &params.DID
	}

	metadata := params.Metadata
	if metadata == nil {
		metadata = json.RawMessage(`{}`)
	}

	var isVerified int64
	if params.IsVerified {
		isVerified = 1
	}

	svc, err := am.kb.queries.CreateService(ctx, CreateServiceParams{
		Origin:      params.Origin,
		Name:        params.Name,
		Description: description,
		LogoUrl:     logoURL,
		Did:         did,
		IsVerified:  isVerified,
		Metadata:    metadata,
	})
	if err != nil {
		return nil, fmt.Errorf("create service: %w", err)
	}

	return serviceToResult(&svc), nil
}

func (am *ActionManager) GetServiceByOrigin(ctx context.Context, origin string) (*ServiceResult, error) {
	am.kb.mu.RLock()
	defer am.kb.mu.RUnlock()

	svc, err := am.kb.queries.GetServiceByOrigin(ctx, origin)
	if err != nil {
		return nil, fmt.Errorf("get service by origin: %w", err)
	}

	return serviceToResult(&svc), nil
}

func (am *ActionManager) GetServiceByID(ctx context.Context, serviceID int64) (*ServiceResult, error) {
	am.kb.mu.RLock()
	defer am.kb.mu.RUnlock()

	svc, err := am.kb.queries.GetServiceByID(ctx, serviceID)
	if err != nil {
		return nil, fmt.Errorf("get service by ID: %w", err)
	}

	return serviceToResult(&svc), nil
}

func (am *ActionManager) UpdateService(ctx context.Context, params UpdateServiceInput) error {
	am.kb.mu.Lock()
	defer am.kb.mu.Unlock()

	var description, logoURL *string
	if params.Description != "" {
		description = &params.Description
	}
	if params.LogoURL != "" {
		logoURL = &params.LogoURL
	}

	metadata := params.Metadata
	if metadata == nil {
		metadata = json.RawMessage(`{}`)
	}

	return am.kb.queries.UpdateService(ctx, UpdateServiceParams{
		Name:        params.Name,
		Description: description,
		LogoUrl:     logoURL,
		Metadata:    metadata,
		ID:          params.ID,
	})
}

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

	services, err := am.kb.queries.ListVerifiedServices(ctx)
	if err != nil {
		return nil, fmt.Errorf("list verified services: %w", err)
	}

	results := make([]ServiceResult, len(services))
	for i, svc := range services {
		results[i] = *serviceToResult(&svc)
	}

	return results, nil
}

func serviceToResult(svc *Service) *ServiceResult {
	description := ""
	if svc.Description != nil {
		description = *svc.Description
	}
	logoURL := ""
	if svc.LogoUrl != nil {
		logoURL = *svc.LogoUrl
	}
	did := ""
	if svc.Did != nil {
		did = *svc.Did
	}

	return &ServiceResult{
		ID:          svc.ID,
		Origin:      svc.Origin,
		Name:        svc.Name,
		Description: description,
		LogoURL:     logoURL,
		DID:         did,
		IsVerified:  svc.IsVerified == 1,
		Metadata:    svc.Metadata,
		CreatedAt:   svc.CreatedAt,
	}
}
