package realname

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"errors"
	"strings"
	"time"
)

type Provider interface {
	Name() string
	Start(ctx context.Context, req StartRequest) (ProviderResult, error)
}

type StartRequest struct {
	UserID uint64
	Name   string
	IDNo   string
}

type ProviderResult struct {
	ProviderOrderNo string
	Status          string
	MaskedName      string
	MaskedIDNo      string
	VerifiedAt      *time.Time
	FailReason      string
}

type MockProvider struct{}

func NewMockProvider() *MockProvider {
	return &MockProvider{}
}

func (p *MockProvider) Name() string {
	return "mock"
}

func (p *MockProvider) Start(_ context.Context, req StartRequest) (ProviderResult, error) {
	if strings.TrimSpace(req.Name) == "" || strings.TrimSpace(req.IDNo) == "" {
		return ProviderResult{}, errors.New("name and id no are required")
	}
	orderNo, err := randomOrderNo()
	if err != nil {
		return ProviderResult{}, err
	}
	now := time.Now()
	return ProviderResult{
		ProviderOrderNo: orderNo,
		Status:          StatusVerified,
		MaskedName:      maskName(req.Name),
		MaskedIDNo:      maskIDNo(req.IDNo),
		VerifiedAt:      &now,
	}, nil
}

func randomOrderNo() (string, error) {
	buf := make([]byte, 8)
	if _, err := rand.Read(buf); err != nil {
		return "", err
	}
	return "mock_rn_" + hex.EncodeToString(buf), nil
}

func maskName(name string) string {
	name = strings.TrimSpace(name)
	if len([]rune(name)) <= 1 {
		return name
	}
	runes := []rune(name)
	return string(runes[0]) + strings.Repeat("*", len(runes)-1)
}

func maskIDNo(idNo string) string {
	idNo = strings.TrimSpace(idNo)
	if len(idNo) <= 8 {
		return idNo
	}
	return idNo[:4] + strings.Repeat("*", len(idNo)-8) + idNo[len(idNo)-4:]
}
