File size: 30,379 Bytes
9988c8e
e2b74e4
 
 
 
5564ecb
1c87f53
e2b74e4
5564ecb
 
 
e2b74e4
 
5564ecb
e2b74e4
1c87f53
52ec837
1c87f53
 
 
 
 
 
 
 
 
 
 
44f174e
 
9ec0cd6
1c87f53
 
d53adef
1c87f53
d53adef
1c87f53
d53adef
1c87f53
d53adef
1c87f53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e2b74e4
 
 
5564ecb
e2b74e4
 
 
 
 
5564ecb
e2b74e4
 
 
5564ecb
 
 
 
 
e2b74e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ef9fcc8
 
e2b74e4
ef9fcc8
e2b74e4
ef9fcc8
 
 
 
e2b74e4
 
 
 
 
 
146b8fe
e2b74e4
 
 
 
 
 
 
 
 
 
ef9fcc8
e2b74e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5564ecb
e2b74e4
 
5564ecb
 
e2b74e4
5564ecb
 
 
 
e2b74e4
 
 
 
 
 
 
 
 
 
 
 
 
ef9fcc8
 
 
e2b74e4
 
 
 
 
 
 
 
ef9fcc8
e2b74e4
 
 
 
 
 
 
ef9fcc8
e2b74e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9988c8e
 
c506a3f
e2b74e4
 
5564ecb
e2b74e4
 
5564ecb
e2b74e4
 
5564ecb
 
e2b74e4
5564ecb
 
e2b74e4
 
c506a3f
 
 
9988c8e
024703e
 
b24ccd7
 
 
 
 
 
 
 
 
 
5564ecb
 
 
b24ccd7
5ca26a9
838738f
 
 
 
 
8985d0d
9988c8e
838738f
 
 
 
 
9484a7b
9988c8e
 
9484a7b
4c50e38
e2b74e4
ef9fcc8
e2b74e4
 
 
 
 
 
3b5e8c9
e2b74e4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9988c8e
c506a3f
9988c8e
 
 
 
 
 
e96cccd
 
9988c8e
 
 
 
d0fa370
5ca26a9
5564ecb
9988c8e
7f38eee
9988c8e
 
 
5ca26a9
5564ecb
c506a3f
9988c8e
 
 
 
 
 
 
9b02218
9988c8e
 
 
 
 
 
 
027c2c7
 
9988c8e
 
 
e767c6b
c506a3f
9988c8e
 
 
82b30a1
49b2f06
 
 
 
 
 
c506a3f
49b2f06
 
 
 
 
 
9988c8e
 
 
 
5a93b14
 
 
 
 
 
c506a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
b8a768c
38138dd
df0d1ca
 
38138dd
 
df0d1ca
38138dd
df0d1ca
 
 
 
 
38138dd
df0d1ca
 
 
8e4fa41
df0d1ca
c506a3f
 
5a93b14
 
c506a3f
5a93b14
 
 
 
9988c8e
5564ecb
 
 
 
 
 
 
 
c506a3f
5564ecb
bb997e4
5564ecb
 
 
c506a3f
 
 
 
5cc7ddc
5564ecb
 
 
 
 
 
 
 
 
 
 
 
 
 
c506a3f
5564ecb
 
 
 
 
c506a3f
 
 
 
 
 
 
 
 
34c83f6
c506a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ca6c47a
c506a3f
aa8057a
c506a3f
aa8057a
c506a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa8057a
c506a3f
aa8057a
c506a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa8057a
c506a3f
aa8057a
c506a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
aa8057a
c506a3f
aa8057a
c506a3f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a129216
c506a3f
 
1c87f53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c506a3f
5cc7ddc
 
 
 
 
 
 
 
 
 
 
 
 
 
efec597
df0d1ca
5cc7ddc
c506a3f
 
e2b74e4
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
from typing import Dict, List
from fastapi import FastAPI, APIRouter, HTTPException, Request, Response # type: ignore
from fastapi.responses import JSONResponse, RedirectResponse, HTMLResponse # type: ignore
from datetime import datetime, timedelta
from fastapi.templating import Jinja2Templates
from app.dialogflow.services.dialog_service import dialog_service
from utils.format_data_dialog import format_time, get_weekday_name

