package ofxgo_test
import (
	"github.com/aclindsa/ofxgo"
	"math/big"
	"strings"
	"testing"
	"time"
)
func TestMarshalInvStatementRequest(t *testing.T) {
	var expectedString string = `
	
		
			20160224131905.000[-5:EST]
			1998124
			Sup3eSekrit
			ENG
			
				First Bank
				01
			
			MYAPP
			1234
		
	
	
		
			382827d6-e2d0-4396-bf3b-665979285420
			
				
					fi.example.com
					82736664
				
				
					20160101000000.000[-5:EST]
					Y
				
				Y
				
					Y
				
				Y
			
		
	
`
	var client = ofxgo.Client{
		AppId:       "MYAPP",
		AppVer:      "1234",
		SpecVersion: "203",
	}
	var request ofxgo.Request
	request.Signon.UserId = "1998124"
	request.Signon.UserPass = "Sup3eSekrit"
	request.Signon.Org = "First Bank"
	request.Signon.Fid = "01"
	EST := time.FixedZone("EST", -5*60*60)
	dtstart := ofxgo.Date(time.Date(2016, 1, 1, 0, 0, 0, 0, EST))
	statementRequest := ofxgo.InvStatementRequest{
		TrnUID: "382827d6-e2d0-4396-bf3b-665979285420",
		InvAcctFrom: ofxgo.InvAcct{
			BrokerId: "fi.example.com",
			AcctId:   "82736664",
		},
		DtStart:        &dtstart,
		Include:        true,
		IncludeOO:      true,
		IncludePos:     true,
		IncludeBalance: true,
	}
	request.InvStmt = append(request.InvStmt, &statementRequest)
	request.SetClientFields(&client)
	// Overwrite the DtClient value set by SetClientFields to time.Now()
	request.Signon.DtClient = ofxgo.Date(time.Date(2016, 2, 24, 13, 19, 5, 0, EST))
	marshalCheckRequest(t, &request, expectedString)
}
func TestUnmarshalInvStatementResponse(t *testing.T) {
	responseReader := strings.NewReader(`
	
		
			
				0
				INFO
			
			20170401201244
			ENG
			
				INVSTRUS
				9999
			
		
	
	
		
			1a0117ad-692b-4c6a-a21b-020d37d34d49
			
				0
				INFO
			
			
				20170331000000
				USD
				
					invstrus.com
					91827364
				
				
					20170101000000
					20170331000000
					
						
							
								729483191
								20170203
								20170207
							
							
								78462F103
								CUSIP
							
							100
							229.00
							9.00
							-22909.00
							CASH
							CASH
						
						BUY
					
					
						
							CREDIT
							20170120
							20170118
							20170123
							22000.00
							993838
							DEPOSIT
							CHECK 19980
						
						CASH
					
				
				
					
						
							
								78462F103
								CUSIP
							
							CASH
							LONG
							200
							235.74
							47148.00
							20170331160000
							Price as of previous close
						
					
					
						
							
								129887339
								CUSIP
							
							CASH
							LONG
							1
							3
							300
							20170331160000
						
					
				
				
					16.73
					-819.20
					0
					
						
							Sweep Int Rate
							Current interest rate for sweep account balances
							PERCENT
							0.25
							20170401
						
					
				
				
					
						
							76464632
							
								922908645
								CUSIP
							
							20170310124445
							10
							CASH
							GOODTILCANCEL
							NONE
							168.50
						
						BUY
						SHARES
					
					
						
							999387423
							
								899422348
								CUSIP
							
							20170324031900
							25
							CASH
							GOODTILCANCEL
							ALLORNONE
							19.75
						
						BUY
					
				
			
		
	
	
		
			
				
					
						78462F103
						CUSIP
					
					S&P 500 ETF
					SPY
					99184
				
				1.92
				OTHER
			
			
				
					
						129887339
						CUSIP
					
					John's Fertilizer Puts
					FERTP
					882919
				
				PUT
				79.00
				20170901
				100
				
					983322180
					CUSIP
				
				LARGESTOCK
			
			
				
					
						899422348
						CUSIP
					
					Whatchamacallit, Inc.
					WHAT
					883897
				
				17
				SMALLSTOCK
			
			
				
					
						922908645
						CUSIP
					
					Mid-Cap Index Fund Admiral Shares
					VIMAX
				
			
		
	
`)
	var expected ofxgo.Response
	GMT := time.FixedZone("GMT", 0)
	expected.Version = "203"
	expected.Signon.Status.Code = 0
	expected.Signon.Status.Severity = "INFO"
	expected.Signon.DtServer = ofxgo.Date(time.Date(2017, 4, 1, 20, 12, 44, 0, GMT))
	expected.Signon.Language = "ENG"
	expected.Signon.Org = "INVSTRUS"
	expected.Signon.Fid = "9999"
	var units1, unitprice1, commission1, total1, amount2 big.Rat
	units1.SetFrac64(100, 1)
	unitprice1.SetFrac64(229, 1)
	commission1.SetFrac64(9, 1)
	total1.SetFrac64(-22909, 1)
	amount2.SetFrac64(22000, 1)
	dtuser := ofxgo.Date(time.Date(2017, 1, 18, 0, 0, 0, 0, GMT))
	dtavail := ofxgo.Date(time.Date(2017, 1, 23, 0, 0, 0, 0, GMT))
	dtsettle := ofxgo.Date(time.Date(2017, 2, 7, 0, 0, 0, 0, GMT))
	invtranlist := ofxgo.InvTranList{
		DtStart: ofxgo.Date(time.Date(2017, 1, 1, 0, 0, 0, 0, GMT)),
		DtEnd:   ofxgo.Date(time.Date(2017, 3, 31, 0, 0, 0, 0, GMT)),
		InvTransactions: []ofxgo.InvTransaction{
			ofxgo.BuyStock{
				InvBuy: ofxgo.InvBuy{
					InvTran: ofxgo.InvTran{
						FiTId:    "729483191",
						DtTrade:  ofxgo.Date(time.Date(2017, 2, 3, 0, 0, 0, 0, GMT)),
						DtSettle: &dtsettle,
					},
					SecId: ofxgo.SecurityId{
						UniqueId:     "78462F103",
						UniqueIdType: "CUSIP",
					},
					Units:       ofxgo.Amount(units1),
					UnitPrice:   ofxgo.Amount(unitprice1),
					Commission:  ofxgo.Amount(commission1),
					Total:       ofxgo.Amount(total1),
					SubAcctSec:  "CASH",
					SubAcctFund: "CASH",
				},
				BuyType: "BUY",
			},
		},
		BankTransactions: []ofxgo.InvBankTransaction{
			ofxgo.InvBankTransaction{
				Transactions: []ofxgo.Transaction{
					ofxgo.Transaction{
						TrnType:  "CREDIT",
						DtPosted: ofxgo.Date(time.Date(2017, 1, 20, 0, 0, 0, 0, GMT)),
						DtUser:   &dtuser,
						DtAvail:  &dtavail,
						TrnAmt:   ofxgo.Amount(amount2),
						FiTId:    "993838",
						Name:     "DEPOSIT",
						Memo:     "CHECK 19980",
					},
				},
				SubAcctFund: "CASH",
			},
		},
	}
	var availcash, marginbalance, shortbalance, balvalue big.Rat
	availcash.SetFrac64(1673, 100)
	marginbalance.SetFrac64(-8192, 10)
	shortbalance.SetFrac64(0, 1)
	balvalue.SetFrac64(25, 100)
	baldtasof := ofxgo.Date(time.Date(2017, 4, 1, 0, 0, 0, 0, GMT))
	invbalance := ofxgo.InvBalance{
		AvailCash:     ofxgo.Amount(availcash),
		MarginBalance: ofxgo.Amount(marginbalance),
		ShortBalance:  ofxgo.Amount(shortbalance),
		BalList: []ofxgo.Balance{
			ofxgo.Balance{
				Name:    "Sweep Int Rate",
				Desc:    "Current interest rate for sweep account balances",
				BalType: "PERCENT",
				Value:   ofxgo.Amount(balvalue),
				DtAsOf:  &baldtasof,
			},
		},
	}
	var balamt, availbalamt, posunits1, posunitprice1, posmktval1, posunits2, posunitprice2, posmktval2, oounits1, oolimitprice1, oounits2, oolimitprice2 big.Rat
	balamt.SetFrac64(20029, 100)
	availbalamt.SetFrac64(20029, 100)
	posunits1.SetFrac64(200, 1)
	posunitprice1.SetFrac64(23574, 100)
	posmktval1.SetFrac64(47148, 1)
	posunits2.SetFrac64(1, 1)
	posunitprice2.SetFrac64(3, 1)
	posmktval2.SetFrac64(300, 1)
	oounits1.SetFrac64(10, 1)
	oolimitprice1.SetFrac64(16850, 100)
	oounits2.SetFrac64(25, 1)
	oolimitprice2.SetFrac64(1975, 100)
	statementResponse := ofxgo.InvStatementResponse{
		TrnUID: "1a0117ad-692b-4c6a-a21b-020d37d34d49",
		Status: ofxgo.Status{
			Code:     0,
			Severity: "INFO",
		},
		DtAsOf: ofxgo.Date(time.Date(2017, 3, 31, 0, 0, 0, 0, GMT)),
		CurDef: "USD",
		InvAcctFrom: ofxgo.InvAcct{
			BrokerId: "invstrus.com",
			AcctId:   "91827364",
		},
		InvTranList: &invtranlist,
		InvPosList: ofxgo.PositionList{
			ofxgo.StockPosition{
				InvPos: ofxgo.InvPosition{
					SecId: ofxgo.SecurityId{
						UniqueId:     "78462F103",
						UniqueIdType: "CUSIP",
					},
					HeldInAcct:  "CASH",
					PosType:     "LONG",
					Units:       ofxgo.Amount(posunits1),
					UnitPrice:   ofxgo.Amount(posunitprice1),
					MktVal:      ofxgo.Amount(posmktval1),
					DtPriceAsOf: ofxgo.Date(time.Date(2017, 3, 31, 16, 0, 0, 0, GMT)),
					Memo:        "Price as of previous close",
				},
			},
			ofxgo.OptPosition{
				InvPos: ofxgo.InvPosition{
					SecId: ofxgo.SecurityId{
						UniqueId:     "129887339",
						UniqueIdType: "CUSIP",
					},
					HeldInAcct:  "CASH",
					PosType:     "LONG",
					Units:       ofxgo.Amount(posunits2),
					UnitPrice:   ofxgo.Amount(posunitprice2),
					MktVal:      ofxgo.Amount(posmktval2),
					DtPriceAsOf: ofxgo.Date(time.Date(2017, 3, 31, 16, 0, 0, 0, GMT)),
				},
			},
		},
		InvBal: &invbalance,
		InvOOList: ofxgo.OOList{
			ofxgo.OOBuyMF{
				OO: ofxgo.OO{
					FiTId: "76464632",
					SecId: ofxgo.SecurityId{
						UniqueId:     "922908645",
						UniqueIdType: "CUSIP",
					},
					DtPlaced:    ofxgo.Date(time.Date(2017, 3, 10, 12, 44, 45, 0, GMT)),
					Units:       ofxgo.Amount(oounits1),
					SubAcct:     "CASH",
					Duration:    "GOODTILCANCEL",
					Restriction: "NONE",
					LimitPrice:  ofxgo.Amount(oolimitprice1),
				},
				BuyType:  "BUY",
				UnitType: "SHARES",
			},
			ofxgo.OOBuyStock{
				OO: ofxgo.OO{
					FiTId: "999387423",
					SecId: ofxgo.SecurityId{
						UniqueId:     "899422348",
						UniqueIdType: "CUSIP",
					},
					DtPlaced:    ofxgo.Date(time.Date(2017, 3, 24, 3, 19, 0, 0, GMT)),
					Units:       ofxgo.Amount(oounits2),
					SubAcct:     "CASH",
					Duration:    "GOODTILCANCEL",
					Restriction: "ALLORNONE",
					LimitPrice:  ofxgo.Amount(oolimitprice2),
				},
				BuyType: "BUY",
			},
		},
	}
	expected.InvStmt = append(expected.InvStmt, &statementResponse)
	var yield1, yield2, strikeprice big.Rat
	yield1.SetFrac64(192, 100)
	yield2.SetFrac64(17, 1)
	strikeprice.SetFrac64(79, 1)
	seclist := ofxgo.SecurityList{
		Securities: []ofxgo.Security{
			ofxgo.StockInfo{
				SecInfo: ofxgo.SecInfo{
					SecId: ofxgo.SecurityId{
						UniqueId:     "78462F103",
						UniqueIdType: "CUSIP",
					},
					SecName: "S&P 500 ETF",
					Ticker:  "SPY",
					FiId:    "99184",
				},
				Yield:      ofxgo.Amount(yield1),
				AssetClass: "OTHER",
			},
			ofxgo.OptInfo{
				SecInfo: ofxgo.SecInfo{
					SecId: ofxgo.SecurityId{
						UniqueId:     "129887339",
						UniqueIdType: "CUSIP",
					},
					SecName: "John's Fertilizer Puts",
					Ticker:  "FERTP",
					FiId:    "882919",
				},
				OptType:     "PUT",
				StrikePrice: ofxgo.Amount(strikeprice),
				DtExpire:    ofxgo.Date(time.Date(2017, 9, 1, 0, 0, 0, 0, GMT)),
				ShPerCtrct:  100,
				SecId: &ofxgo.SecurityId{
					UniqueId:     "983322180",
					UniqueIdType: "CUSIP",
				},
				AssetClass: "LARGESTOCK",
			},
			ofxgo.StockInfo{
				SecInfo: ofxgo.SecInfo{
					SecId: ofxgo.SecurityId{
						UniqueId:     "899422348",
						UniqueIdType: "CUSIP",
					},
					SecName: "Whatchamacallit, Inc.",
					Ticker:  "WHAT",
					FiId:    "883897",
				},
				Yield:      ofxgo.Amount(yield2),
				AssetClass: "SMALLSTOCK",
			},
			ofxgo.MFInfo{
				SecInfo: ofxgo.SecInfo{
					SecId: ofxgo.SecurityId{
						UniqueId:     "922908645",
						UniqueIdType: "CUSIP",
					},
					SecName: "Mid-Cap Index Fund Admiral Shares",
					Ticker:  "VIMAX",
				},
			},
		},
	}
	expected.SecList = append(expected.SecList, &seclist)
	response, err := ofxgo.ParseResponse(responseReader)
	if err != nil {
		t.Fatalf("Unexpected error unmarshalling response: %s\n", err)
	}
	checkResponsesEqual(t, &expected, response)
}