package main

import (
	"fmt"
	"strconv"
)

type Wallet struct {
	Cash int
}

type Stringer interface {
	String() string
}

func (w *Wallet) String() string {
	return "Кошелек в котором " + strconv.Itoa(w.Cash) + " денег"
}

func (w *Wallet) Pay(amount int) error {
	if w.Cash < amount {
		return fmt.Errorf("Не хватает денег в кошельке")
	}
	w.Cash -= amount
	return nil
}

// ------------------

type Card struct {
	Balance    int
	ValidUntil string
	CardHolder string
	CVV        string
	Number     string
}

func (c *Card) Pay(amount int) error {
	if c.Balance < amount {
		return fmt.Errorf("Не хватает денег на карте")
	}
	c.Balance -= amount
	return nil
}

// ------------------

type ApplePay struct {
	Money   int
	AppleID string
}

func (a *ApplePay) Pay(amount int) error {
	if a.Money < amount {
		return fmt.Errorf("Не хватает денег на аккаунте")
	}
	a.Money -= amount
	return nil
}

// ------------------

type Payer interface {
	Pay(int) error
}

// ------------------

func Buy(in interface{}) {
	var p Payer
	var ok bool
	if p, ok = in.(Payer); !ok {
		fmt.Printf("%T не является платежным средством\n\n", in)
		return
	}

	err := p.Pay(10)
	if err != nil {
		fmt.Printf("Ошибка при оплате %T: %v\n\n", p, err)
		return
	}
	fmt.Printf("Спасибо за покупку через %T\n\n", p)
}

func main() {
	/*
		myWallet := &Wallet{Cash: 100}
		Buy(myWallet)

		var myMoney Payer
		myMoney = &Card{Balance: 100, CardHolder: "rvasily"}
		Buy(myMoney)

		myMoney = &ApplePay{Money: 120}
		Buy(myMoney)
	*/

	// Пустые интерфейсы
	myWallet := &Wallet{Cash: 100}
	fmt.Printf("Raw payment: %#v\n", myWallet)
	fmt.Printf("Способ оплаты: %s\n", myWallet)
}