from common.external.external_api import api
from app.dialogflow.services.origin_codes import origin_codes
from common.response.respone_dialogflow import DialogFlowResponseAPI
router = APIRouter()

templates = Jinja2Templates(directory="templates")


@router.post('/info/confirm')
async def confirm(request: Request):
    body = await request.json()
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters", {}) if isinstance(session_info.get("parameters"), dict) else {}
    raw_date = parameters.get("date")
    departure_city = parameters.get("departure_city")
    destination_city = parameters.get("destination_city")
    origin_office = parameters.get("origin_office")
    dest_office = parameters.get("dest_office")
    raw_ticket_number = parameters.get("ticket_number")
    ticket_number = int(raw_ticket_number) if raw_ticket_number else 1
    date = dialog_service.to_datetime_from_Dialogflow(raw_date)
    date, week_day = get_weekday_name(date)
    text = [f"""Ngày: {date} {week_day}\nSố vé: {ticket_number}"""]
    temp = ""
    if origin_office and dest_office:
        temp = f"""Điểm đi: {origin_office}\nĐiểm đến: {dest_office}\n"""
    elif origin_office and departure_city:
        temp = f"""Điểm đi: {origin_office}\nĐiểm đến: {departure_city}\n"""  
    elif dest_office and departure_city:
        temp = f"""Điểm đi: {departure_city}\nĐiểm đến: {dest_office}\n"""
    elif departure_city and destination_city:
        temp = f"""Điểm đi: {departure_city}\nĐiểm đến: {destination_city}\n"""
    text[0] = temp + text[0] 
    payload = {
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [
                                                {"text": "Tìm chuyến xe"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }
    return DialogFlowResponseAPI(text=text, payload=payload)
@router.post('/routes')
async def route(request: Request):
    body = await request.json()
    raw_departure_city, raw_destination_city, raw_ticket_number , raw_date, _ = dialog_service.get_param_from_dialogflow(body)
    
    
    ticket_count = int(raw_ticket_number) if raw_ticket_number else 1

    if raw_date is None:
        from_time, to_time = dialog_service.process_dates_to_timestamp()
        date = datetime.today().date().strftime('%m-%d-%Y')
    else:
        date = raw_date.strftime('%m-%d-%Y')
        from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date)
    departure_code = origin_codes.get(raw_departure_city)
    destination_code = origin_codes.get(raw_destination_city)
    route_dep_to_des = await dialog_service.search_route_ids_from_province(departure_code,destination_code)
    route_des_to_dep = await dialog_service.search_route_ids_from_province(destination_code,departure_code)
    routes_ids = list(set(route_dep_to_des + route_des_to_dep))
    payload = {
        "from_time": from_time,
        "to_time": to_time,
        "route_ids": routes_ids,
        "ticket_count": 1,
        "sort_by": ["price", "departure_time"]
    }
    try:
        respone = await api.post("/search/trips", payload=payload)
        data = respone["data"]["items"]
        total = respone["data"]["total"]
        if total > 0:
            price = data[0]["price"]
            list_raw_departure_times = sorted(list(set([ trip["raw_departure_time"] for trip in data])))
            list_raw_seat_type = list(set([ trip["seat_type_name"] for trip in data]))
            seat_type_trip_string = "**" + "** | **".join(map(str, list_raw_seat_type)) + "**"
            schedule_time_trip = "**" + "** | **".join(map(str, list_raw_departure_times)) + "**"
            duration = data[0]["duration"]
            link = f'https://stag.futabus.vn/dat-ve?from={departure_code}&fromTime={date}&isReturn=false&ticketCount={ticket_count}&to={destination_code}&toTime='
            text = [f"Tuyến xe **{raw_departure_city}** - **{raw_destination_city}**\n \
                                     Loại xe: {seat_type_trip_string} \n \
                                     Thời gian hành trình: {duration} giờ \n \
                                     Giá vé: **{price}** VND"]
            payload = {
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [
                                                {"text": "Tìm chuyến xe"},
                                                {"text": "Xem lịch trình khác"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }
            
            return DialogFlowResponseAPI(text=text, payload=payload)

        text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]
        payload = {
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [
                                                {"text": "Xem lịch trình khác"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }
        return DialogFlowResponseAPI(text=text, payload=payload)
        # return DialogFlowResponeAPI(text=['Hello'])
    except Exception as e:
        return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."])


@router.post('/price')
async def price(request: Request):
    body = await request.json()
    raw_departure_city, raw_destination_city, _, raw_date, _ = dialog_service.get_param_from_dialogflow(body)
    
    if raw_date is None:
        from_time, to_time = dialog_service.process_dates_to_timestamp()
    from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date)

    departure_code = origin_codes.get(raw_departure_city)
    destination_code = origin_codes.get(raw_destination_city)
    route_dep_to_des = await dialog_service.search_route_ids_from_province(departure_code,destination_code)
    route_des_to_dep = await dialog_service.search_route_ids_from_province(destination_code,departure_code)
    routes_ids = list(set(route_dep_to_des + route_des_to_dep))
    payload = {
        "from_time": from_time,
        "to_time": to_time,
        "route_ids": routes_ids,
        "ticket_count": 1,
        "sort_by": ["price", "departure_time"]
    }
    try:
        respone = await api.post("/search/trips", payload=payload)
        total = respone["data"]["total"]
        if total > 0:
            price = respone["data"]["items"][0]["price"]
            text = [f"Tuyến xe **{raw_departure_city}** - **{raw_destination_city}**\n"
                                     f"Giá vé: **{price}** VND.\n \
                                     Bạn có muốn đặt vé không?"
                                     ]
            payload = {
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [
                                                {"text": "Có, tôi muốn đặt vé"},
                                                {"text": "Xem giá vé tuyến xe khác"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }
            return DialogFlowResponseAPI(text=text, payload=payload)
        text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]
        payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [
                                                {"text": "Xem giá vé lịch trình khác"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }
        
        return DialogFlowResponseAPI(text=text, payload=payload)
    except:
        return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."])


@router.post('/trip/route/list')
async def booking_trip(request: Request) -> Response:
    body = await request.json()
    raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, raw_time_of_day = dialog_service.get_param_from_dialogflow(body)
    
    date = raw_date.strftime('%m-%d-%Y')
    from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date)
    ticket_count = int(raw_ticket_number) if raw_ticket_number else 1

    departure_code = origin_codes.get(raw_departure_city)
    destination_code = origin_codes.get(raw_destination_city)

    route_dep_to_des = await dialog_service.search_route_ids_from_province(departure_code,destination_code)
    route_des_to_dep = await dialog_service.search_route_ids_from_province(destination_code,departure_code)
    routes_ids = list(set(route_dep_to_des + route_des_to_dep))
    try:
        data = await dialog_service.search_trip(from_time, to_time, routes_ids, ticket_count)
        total = len(data)
        if total > 0:
                trips = []
                routes_name = []
                for trip in data:
                    if ticket_count <= trip["empty_seat_quantity"]:
                        route = f"{trip['route']['origin_hub_name']} => {trip['route']['dest_hub_name']}"
                        if trip["route"] and route not in routes_name:
                            routes_name.append(f"{trip['route']['origin_hub_name']} => {trip['route']['dest_hub_name']}")
                        trips.append({
                                "route_name": f"{trip['route']['origin_hub_name']} => {trip['route']['dest_hub_name']}",
                                "route_id": trip["route_id"],
                                "id": trip["id"],
                                "departure_date": trip["raw_departure_date"],
                                "departure_time": trip["raw_departure_time"],
                                "kind": trip["seat_type_name"],
                                "way_id": trip["way_id"]

                                })
                text = ["Quý khách vui lòng lựa chọn chuyến xe\n" + "\n".join(f"{i+1}. {name}" for i, name in enumerate(routes_name))]
                payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [ 
                                                {"text": name} for name in (routes_name)
                                            ]
                                        }
                                    ]
                                ]
                            }
                parameters = {
                    "trip_list": trips,
                    "routes_name": routes_name
                }
                return DialogFlowResponseAPI(text=text, payload=payload,parameters=parameters)                
            
        text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]
        payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [
                                                {"text": "Xem tuyến xe khác"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }
                        
        return DialogFlowResponseAPI(text=text, payload=payload)
    except Exception as e:
        print(e)
        return JSONResponse(
                    {
                    "fulfillment_response": {
                        "messages": [
                        {
                            "text": {
                            "text": ["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]
                            }
                        }
                        ]
                    },
                }
        )

@router.post('/trip/route/check-route-select')
async def is_valid_select_trip(request: Request) -> Response:
    body = await request.json()
    raw_input = body.get("text", "")
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters")
    routes_name = parameters.get("routes_name")
    if raw_input:
        raw_input = raw_input.strip()
    if raw_input in routes_name:
        trip_list: List[Dict[str, any]] = parameters.get("trip_list")
        for trip in trip_list:
            if trip["route_name"] == raw_input:
                route_id = int(trip["route_id"])
                kind = trip["kind"]
                way_id = trip["way_id"]
                break
        
        parameters = {
                "is_valid_trip": True,
                "route_name": raw_input,
                "kind": kind,
                "route_id": route_id,
                "way_id": way_id,   
            }
    else:
        parameters = {
                "is_valid_trip": False,
            }
    return DialogFlowResponseAPI(parameters=parameters)

@router.post('/trip/time-trip-list')
async def time_trip(request: Request) -> Response:
    try:
        body = await request.json()
        session_info = body.get("sessionInfo", {})
        parameters = session_info.get("parameters")
        trip_list: List[Dict[str, any]] = parameters.get("trip_list", [])
        raw_route_id = parameters.get("route_id", None)
        route_name = parameters.get("route_name", "")

        route_id = int(raw_route_id) if raw_route_id else None
        time_list = []
        for trip in trip_list:
            if (trip["route_id"]) == route_id:
                time_list.append({"time": trip["departure_time"], "id": trip["id"]})
        parameters = {
            "time_list": time_list
        }
        text = [f"Quý khách lựa chọn thời gian chuyến {route_name}\n" + " | ".join([item["time"] for item in time_list])]
        payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [ 
                                                {"text": time["time"]} for time in (time_list)
                                            ]
                                        }
                                    ]
                                ]
                            }
        return DialogFlowResponseAPI(text=text, payload=payload ,parameters=parameters)
    except Exception as e:
        print(e)
        return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."])

