1+ /*
2+ * Copyright 2025 HM Revenue & Customs
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+
17+ package connectors
18+
19+ import config .FrontendAppConfig
20+ import jakarta .inject .Singleton
21+ import models .NormalMode
22+ import models .responses .addresslookup .JourneyInitResponse .AddressLookupResponse
23+ import models .responses .addresslookup .JourneyOutcomeResponse .AddressLookupJourneyOutcome
24+ import play .api .i18n .{Lang , Messages , MessagesApi }
25+ import play .api .libs .json .*
26+ import uk .gov .hmrc .http .client .HttpClientV2
27+ import uk .gov .hmrc .http .{HeaderCarrier , StringContextOps }
28+
29+ import javax .inject .Inject
30+ import scala .concurrent .{ExecutionContext , Future }
31+ import play .api .Logger
32+
33+ @ Singleton
34+ class AddressLookupConnector @ Inject ()(val appConfig : FrontendAppConfig ,
35+ http : HttpClientV2 ,
36+ val messagesApi : MessagesApi )(implicit ec : ExecutionContext ) {
37+
38+ private val baseUrl : String = appConfig.addressLookupBaseUrl
39+ val addressLookupInitializeUrl : String = s " $baseUrl/api/v2/init "
40+ val addressLookupOutcomeUrl : String => String = (id : String ) => s " $baseUrl/api/v2/confirmed?id= $id"
41+
42+ private val sessionTimeout : Long = appConfig.sessionTimeOut
43+ private val addressLookupTimeoutUrl : String = appConfig.addressLookupTimeoutUrl
44+
45+ private val langResourcePrefix : String = " manageAgents.addressLookup"
46+
47+ private val continueUrl = appConfig.loginContinueUrl +
48+ controllers.manageAgents.routes.AddressLookupController .onSubmit(NormalMode ).url
49+
50+ private def setJourneyOptions (): Seq [(String , JsValue )] = {
51+ Seq (
52+ " continueUrl" -> JsString (continueUrl),
53+
54+ " ukMode" -> JsBoolean (true ),
55+ // TODO: we expect Welsh translation to be disabled / not working as expected
56+ " disableTranslations" -> JsBoolean (true ),
57+
58+ " showPhaseBanner" -> JsBoolean (true ),
59+ " alphaPhase" -> JsBoolean (true ),
60+
61+ " includeHMRCBranding" -> JsBoolean (true ),
62+
63+ " selectPageConfig" -> JsObject (
64+ Seq (
65+ " proposalListLimit" -> JsNumber (30 ),
66+ " showSearchLinkAgain" -> JsBoolean (true )
67+ )
68+ ),
69+ " confirmPageConfig" -> JsObject (
70+ Seq (
71+ " showChangeLink" -> JsBoolean (true ),
72+ " showSubHeadingAndInfo" -> JsBoolean (false ),
73+ " showSearchAgainLink" -> JsBoolean (false ),
74+ " showConfirmChangeText" -> JsBoolean (false ),
75+ )
76+ ),
77+ " manualAddressEntryConfig" -> JsObject (
78+ Seq (
79+ " line1MaxLength" -> JsNumber (255 ),
80+ " line2MaxLength" -> JsNumber (255 ),
81+ " line3MaxLength" -> JsNumber (255 ),
82+ " townMaxLength" -> JsNumber (255 )
83+ )
84+ ),
85+ " timeoutConfig" -> JsObject (
86+ Seq (
87+ " timeoutAmount" -> JsNumber (sessionTimeout),
88+ " timeoutUrl" -> JsString (addressLookupTimeoutUrl)
89+ )
90+ ),
91+ " pageHeadingStyle" -> JsString (" govuk-heading-l" )
92+ )
93+ }
94+
95+ private def setLabels (agentName : Option [String ], lang : Lang )
96+ (implicit messages : Messages ): Seq [(String , JsObject )] = {
97+ Seq (
98+ " appLevelLabels" -> JsObject (
99+ Seq (
100+ " navTitle" -> JsString (messagesApi.preferred( Seq ( lang ) )(s " $langResourcePrefix.header.title " ))
101+ )
102+ ),
103+ " selectPageLabels" -> JsObject (
104+ Seq (
105+ " heading" -> JsString (
106+ messages(
107+ s " $langResourcePrefix.select.heading " , agentName.getOrElse(" " )
108+ )
109+ )
110+ )
111+ ),
112+ " lookupPageLabels" -> JsObject (
113+ Seq (
114+ " heading" -> JsString (
115+ messages(
116+ s " $langResourcePrefix.lookup.heading " , agentName.getOrElse(" " )
117+ )
118+ )
119+ )
120+ ),
121+ " confirmPageLabels" -> JsObject (
122+ Seq (
123+ " heading" -> JsString (
124+ messages(
125+ s " $langResourcePrefix.confirm.heading " , agentName.getOrElse(" " )
126+ )
127+ ),
128+ " changeLinkText" -> JsString (
129+ messages(
130+ s " $langResourcePrefix.confirm.changeLinkText " , agentName.getOrElse(" " )
131+ )
132+ ),
133+ )
134+ ),
135+ " editPageLabels" -> JsObject (
136+ Seq (
137+ " heading" ->
138+ JsString (
139+ messages(
140+ s " $langResourcePrefix.edit.heading " , agentName.getOrElse(" " )
141+ )
142+ )
143+ )
144+ )
145+ )
146+ }
147+
148+ private def buildConfig (agentName : Option [String ])
149+ (implicit messages : Messages ): JsValue = {
150+ JsObject (
151+ Seq (
152+ " version" -> JsNumber (2 ),
153+ " options" -> JsObject (
154+ setJourneyOptions()
155+ ),
156+ " labels" -> JsObject (
157+ Seq (
158+ " en" -> JsObject (
159+ setLabels(agentName, Lang (" en" ) )
160+ )
161+ )
162+ )
163+ )
164+ )
165+ }
166+
167+ // Step 1: Journey start/init
168+ def initJourney (agentName : Option [String ])
169+ (implicit hc : HeaderCarrier , messages : Messages ): Future [AddressLookupResponse ] = {
170+ import play .api .libs .ws .writeableOf_JsValue
171+ val payload : JsValue = buildConfig(agentName)
172+ Logger (" application" ).info(s " [AddressLookupConnector] - body: ${Json .stringify(payload)}" )
173+ http.post(url " $addressLookupInitializeUrl" )
174+ .withBody(payload)
175+ .execute[AddressLookupResponse ]
176+ }
177+
178+ // Step 2: Extract journey result/outcome
179+ def getJourneyOutcome (id : String )
180+ (implicit hc : HeaderCarrier ): Future [AddressLookupJourneyOutcome ] = {
181+ Logger (" application" ).info(s " [AddressLookupConnector] - Extract address: ${addressLookupOutcomeUrl(id)}" )
182+ http.get(url " ${addressLookupOutcomeUrl(id)}" ).execute[AddressLookupJourneyOutcome ]
183+ }
184+
185+ }
0 commit comments