// Copyright (c) 2017-2026 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// SPDX-License-Identifier: EUPL-1.2

package types

import "testing"

func TestAssetOperationConstants_Good(t *testing.T) {
	tests := []struct {
		name string
		got  uint8
		want uint8
	}{
		{"register", AssetOpRegister, 0},
		{"emit", AssetOpEmit, 1},
		{"update", AssetOpUpdate, 2},
		{"burn", AssetOpBurn, 3},
		{"public_burn", AssetOpPublicBurn, 4},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if tt.got != tt.want {
				t.Fatalf("got %d, want %d", tt.got, tt.want)
			}
		})
	}
}

func TestAssetDescriptorTypes_Good(t *testing.T) {
	base := AssetDescriptorBase{
		Ticker:         "LTHN",
		FullName:       "Lethean",
		TotalMaxSupply: 1000000,
		CurrentSupply:  0,
		DecimalPoint:   12,
		MetaInfo:       "{}",
		OwnerKey:       PublicKey{1},
		Etc:            []byte{1, 2, 3},
	}

	op := AssetDescriptorOperation{
		Version:       1,
		OperationType: AssetOpRegister,
		Descriptor:    &base,
		AssetID:       Hash{1},
		AmountToEmit:  100,
		AmountToBurn:  10,
		Etc:           []byte{4, 5, 6},
	}

	if op.Descriptor == nil || op.Descriptor.Ticker != "LTHN" {
		t.Fatalf("unexpected descriptor: %+v", op.Descriptor)
	}
	if op.OperationType != AssetOpRegister || op.Version != 1 {
		t.Fatalf("unexpected operation: %+v", op)
	}
}

func TestAssetDescriptorBaseValidate_Good(t *testing.T) {
	base := AssetDescriptorBase{
		Ticker:         "LTHN",
		FullName:       "Lethean",
		TotalMaxSupply: 1000000,
		CurrentSupply:  0,
		DecimalPoint:   12,
		MetaInfo:       "{}",
		OwnerKey:       PublicKey{1},
	}

	if err := base.Validate(); err != nil {
		t.Fatalf("Validate() error = %v", err)
	}
}

func TestAssetDescriptorBaseValidate_Bad(t *testing.T) {
	tests := []struct {
		name string
		base AssetDescriptorBase
	}{
		{"zero_supply", AssetDescriptorBase{Ticker: "LTHN", FullName: "Lethean", OwnerKey: PublicKey{1}}},
		{"too_many_current", AssetDescriptorBase{Ticker: "LTHN", FullName: "Lethean", TotalMaxSupply: 10, CurrentSupply: 11, OwnerKey: PublicKey{1}}},
		{"empty_ticker", AssetDescriptorBase{FullName: "Lethean", TotalMaxSupply: 10, OwnerKey: PublicKey{1}}},
		{"empty_name", AssetDescriptorBase{Ticker: "LTHN", TotalMaxSupply: 10, OwnerKey: PublicKey{1}}},
		{"zero_owner", AssetDescriptorBase{Ticker: "LTHN", FullName: "Lethean", TotalMaxSupply: 10}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := tt.base.Validate(); err == nil {
				t.Fatal("Validate() error = nil, want error")
			}
		})
	}
}

func TestAssetDescriptorOperationValidate_Good(t *testing.T) {
	base := AssetDescriptorBase{
		Ticker:         "LTHN",
		FullName:       "Lethean",
		TotalMaxSupply: 1000000,
		CurrentSupply:  0,
		DecimalPoint:   12,
		MetaInfo:       "{}",
		OwnerKey:       PublicKey{1},
	}

	op := AssetDescriptorOperation{
		Version:       1,
		OperationType: AssetOpRegister,
		Descriptor:    &base,
	}

	if err := op.Validate(); err != nil {
		t.Fatalf("Validate() error = %v", err)
	}
}

func TestAssetDescriptorOperationValidate_Bad(t *testing.T) {
	tests := []struct {
		name string
		op   AssetDescriptorOperation
	}{
		{"unsupported_version", AssetDescriptorOperation{Version: 2, OperationType: AssetOpRegister}},
		{"register_missing_descriptor", AssetDescriptorOperation{Version: 1, OperationType: AssetOpRegister}},
		{"emit_zero_amount", AssetDescriptorOperation{Version: 1, OperationType: AssetOpEmit, AssetID: Hash{1}}},
		{"update_missing_descriptor", AssetDescriptorOperation{Version: 1, OperationType: AssetOpUpdate, AssetID: Hash{1}}},
		{"burn_zero_amount", AssetDescriptorOperation{Version: 1, OperationType: AssetOpBurn, AssetID: Hash{1}}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if err := tt.op.Validate(); err == nil {
				t.Fatal("Validate() error = nil, want error")
			}
		})
	}
}