@router.post('/trip/check-time-select')
async def is_valid_select_time(request: Request) -> Response:
    try:
        body = await request.json()
        session_info = body.get("sessionInfo", {})
        parameters = session_info.get("parameters")

        raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, raw_time_of_day = dialog_service.get_param_from_dialogflow(body)
    
        date = raw_date.strftime('%m-%d-%Y')
        from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date)
        ticket_count = int(raw_ticket_number) if raw_ticket_number else 1

        departure_code = origin_codes.get(raw_departure_city)
        destination_code = origin_codes.get(raw_destination_city)

        route_dep_to_des = await dialog_service.search_route_ids_from_province(departure_code,destination_code)
        route_des_to_dep = await dialog_service.search_route_ids_from_province(destination_code,departure_code)
        routes_ids = list(set(route_dep_to_des + route_des_to_dep))

        time_list: List[Dict[str, any]] = parameters.get("time_list", [])
        time_select = parameters.get("time-select", None)
        route_name = parameters.get("route_name", None)
        
        if time_select is not None:
            time_select = format_time(time_select)
            for time in time_list:
                if time_select == time["time"]:
                    id = int(time["id"])
                    trip = await dialog_service.search_trip_by_id(id, from_time, to_time, routes_ids, ticket_count)
                    departure_date = trip["raw_departure_date"]
                    parameters = {
                        "is_valid_time": True,
                        "departure_time": time_select,
                        "departure_date": departure_date,
                        "trip": trip,
                    }
                    text = [f' Quý khách chọn chuyến {time_select} | {route_name}']
                    return DialogFlowResponseAPI(text=text, parameters=parameters)
                
        parameters = {
                "is_valid_time": False
            }
        text = []
        return DialogFlowResponseAPI(text=text, parameters=parameters)
    except Exception as e:
        print(e)
        return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."])


