package m2mcore

import (
	"context"
	"errors"
	"time"

	"git.zetit.ru/zuevav/Bridge-and-Join-s/internal/m2m"
)

// CertInfo — описание подписанта (заполняется CryptoVerifier).
type CertInfo struct {
	SignerCN  string
	SignerINN string
	Serial    string
	NotBefore time.Time
	NotAfter  time.Time
}

// Client — анкета инвестора, нужная для enrich Request.
type Client struct {
	ID         string
	LastName   string
	FirstName  string
	MiddleName string
	BirthDate  *time.Time
	Document   ClientDocument
}

// ClientDocument — документ, удостоверяющий личность.
type ClientDocument struct {
	DocumentType m2m.IdentityDocumentCode
	Series       string
	Number       string
}

// DepoAccount — счёт депо инвестора у депозитария.
type DepoAccount struct {
	ID            string
	ClientID      string
	DeponentCode  string
	AccountID     m2m.AccountID
	SectionID     string
	DepositoryINN m2m.OrganizationINN
}

// SecurityBalance — остаток по ценной бумаге на конкретном счёте депо.
type SecurityBalance struct {
	SecurityCode       m2m.SecurityCode
	ISIN               m2m.ISIN
	QuantityWhole      *uint64
	QuantityFractional *m2m.Decimal16
	IsolationStatus    m2m.IsolationStatus
	ValuedAt           time.Time
}

// NSDSender — порт отправки в НРД (через ИШ или резервный канал WS ONYX).
type NSDSender interface {
	// Send отправляет запрос на перевод и возвращает квитанцию НРД.
	Send(ctx context.Context, req *m2m.M2MTransferRequest) (*m2m.M2MTransferResponse, error)
	// SendDecision отправляет решение принимающей стороны.
	SendDecision(ctx context.Context, decision *m2m.M2MTransferDecision) error
}

// LKCallbackClient — порт уведомления ЛК клиента об изменении статуса.
type LKCallbackClient interface {
	UpdateStatus(ctx context.Context, claimID, status, reason string) error
}

// CryptoVerifier — порт проверки и формирования XMLDSig-подписей.
type CryptoVerifier interface {
	VerifyXMLDSig(ctx context.Context, payload []byte) (CertInfo, error)
}

// FansyStore — порт чтения данных из принимающей БД fansy-store.
type FansyStore interface {
	GetClientByID(ctx context.Context, id string) (*Client, error)
	GetDepoAccounts(ctx context.Context, clientID string, depositoryINN m2m.OrganizationINN) ([]DepoAccount, error)
	GetBalances(ctx context.Context, depoAccountID string, codes []m2m.SecurityCode) ([]SecurityBalance, error)
}

// ErrNotImplemented возвращается заглушками портов.
var ErrNotImplemented = errors.New("m2mcore: не реализовано (M1 заглушка)")

// NoopNSDSender — заглушка NSDSender для M1.
type NoopNSDSender struct{}

// Send возвращает ErrNotImplemented.
func (NoopNSDSender) Send(context.Context, *m2m.M2MTransferRequest) (*m2m.M2MTransferResponse, error) {
	return nil, ErrNotImplemented
}

// SendDecision возвращает ErrNotImplemented.
func (NoopNSDSender) SendDecision(context.Context, *m2m.M2MTransferDecision) error {
	return ErrNotImplemented
}

// NoopLKCallbackClient — заглушка LKCallbackClient для M1.
type NoopLKCallbackClient struct{}

// UpdateStatus возвращает ErrNotImplemented.
func (NoopLKCallbackClient) UpdateStatus(context.Context, string, string, string) error {
	return ErrNotImplemented
}

// NoopCryptoVerifier — заглушка CryptoVerifier для M1.
type NoopCryptoVerifier struct{}

// VerifyXMLDSig возвращает ErrNotImplemented.
func (NoopCryptoVerifier) VerifyXMLDSig(context.Context, []byte) (CertInfo, error) {
	return CertInfo{}, ErrNotImplemented
}

// NoopFansyStore — заглушка FansyStore для M1.
type NoopFansyStore struct{}

// GetClientByID возвращает ErrNotImplemented.
func (NoopFansyStore) GetClientByID(context.Context, string) (*Client, error) {
	return nil, ErrNotImplemented
}

// GetDepoAccounts возвращает ErrNotImplemented.
func (NoopFansyStore) GetDepoAccounts(context.Context, string, m2m.OrganizationINN) ([]DepoAccount, error) {
	return nil, ErrNotImplemented
}

// GetBalances возвращает ErrNotImplemented.
func (NoopFansyStore) GetBalances(context.Context, string, []m2m.SecurityCode) ([]SecurityBalance, error) {
	return nil, ErrNotImplemented
}
