package main

import (
	"context"
	"net/http"
	"strings"
	"sync"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/core/authidentity"
	"github.com/tidbcloud/AgentTeam/internal/sms"
)

type e2eMobileVerificationRecorder struct {
	mu      sync.Mutex
	entries map[string]e2eMobileVerificationEntry
}

type e2eMobileVerificationEntry struct {
	Mobile string    `json:"mobile"`
	Code   string    `json:"code"`
	SentAt time.Time `json:"sentAt"`
}

func newE2EMobileVerificationRecorder() *e2eMobileVerificationRecorder {
	return &e2eMobileVerificationRecorder{
		entries: make(map[string]e2eMobileVerificationEntry),
	}
}

func normalizeE2EMobile(mobile string) (string, error) {
	return authidentity.NormalizeMobile(mobile)
}

func (recorder *e2eMobileVerificationRecorder) record(mobile string, code string) {
	normalizedMobile, err := normalizeE2EMobile(mobile)
	if err != nil {
		return
	}

	recorder.mu.Lock()
	defer recorder.mu.Unlock()
	recorder.entries[normalizedMobile] = e2eMobileVerificationEntry{
		Mobile: normalizedMobile,
		Code:   strings.TrimSpace(code),
		SentAt: time.Now(),
	}
}

func (recorder *e2eMobileVerificationRecorder) latest(mobile string) (e2eMobileVerificationEntry, bool, error) {
	normalizedMobile, err := normalizeE2EMobile(mobile)
	if err != nil {
		return e2eMobileVerificationEntry{}, false, err
	}

	recorder.mu.Lock()
	defer recorder.mu.Unlock()
	entry, ok := recorder.entries[normalizedMobile]
	return entry, ok, nil
}

type e2eMobileVerificationSender struct {
	next     sms.Sender
	recorder *e2eMobileVerificationRecorder
}

func newE2EMobileVerificationSender(next sms.Sender, recorder *e2eMobileVerificationRecorder) sms.Sender {
	return &e2eMobileVerificationSender{next: next, recorder: recorder}
}

func (sender *e2eMobileVerificationSender) Send(ctx context.Context, mobile string, code string) (sms.Receipt, error) {
	receipt := sms.Receipt{Provider: sms.ProviderNoop}
	if sender.next != nil {
		nextReceipt, err := sender.next.Send(ctx, mobile, code)
		receipt = nextReceipt
		if err != nil {
			return receipt, err
		}
	}
	if sender.recorder != nil {
		sender.recorder.record(mobile, code)
	}
	return receipt, nil
}

func e2eMobileVerificationLatestHandler(recorder *e2eMobileVerificationRecorder) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodGet {
			w.WriteHeader(http.StatusMethodNotAllowed)
			return
		}

		mobile := strings.TrimSpace(r.URL.Query().Get("mobile"))
		if mobile == "" {
			writeE2EJSON(w, http.StatusBadRequest, e2eErrorResponse{Error: "mobile is required"})
			return
		}

		entry, ok, err := recorder.latest(mobile)
		if err != nil {
			writeE2EJSON(w, http.StatusBadRequest, e2eErrorResponse{Error: err.Error()})
			return
		}
		if !ok {
			writeE2EJSON(w, http.StatusNotFound, e2eErrorResponse{Error: "not found"})
			return
		}

		writeE2EJSON(w, http.StatusOK, entry)
	}
}