@router.post('/trip/seats')
async def seats_trip(request: Request) -> Response:
    try:
        body = await request.json()
        session_info = body.get("sessionInfo", {})
        parameters = session_info.get("parameters")
        
        trip = parameters.get("trip", None)
        route_id: int = parameters.get("route_id", None)
        route_id = int(route_id) if route_id else None
        departure_date: str = parameters.get("departure_date", None)
        departure_time: str = parameters.get("departure_time", None)
        kind: str = parameters.get("kind", None)

        trip_id = int(trip["id"]) if trip else None
        seats = await dialog_service.seats_trip(route_id, trip_id, departure_date, departure_time, kind)
        seats_empty = [ seat for seat in seats if seat["bookStatus"] == 0 ]
        seats_empty.sort(key=lambda x: x["chair"])
        text=["Vui lòng chọn ghế"]
        payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [ 
                                                {"text": seat["chair"]} for seat in (seats_empty)
                                            ]
                                        }
                                    ]
                                ]
                            }
        parameters = {
            "seat_list": seats
        }
        return DialogFlowResponseAPI(text=text, payload=payload, parameters=parameters)
    except Exception as e:
        print(e)
        return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."])
@router.post('/trip/check-seat-select')
async def is_valid_select_seat(request: Request) -> Response:
    try:
        body = await request.json()
        session_info = body.get("sessionInfo", {})
        parameters = session_info.get("parameters")
        
        trip = parameters.get("trip", None)
        route_id: int = parameters.get("route_id", None)
        route_id = int(route_id) if route_id else None
        departure_date: str = parameters.get("departure_date", None)
        departure_time: str = parameters.get("departure_time", None)
        kind: str = parameters.get("kind", None)
        seat: str = parameters.get("seat", None)

        trip_id = int(trip["id"]) if trip else None

        is_valid = await dialog_service.is_valid_select_seat(seat, route_id, trip_id, departure_date, departure_time, kind)
        if is_valid:
            parameters = {
                "is_valid_seat": True,
                "seat": seat
            }
            text = [f"Quý khách chọn ghế {seat}"]
        else:
            parameters = {
                "is_valid_seat": False,
                "seat": None        
            }
            text = [f"Ghế {seat} đã được đặt. Quý khách vui lòng chọn ghế khác"]
        return DialogFlowResponseAPI(text=text, parameters=parameters)
        
    except Exception as e:
        return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."])

