package bcbsimodel

import (
	"encoding/xml"
	"time"

	"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
)

func GetEnvelope(eligibility viewmodel.Eligibility) Envelope {
	soapEnvelope := Envelope{}
	soapEnvelope.Namespace = "http://schemas.xmlsoap.org/soap/envelope/"
	soapEnvelope.Body.MemberEligibilityRequest = GetEligibilityRequest(eligibility)
	soapEnvelope.Body.MemberEligibilityRequest.Namespace = "http://v30.bx.services.bcbsa.com/eligibility-ext"
	return soapEnvelope
}

func GetEligibilityRequest(eligibility viewmodel.Eligibility) MemberEligibilityRequest {
	retVal := MemberEligibilityRequest{}
	retVal.Version.MajorVersion = 3
	retVal.Version.MinorVersion = 0

	retVal.QueryHeader.TimeSent = time.Now().Format("2006-01-02T15:04:05")
	retVal.QueryHeader.TrackingID = eligibility.TrackingID
	retVal.Query.PayerInfo.PayerID = eligibility.Payer.PayerID
	retVal.Query.PayerInfo.PayerName = eligibility.Payer.PayerName

	retVal.Query.ProviderInfo.ProviderID = eligibility.Provider.ProviderID
	retVal.Query.ProviderInfo.ProviderNPI = eligibility.Provider.ProviderNPI
	retVal.Query.ProviderInfo.Provider.Organization = eligibility.Provider.ProviderName
	retVal.Query.ProviderInfo.Provider.Name.First = eligibility.Provider.Name.First
	retVal.Query.ProviderInfo.Provider.Name.Last = eligibility.Provider.Name.Last
	retVal.Query.ProviderInfo.Provider.Name.Middle = eligibility.Provider.Name.Middle
	retVal.Query.SubscriberInfo.SubscriberID = eligibility.Subscriber.SubscriberID
	retVal.Query.SubscriberInfo.PatientType = eligibility.Subscriber.PatientType
	retVal.Query.SubscriberInfo.Name.First = eligibility.Subscriber.Name.First
	retVal.Query.SubscriberInfo.Name.Last = eligibility.Subscriber.Name.Last
	retVal.Query.SubscriberInfo.Name.Middle = eligibility.Subscriber.Name.Middle
	retVal.Query.SubscriberInfo.DemographicInfo.DateOfBirth = eligibility.Subscriber.DemographicInfo.DateOfBirth.Format("20060102")
	retVal.Query.SubscriberInfo.DemographicInfo.GenderCode = eligibility.Subscriber.DemographicInfo.Gender

	var dependents []Dependent
	for _, d := range eligibility.Subscriber.Dependents {
		dependent := Dependent{}
		dependent.PatientAccountNumber = d.PatientAccountNumber
		dependent.DemographicInfo.DateOfBirth = d.DemographicInfo.DateOfBirth.Format("20060102")
		dependent.DemographicInfo.GenderCode = d.DemographicInfo.Gender
		dependent.Name.First = d.Name.First
		dependent.Name.Last = d.Name.Last
		dependent.Name.Middle = d.Name.Middle
		dependents = append(dependents, dependent)
	}
	if len(dependents) == 0 {
		dependents = append(dependents, Dependent{})
	}

	retVal.Query.SubscriberInfo.DependentInfo.Dependents = dependents
	retVal.Query.ServiceInfo.DateOfService = eligibility.ServiceInfo.DateOfService.Format("20060102")
	retVal.Query.ServiceInfo.ServiceTypeCodes.ServiceTypeCode = eligibility.ServiceInfo.ServiceTypeCodes

	return retVal
}

type Envelope struct {
	XMLName   xml.Name     `xml:"soap:Envelope"`
	Body      EnvelopeBody `xml:"soap:Body"`
	Namespace string       `xml:"xmlns:soap,attr"`
}

type EnvelopeBody struct {
	MemberEligibilityRequest MemberEligibilityRequest `xml:"elig:MemberEligibilityRequest"`
}

type MemberEligibilityRequest struct {
	Version     Version     `xml:"version"`
	QueryHeader QueryHeader `xml:"elig:eligibility-benefits-query-header"`
	Query       Query       `xml:"elig:eligibility-benefits-query"`
	Namespace   string      `xml:"xmlns:elig,attr"`
}

type Version struct {
	MajorVersion int64 `xml:"majorVersion"`
	MinorVersion int64 `xml:"minorVersion"`
}

type QueryHeader struct {
	TrackingID string `xml:"tracking-id"`
	TimeSent   string `xml:"time-sent"`
}

type Query struct {
	PayerInfo      PayerInfo      `xml:"elig:payer-info"`
	ProviderInfo   ProviderInfo   `xml:"elig:provider-info"`
	SubscriberInfo SubscriberInfo `xml:"elig:subscriber-info"`
	ServiceInfo    ServiceInfo    `xml:"elig:service-info"`
}

type ServiceInfo struct {
	DateOfService    string           `xml:"elig:date-of-service"`
	ServiceTypeCodes ServiceTypeCodes `xml:"elig:service-type-codes"`
}

type ServiceTypeCodes struct {
	ServiceTypeCode []string `xml:"elig:service-type-code"`
}

type SubscriberInfo struct {
	PatientType     string          `xml:"elig:patient-type"`
	SubscriberID    string          `xml:"elig:subscriber-id"`
	Name            Name            `xml:"elig:name"`
	DemographicInfo DemographicInfo `xml:"elig:demographic-info"`
	DependentInfo   DependentInfo   `xml:"elig:dependent-info"`
}

type DependentInfo struct {
	Dependents []Dependent `xml:"elig:dependent"`
}

type Dependent struct {
	PatientAccountNumber string          `xml:"elig:patient-account-number"`
	Name                 Name            `xml:"elig:name"`
	DemographicInfo      DemographicInfo `xml:"elig:demographic-info"`
}

type DemographicInfo struct {
	DateOfBirth string `xml:"elig:date-of-birth"`
	GenderCode  string `xml:"elig:gender-code"`
}

type ProviderInfo struct {
	ProviderID  string   `xml:"elig:provider-id"`
	ProviderNPI string   `xml:"elig:provider-npi"`
	Provider    Provider `xml:"elig:provider-name"`
}

type Provider struct {
	Organization string `xml:"organization"`
	Name         Name   `xml:"elig:name"`
}

type Name struct {
	First  string `xml:"elig:first"`
	Last   string `xml:"elig:last"`
	Middle string `xml:"elig:middle"`
}

type PayerInfo struct {
	PayerName string `xml:"elig:payer-name"`
	PayerID   string `xml:"elig:payer-id"`
}