@router.post('/trip/stop/pickup')
async def pickup(request: Request) -> Response:
    body = await request.json()
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters")
    trip: dict[str, any] = parameters.get("trip", None)
    route_id: int = trip["route_id"]
    route_id = int(route_id) if route_id else None
    way_id: int = trip["way_id"]
    way_id = int(way_id) if way_id else None
    pickup_list = await dialog_service.pickup_list(route_id, way_id)
    
    text=["Quý khách vui lòng chọn điểm đón"]
    payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [ 
                                                {"text": pickup["name"]} for pickup in (pickup_list)
                                            ]
                                        }
                                    ]
                                ]
                            }
    parameters = {
        "pickup_list": pickup_list
    }
    
    return DialogFlowResponseAPI(text=text, payload=payload, parameters=parameters)

@router.post('/trip/check-pickup-select')
async def is_valid_select_pickup(request: Request) -> Response:
    body = await request.json()
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters")
    trip = parameters.get("trip", None)
    route_id: int = trip["route_id"]
    route_id = int(route_id) if route_id else None
    way_id: int = trip["way_id"]
    way_id = int(way_id) if way_id else None
    raw_input = (body.get("text",""))
    pickup = raw_input.strip()

    is_valid = await dialog_service.is_valid_pickup(pickup, route_id, way_id)

    if is_valid:
        parameters = {
            "is_valid_pickup": True,
            "pick_up": pickup
        }
        text = [f"Quý khách chọn điểm đón {pickup}"]
    else:
        parameters = {
            "is_valid_pickup": False,
        }
        text = [f"Điểm đón không hợp lệ. Quý khách vui lòng chọn điểm đón khác"]

    return DialogFlowResponseAPI(text=text, parameters=parameters)

@router.post('/trip/stop/dropoff')
async def dropoff(request: Request) -> Response:
    body = await request.json()
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters")
    trip = parameters.get("trip", None)
    route_id: int = trip["route_id"]
    route_id = int(route_id) if route_id else None
    way_id: int = trip["way_id"]
    way_id = int(way_id) if way_id else None
    dropoff_list = await dialog_service.dropoff_list(route_id, way_id)

    text=["Quý khách vui lòng chọn điểm trả khách"]
    payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [ 
                                                {"text": dropoff["name"]} for dropoff in (dropoff_list)
                                            ]
                                        }
                                    ]
                                ]
                            }
    parameters = {
        "dropoff_list": dropoff_list
    }
    
    return DialogFlowResponseAPI(text=text, payload=payload, parameters=parameters)

@router.post('/trip/check-dropoff-select')
async def is_valid_select_dropoff(request: Request) -> Response:
    body = await request.json()
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters")
    trip = parameters.get("trip", None)
    route_id: int = trip["route_id"]
    route_id = int(route_id) if route_id else None
    way_id: int = trip["way_id"]
    way_id = int(way_id) if way_id else None
    raw_input = (body.get("text",""))
    dropoff = raw_input.strip()

    is_valid = await dialog_service.is_valid_dropoff(dropoff, route_id, way_id)

    if is_valid:
        parameters = {
            "is_valid_dropoff": True,
            "drop_off": dropoff
        }
        text = [f"Quý khách chọn điểm trả khách {dropoff}"]
    else:
        parameters = {
            "is_valid_dropoff": False,
        }
        text = [f"Điểm trả khách không hợp lệ. Quý khách vui lòng chọn điểm trả khách khác"]

    return DialogFlowResponseAPI(text=text, parameters=parameters)

@router.post('/trip/ticket/info')
async def response_ticket_info(request: Request) -> Response:
    body = await request.json()
    session_info = body.get("sessionInfo", {})
    parameters = session_info.get("parameters")

    user_name = parameters.get("user_name", None)
    phone_number = parameters.get("phone_number", None)
    email = parameters.get("email", None)
    seat = parameters.get("seat", None)
    pickup = parameters.get("pick_up", None)
    dropoff = parameters.get("drop_off", None)

    trip = parameters.get("trip", None)

    route_name = trip["route"]["name"]
    time = trip["raw_departure_time"]
    date = trip["raw_departure_date"]
    price = trip["price"]
    price = int(price) if price else None

    text = [
        f" \
        **Thông tin hành khách**\
        \n\
        Họ và tên {user_name} \
        Số điện thoại {phone_number} \
        Email {email} \
        \n\
        **Thông tin lượt đi** \
        \n\
        Tuyến xe {route_name} \
        Thời gian xuất bến {time} {date} \
        Số ghế {seat} \
        Điểm lên xe {pickup} \
        Điểm trả khách {dropoff} \
        Tổng tiền lượt đi {price} VND \
        "
        ]
    
    payload={
                                "richContent": [
                                    [
                                        {
                                            "type": "chips",
                                            "options": [ 
                                                {"text": "Đặt vé"},
                                                {"text": "Không, cảm ơn"}
                                            ]
                                        }
                                    ]
                                ]
                            }


    return DialogFlowResponseAPI(text=text, payload=payload)


@router.get("/")
def home():
    return "Hello World!"

@router.get('/chatbot', response_class=HTMLResponse)
async def index(request: Request):
    return templates.TemplateResponse("index.html", {"request": request, "title": "Dawi Chatbot"})