File size: 29,275 Bytes
9f55fd3
5bea5ac
 
 
e9d239b
 
 
870083e
 
 
 
e9d239b
870083e
e9d239b
e60baea
 
e9d239b
 
 
60655e0
870083e
e9d239b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
870083e
e9d239b
 
870083e
e9d239b
 
 
 
 
 
 
 
870083e
 
 
 
 
 
 
e9d239b
 
 
e6aaa19
5bea5ac
 
e9d239b
 
870083e
 
 
 
e9d239b
 
 
 
 
 
870083e
 
 
 
e9d239b
 
 
 
 
870083e
5bea5ac
e9d239b
 
030806e
e9d239b
e6aaa19
e9d239b
030806e
5bea5ac
870083e
e6aaa19
 
e9d239b
 
c5bc2b2
e9d239b
030806e
e9d239b
 
 
 
 
 
 
 
 
 
 
 
e6aaa19
 
e9d239b
 
e6aaa19
9f55fd3
 
 
 
 
e6aaa19
9f55fd3
e6aaa19
e9d239b
9f55fd3
870083e
9f55fd3
 
870083e
e9d239b
 
e6aaa19
e9d239b
 
870083e
 
 
 
e6aaa19
 
a3dec8c
e9d239b
 
 
 
 
 
 
e6aaa19
d8667c2
e9d239b
 
e6aaa19
 
e9d239b
 
e6aaa19
870083e
e9d239b
 
870083e
 
 
e6aaa19
6abfe5d
870083e
17ba015
870083e
d8667c2
 
17ba015
 
e6aaa19
870083e
e6aaa19
17ba015
 
 
870083e
e9d239b
870083e
17ba015
 
6abfe5d
e6aaa19
17ba015
e6aaa19
 
870083e
17ba015
870083e
 
 
e6aaa19
 
870083e
e9d239b
e6aaa19
17ba015
 
9f55fd3
68a43c1
17ba015
68a43c1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e6aaa19
17ba015
9f55fd3
e6aaa19
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9f55fd3
 
e6aaa19
68a43c1
9f55fd3
e6aaa19
68a43c1
 
9f55fd3
e6aaa19
68a43c1
 
9f55fd3
e6aaa19
68a43c1
 
9f55fd3
e6aaa19
 
6abfe5d
e6aaa19
 
9f55fd3
e60baea
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6abfe5d
 
 
 
e60baea
 
 
e6aaa19
17ba015
9f55fd3
 
 
 
e6aaa19
6419184
 
 
9f55fd3
 
6419184
e6aaa19
9f55fd3
 
e6aaa19
 
9f55fd3
e6aaa19
9f55fd3
 
e6aaa19
 
 
9f55fd3
 
e6aaa19
 
 
9f55fd3
e6aaa19
 
9f55fd3
 
17ba015
9f55fd3
e6aaa19
 
9f55fd3
e6aaa19
 
 
 
 
 
 
 
9f55fd3
 
17ba015
9f55fd3
 
 
 
e6aaa19
 
 
9f55fd3
68a43c1
 
 
 
e6aaa19
 
68a43c1
 
e6aaa19
 
 
9f55fd3
 
 
e6aaa19
9f55fd3
 
e6aaa19
9f55fd3
 
e6aaa19
6419184
e6aaa19
17ba015
 
9f55fd3
 
 
6abfe5d
9f55fd3
 
 
e6aaa19
 
9f55fd3
17ba015
9f55fd3
 
870083e
 
 
 
 
e6aaa19
870083e
 
68a43c1
870083e
 
 
 
 
 
e6aaa19
870083e
 
68a43c1
870083e
 
 
 
 
 
e6aaa19
870083e
 
68a43c1
870083e
 
 
 
d8667c2
 
 
a3dec8c
 
68a43c1
a3dec8c
e6aaa19
17ba015
870083e
 
e6aaa19
870083e
e6aaa19
870083e
e6aaa19
d8667c2
e6aaa19
e9d239b
 
e6aaa19
a3dec8c
e6aaa19
 
 
a3dec8c
e9d239b
e6aaa19
 
 
e9d239b
 
d8667c2
e9d239b
e6aaa19
 
 
e9d239b
a3dec8c
d8667c2
 
e6aaa19
a3dec8c
 
e6aaa19
 
 
 
 
870083e
e6aaa19
870083e
e6aaa19
 
 
 
870083e
 
 
e6aaa19
17ba015
b5e0d07
e6aaa19
 
870083e
 
 
 
17ba015
870083e
e6aaa19
 
 
d8667c2
e6aaa19
870083e
 
17ba015
870083e
e6aaa19
 
 
d8667c2
e6aaa19
870083e
e6aaa19
 
 
 
 
17ba015
 
 
 
 
 
 
 
 
e6aaa19
 
17ba015
e6aaa19
17ba015
e6aaa19
 
 
d8667c2
e6aaa19
d8667c2
 
6abfe5d
d8667c2
 
870083e
d8667c2
6abfe5d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
870083e
 
6abfe5d
870083e
6abfe5d
 
 
 
 
 
 
870083e
 
6abfe5d
 
 
 
 
 
 
 
d8667c2
 
 
6abfe5d
 
 
d8667c2
 
e9d239b
870083e
c5bc2b2
870083e
 
6abfe5d
870083e
 
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
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
# app.py
import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from streamlit_option_menu import option_menu
from pathlib import Path
import warnings
warnings.filterwarnings('ignore')

# ========== PAGE CONFIGURATION ==========
st.set_page_config(
    page_title="Car Rental Delay Analysis",
    #page_icon="🚗",
    layout="wide",
    initial_sidebar_state="expanded"
)

# ========== CUSTOM CSS ==========
st.markdown("""
<style>
    .main-header {
        font-size: 2.5rem;
        font-weight: 700;
        color: #1f77b4;
        text-align: center;
        margin-bottom: 2rem;
    }
    .section-header {
        font-size: 1.8rem;
        font-weight: 600;
        color: #2c3e50;
        margin: 2rem 0 1rem 0;
        border-bottom: 2px solid #3498db;
        padding-bottom: 0.5rem;
    }
    .metric-card {
        background-color: #f8f9fa;
        padding: 1.5rem;
        border-radius: 0.5rem;
        border-left: 4px solid #3498db;
        text-align: center;
    }
    .insight-box {
        background-color: #e8f4f8;
        padding: 1rem;
        border-radius: 0.5rem;
        border-left: 4px solid #17a2b8;
        margin: 1rem 0;
    }
    .recommendation-box {
        background-color: #d4edda;
        padding: 1.5rem;
        border-radius: 0.5rem;
        border-left: 4px solid #28a745;
        margin: 1rem 0;
    }
</style>
""", unsafe_allow_html=True)

# ========== DATA LOADING ==========
@st.cache_data(show_spinner=False)
def load_data():
    """Load and preprocess the rental data"""
    possible_paths = [
        "get_around_delay_analysis.xlsx",
        "get_around_delay_analysis.csv", 
        "/mnt/data/get_around_delay_analysis.xlsx",
        "/mnt/data/get_around_delay_analysis.csv"
    ]
    
    df = None
    for path in possible_paths:
        if Path(path).exists():
            try:
                if path.endswith('.xlsx'):
                    df = pd.read_excel(path)
                else:
                    df = pd.read_csv(path)
                break
            except Exception as e:
                continue
    
    if df is None:
        st.error("❌ Data file not found. Please ensure 'get_around_delay_analysis.xlsx' or 'get_around_delay_analysis.csv' is available.")
        st.stop()
    
    # Clean the data
    df = df.drop(columns=[c for c in df.columns if c.lower().startswith("unnamed")], errors="ignore")
    df["has_previous_rental"] = df["time_delta_with_previous_rental_in_minutes"].notnull()
    df["clean_delay"] = df["delay_at_checkout_in_minutes"].clip(-720, 720)
    
    return df

# ========== ANALYSIS FUNCTIONS ==========
def calculate_metrics(df, threshold_minutes, scope="all"):
    """Calculate key metrics for threshold analysis"""
    
    # Filter by scope
    if scope == "connect":
        df_filtered = df[df["checkin_type"].str.lower() == "connect"].copy()
    else:
        df_filtered = df.copy()
    
    df_with_prev = df_filtered[df_filtered["has_previous_rental"]].copy()
    
    if len(df_with_prev) == 0:
        return {
            "total_rentals": len(df_filtered),
            "rentals_with_previous": 0,
            "blocked_rentals": 0,
            "blocked_percentage": 0.0,
            "current_problems": 0,
            "problems_solved": 0,
            "solve_efficiency": 0.0,
            "revenue_impact": 0.0
        }
    
    # Join with previous rental data
    prev_rental_data = df[["rental_id", "delay_at_checkout_in_minutes"]].rename(
        columns={"rental_id": "previous_ended_rental_id", 
                "delay_at_checkout_in_minutes": "previous_delay"}
    )
    
    df_with_prev = df_with_prev.merge(prev_rental_data, on="previous_ended_rental_id", how="left")
    
    # Calculate key metrics
    df_with_prev["would_be_blocked"] = df_with_prev["time_delta_with_previous_rental_in_minutes"] < threshold_minutes
    df_with_prev["previous_delay_clean"] = df_with_prev["previous_delay"].clip(-720, 720)
    df_with_prev["causes_problem"] = (
        df_with_prev["previous_delay"].notnull() & 
        (df_with_prev["previous_delay_clean"] > df_with_prev["time_delta_with_previous_rental_in_minutes"])
    )
    df_with_prev["problem_solved"] = df_with_prev["causes_problem"] & df_with_prev["would_be_blocked"]
    
    # Final calculations
    total_rentals = len(df_filtered)
    rentals_with_previous = len(df_with_prev)
    blocked_rentals = int(df_with_prev["would_be_blocked"].sum())
    blocked_percentage = (blocked_rentals / rentals_with_previous) * 100 if rentals_with_previous > 0 else 0
    current_problems = int(df_with_prev["causes_problem"].sum())
    problems_solved = int(df_with_prev["problem_solved"].sum())
    solve_efficiency = (problems_solved / blocked_rentals * 100) if blocked_rentals > 0 else 0
    revenue_impact = (blocked_rentals / total_rentals) * 100 if total_rentals > 0 else 0
    
    return {
        "total_rentals": total_rentals,
        "rentals_with_previous": rentals_with_previous,
        "blocked_rentals": blocked_rentals,
        "blocked_percentage": blocked_percentage,
        "current_problems": current_problems,
        "problems_solved": problems_solved,
        "solve_efficiency": solve_efficiency,
        "availability_impact": revenue_impact  # More accurate naming
    }

def create_threshold_analysis(df, thresholds, scope="all"):
    """Create threshold analysis data"""
    results = []
    for threshold in thresholds:
        metrics = calculate_metrics(df, threshold, scope)
        results.append({"threshold": threshold, **metrics})
    return pd.DataFrame(results)

# ========== LOAD DATA ==========
df = load_data()

# ========== MAIN DASHBOARD ==========
st.markdown('<h1 class="main-header">Car Rental Delay Analysis</h1>', unsafe_allow_html=True)

# Sidebar with controls
with st.sidebar:
    # Logo placeholder - you can add your logo here
    # st.image("logo.png", width=200)  # Uncomment and add your logo file
    
    st.markdown("## Analysis Controls")
    
    selected = option_menu(
        "Analysis Focus",
        ["Overview & Problems", "Threshold & Scope"],
        icons=["graph-up", "sliders"],  # More professional icons
        menu_icon="house-gear",
        default_index=0,
    )
    
    if selected == "Threshold & Scope":
        st.markdown("### Settings")
        threshold = st.slider("Threshold (minutes)", 0, 300, 90, step=30,
                             help="Minimum delay between consecutive rentals")
        scope = st.selectbox("Implementation Scope", ["all", "connect"],
                            format_func=lambda x: "All Cars" if x == "all" else "Connect Cars Only")
    
    st.markdown("---")
    st.markdown("### Dataset Summary")
    st.info(f"""
    **Total Rentals:** {len(df):,}
    **Connect Rentals:** {len(df[df['checkin_type'].str.lower() == 'connect']):,}
    **Cancelled Rentals:** {len(df[df['state'] == 'canceled']):,}
    **With Previous Rental:** {df['has_previous_rental'].sum():,}
    """)

# ========== PAGE 1: OVERVIEW & PROBLEMS ==========
if selected == "Overview & Problems":
    st.title("Understanding the Delay Problem")
    
    # Dataset Overview
    st.markdown('<div class="section-header">Dataset Overview</div>', unsafe_allow_html=True)
    
    col1, col2, col3, col4 = st.columns(4)
    with col1:
        st.metric("Total Rentals", f"{len(df):,}",
                 help="Complete dataset of all rental transactions")
    with col2:
        st.metric("Connect Rentals", f"{len(df[df['checkin_type'].str.lower() == 'connect']):,}",
                 help="Rentals using Connect technology (keyless entry via smartphone)")
    with col3:
        st.metric("Mobile Rentals", f"{len(df[df['checkin_type'].str.lower() == 'mobile']):,}",
                 help="Traditional rentals using mobile app (owner hands over keys)")
    with col4:
        st.metric("With Previous Rental", f"{df['has_previous_rental'].sum():,}",
                 help="Rentals where the same car had another rental within 12 hours before - these can be analyzed for delay impact")
    
    # Rental type distribution
    col1, col2 = st.columns(2)
    
    with col1:
        checkin_counts = df["checkin_type"].value_counts()
        fig_checkin = px.pie(
            values=checkin_counts.values, 
            names=checkin_counts.index,
            title="Distribution by Checkin Type",
            color_discrete_sequence=px.colors.qualitative.Set3
        )
        st.plotly_chart(fig_checkin, use_container_width=True)
    
    with col2:
        state_counts = df["state"].value_counts()
        fig_state = px.pie(
            values=state_counts.values, 
            names=state_counts.index,
            title="Distribution by Rental State",
            color_discrete_sequence=px.colors.qualitative.Pastel
        )
        st.plotly_chart(fig_state, use_container_width=True)
    
    # Key Problem Analysis
    st.markdown('<div class="section-header">Current Problem Scope</div>', unsafe_allow_html=True)
    
    # Calculate current problems
    df_problems = df[df["has_previous_rental"]].copy()
    prev_rental_data = df[["rental_id", "delay_at_checkout_in_minutes"]].rename(
        columns={"rental_id": "previous_ended_rental_id", 
                "delay_at_checkout_in_minutes": "previous_delay"}
    )
    df_problems = df_problems.merge(prev_rental_data, on="previous_ended_rental_id", how="left")
    df_problems["previous_delay_clean"] = df_problems["previous_delay"].clip(-720, 720)
    df_problems["causes_problem"] = (
        df_problems["previous_delay"].notnull() & 
        (df_problems["previous_delay_clean"] > df_problems["time_delta_with_previous_rental_in_minutes"])
    )
    df_problems["wait_time"] = np.maximum(
        0, 
        df_problems["previous_delay_clean"] - df_problems["time_delta_with_previous_rental_in_minutes"]
    ).fillna(0)
    
    problem_cases = df_problems[df_problems["causes_problem"]]
    
    # Key metrics
    col1, col2, col3, col4 = st.columns(4)
    with col1:
        st.metric("Problem Cases", f"{len(problem_cases):,}",
                 help="Formula: previous_rental_delay > gap_to_current_rental AND previous_rental_delay > 0. Uses previous_ended_rental_id to link actual delay data.")
    with col2:
        problem_rate = (len(problem_cases) / len(df_problems)) * 100 if len(df_problems) > 0 else 0
        st.metric("Problem Rate", f"{problem_rate:.1f}%",
                 help="Calculation: problem_cases / rentals_with_previous_rental * 100")
    with col3:
        avg_wait = problem_cases["wait_time"].mean() if len(problem_cases) > 0 else 0
        st.metric("Avg Wait Time", f"{avg_wait:.1f} min",
                 help="Formula: max(0, previous_rental_delay - gap_to_current_rental). Average wait time when problems occur.")
    with col4:
        delay_cancels = problem_cases[problem_cases["state"] == "canceled"]
        st.metric("Resulting Cancellations", f"{len(delay_cancels):,}",
                 help="Cancelled rentals that were also problem cases (delay caused customer to cancel)")
    
    st.markdown("""
    <div class="insight-box">
    <strong>The Problem:</strong> Late returns create customer wait times and cancellations.
    </div>
    """, unsafe_allow_html=True)
    
    # Direct answer to PM's questions
    st.markdown('<div class="section-header">How Often Are Drivers Late & Impact on Next Driver</div>', unsafe_allow_html=True)
    
    # Calculate late return frequency and impact
    df_late_analysis = df[df["has_previous_rental"]].copy()
    
    # Join with previous rental delay data
    prev_rental_data = df[["rental_id", "delay_at_checkout_in_minutes"]].rename(
        columns={"rental_id": "previous_ended_rental_id", 
                "delay_at_checkout_in_minutes": "previous_delay"}
    )
    df_late_analysis = df_late_analysis.merge(prev_rental_data, on="previous_ended_rental_id", how="left")
    
    # Calculate late return frequency
    df_late_analysis["previous_delay_clean"] = df_late_analysis["previous_delay"].clip(-720, 720)
    df_late_analysis["previous_was_late"] = (
        df_late_analysis["previous_delay"].notnull() & 
        (df_late_analysis["previous_delay_clean"] > 0)
    )
    
    # Calculate impact on next driver
    df_late_analysis["causes_problem"] = (
        df_late_analysis["previous_delay"].notnull() & 
        (df_late_analysis["previous_delay_clean"] > df_late_analysis["time_delta_with_previous_rental_in_minutes"])
    )
    df_late_analysis["wait_time"] = np.maximum(
        0, 
        df_late_analysis["previous_delay_clean"] - df_late_analysis["time_delta_with_previous_rental_in_minutes"]
    ).fillna(0)
    
    late_returns = df_late_analysis[df_late_analysis["previous_was_late"]]
    impacted_next_drivers = df_late_analysis[df_late_analysis["causes_problem"]]
    
    col1, col2 = st.columns(2)
    
    with col1:
        st.markdown("#### Late Return Frequency")
        total_with_delay_data = df_late_analysis[df_late_analysis["previous_delay"].notnull()]
        late_frequency = (len(late_returns) / len(total_with_delay_data)) * 100 if len(total_with_delay_data) > 0 else 0
        
        st.metric("Late Returns", f"{len(late_returns):,}")
        st.metric("Late Return Rate", f"{late_frequency:.1f}%",
                 help="Percentage of returns that are late (delay > 0 minutes)")
        
        # Late return severity
        if len(late_returns) > 0:
            avg_late_delay = late_returns["previous_delay_clean"].mean()
            st.metric("Average Late Delay", f"{avg_late_delay:.1f} min")
    
    with col2:
        st.markdown("#### Impact on Next Driver")
        impact_rate = (len(impacted_next_drivers) / len(df_late_analysis)) * 100 if len(df_late_analysis) > 0 else 0
        
        st.metric("Next Drivers Impacted", f"{len(impacted_next_drivers):,}")
        st.metric("Impact Rate", f"{impact_rate:.1f}%",
                 help="Percentage of consecutive rentals where late return causes waiting")
        
        if len(impacted_next_drivers) > 0:
            avg_wait = impacted_next_drivers["wait_time"].mean()
            st.metric("Average Wait Time", f"{avg_wait:.1f} min",
                     help="Average additional wait time when impacted")
    
    # Visual analysis of the relationship
    col1, col2 = st.columns(2)
    
    with col1:
        # Late return distribution
        if len(late_returns) > 0:
            late_delays = late_returns["previous_delay_clean"]
            late_filtered = late_delays[late_delays <= 300]  # Cap at 5 hours for visualization
            
            fig_late = px.histogram(
                late_filtered, 
                nbins=20,
                title="Distribution of Late Return Delays",
                labels={"value": "Delay (minutes)", "count": "Number of Late Returns"}
            )
            st.plotly_chart(fig_late, use_container_width=True)
    
    with col2:
        # Wait time impact distribution
        if len(impacted_next_drivers) > 0:
            wait_times = impacted_next_drivers[impacted_next_drivers["wait_time"] > 0]["wait_time"]
            
            fig_wait = px.histogram(
                wait_times, 
                nbins=20,
                title="Wait Time Distribution for Impacted Next Drivers",
                labels={"value": "Wait Time (minutes)", "count": "Number of Impacted Drivers"}
            )
            st.plotly_chart(fig_wait, use_container_width=True)
    
    # Key insight summary
    late_to_impact_ratio = (len(impacted_next_drivers) / len(late_returns)) * 100 if len(late_returns) > 0 else 0
    
    st.markdown(f"""
    <div class="insight-box">
    <strong>Key Insights:</strong>
{late_frequency:.1f}% of returns are late
{impact_rate:.1f}% of consecutive rentals are impacted
    • Average wait time: {avg_wait:.1f} minutes when problems occur
    </div>
    """, unsafe_allow_html=True)
    
    # Visual analysis
    st.markdown('<div class="section-header">Delay Patterns</div>', unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    
    with col1:
        # Return status distribution
        df_with_delay_data = df[df["delay_at_checkout_in_minutes"].notnull()].copy()
        df_with_delay_data["delay_status"] = df_with_delay_data["delay_at_checkout_in_minutes"].apply(
            lambda x: "Early Return" if x < 0 else "On Time" if x == 0 else "Late Return"
        )
        
        delay_counts = df_with_delay_data["delay_status"].value_counts()
        fig_status = px.pie(
            values=delay_counts.values, 
            names=delay_counts.index,
            title="Return Status Distribution",
            color_discrete_sequence=px.colors.qualitative.Set3
        )
        st.plotly_chart(fig_status, use_container_width=True)
    
    with col2:
        # Delay distribution
        delay_filtered = df_with_delay_data[df_with_delay_data["delay_at_checkout_in_minutes"].between(-60, 240)]
        fig_hist = px.histogram(
            delay_filtered, 
            x="delay_at_checkout_in_minutes",
            nbins=30,
            title="Delay Distribution",
            labels={"delay_at_checkout_in_minutes": "Delay (minutes)", "count": "Rentals"}
        )
        fig_hist.add_vline(x=0, line_dash="dash", line_color="red", annotation_text="On Time")
        st.plotly_chart(fig_hist, use_container_width=True)
    
    # Gap analysis
    st.markdown('<div class="section-header">Time Gaps Between Rentals</div>', unsafe_allow_html=True)
    
    gap_data = df[df["has_previous_rental"]]
    gap_filtered = gap_data[gap_data["time_delta_with_previous_rental_in_minutes"].between(0, 480)]
    
    fig_gap = px.histogram(
        gap_filtered, 
        x="time_delta_with_previous_rental_in_minutes",
        nbins=20,
        title="Gap Distribution Between Consecutive Rentals",
        labels={"time_delta_with_previous_rental_in_minutes": "Gap (minutes)", "count": "Rentals"}
    )
    st.plotly_chart(fig_gap, use_container_width=True)
    
    # Cancellation analysis
    st.markdown('<div class="section-header">Cancellation Impact</div>', unsafe_allow_html=True)
    
    col1, col2 = st.columns(2)
    
    with col1:
        total_cancels_all = (df["state"] == "canceled").sum()
        delay_related_cancels = (df_problems["state"] == "canceled") & df_problems["causes_problem"]
        delay_cancel_count = delay_related_cancels.sum()
        
        st.metric("Total Cancellations", f"{total_cancels_all:,}",
                 help="All cancelled rentals in the dataset (state = 'canceled')")
        st.metric("Due to Previous Delays", f"{delay_cancel_count:,}",
                 help="Cancelled rentals that were also problem cases (previous rental caused delay)")
        if total_cancels_all > 0:
            delay_cancel_rate = (delay_cancel_count / total_cancels_all * 100)
            st.metric("% Due to Delays", f"{delay_cancel_rate:.1f}%",
                     help="Calculation: delay_related_cancellations / total_cancellations * 100")
    
    with col2:
        # Cancellation by checkin type
        cancellation_by_type = df.groupby(['checkin_type', 'state']).size().unstack(fill_value=0)
        if 'canceled' in cancellation_by_type.columns:
            cancel_rates = (cancellation_by_type['canceled'] / cancellation_by_type.sum(axis=1) * 100).round(1)
            fig_cancel = px.bar(
                x=cancel_rates.index, 
                y=cancel_rates.values,
                title="Cancellation Rate by Type",
                labels={"x": "Checkin Type", "y": "Cancellation Rate (%)"}
            )
            st.plotly_chart(fig_cancel, use_container_width=True)

# ========== PAGE 2: THRESHOLD & SCOPE ANALYSIS ==========
elif selected == "Threshold & Scope":
    st.title("Threshold & Scope Decision")
    
    st.markdown("""
    <div class="insight-box">
    <strong>Availability Impact:</strong> Percentage of rental slots blocked due to insufficient gap between rentals.
    </div>
    """, unsafe_allow_html=True)
    
    # Current impact
    current_metrics = calculate_metrics(df, threshold, scope)
    
    st.markdown('<div class="section-header">Impact at Current Settings</div>', unsafe_allow_html=True)
    
    col1, col2, col3, col4 = st.columns(4)
    with col1:
        st.markdown(f"""
        <div class="metric-card">
        <h3 style="color: #e74c3c;">{current_metrics['blocked_rentals']:,}</h3>
        <p>Blocked Rentals</p>
        <small>Gap < {threshold} min</small>
        </div>
        """, unsafe_allow_html=True)
        st.caption("Formula: time_delta_with_previous_rental < threshold")
    
    with col2:
        st.markdown(f"""
        <div class="metric-card">
        <h3 style="color: #f39c12;">{current_metrics['blocked_percentage']:.1f}%</h3>
        <p>Blocked Rate</p>
        <small>Of consecutive rentals</small>
        </div>
        """, unsafe_allow_html=True)
        st.caption("Calculation: blocked_rentals / rentals_with_previous * 100")
    
    with col3:
        st.markdown(f"""
        <div class="metric-card">
        <h3 style="color: #27ae60;">{current_metrics['problems_solved']:,}</h3>
        <p>Problems Solved</p>
        <small>Waiting eliminated</small>
        </div>
        """, unsafe_allow_html=True)
        st.caption("Logic: current_problems AND would_be_blocked")
    
    with col4:
        st.markdown(f"""
        <div class="metric-card">
        <h3 style="color: #9b59b6;">{current_metrics['availability_impact']:.1f}%</h3>
        <p>Availability Impact</p>
        <small>% of rental slots blocked</small>
        </div>
        """, unsafe_allow_html=True)
        st.caption("Formula: blocked_rentals / total_rentals * 100")
    
    # Threshold analysis
    st.markdown('<div class="section-header">Threshold Analysis</div>', unsafe_allow_html=True)
    
    thresholds = list(range(0, 301, 30))
    threshold_data = create_threshold_analysis(df, thresholds, scope)
    
    # Create dual-axis chart
    fig = make_subplots(
        rows=1, cols=2,
        subplot_titles=("Problems Solved vs Blocked Rentals", "Efficiency vs Availability Impact"),
        specs=[[{"secondary_y": True}, {"secondary_y": True}]]
    )
    
    # Left chart: Problems vs Blocked
    fig.add_trace(
        go.Scatter(x=threshold_data["threshold"], y=threshold_data["problems_solved"],
                  mode="lines+markers", name="Problems Solved", line=dict(color="green")),
        row=1, col=1, secondary_y=False
    )
    fig.add_trace(
        go.Scatter(x=threshold_data["threshold"], y=threshold_data["blocked_rentals"],
                  mode="lines+markers", name="Blocked Rentals", line=dict(color="red")),
        row=1, col=1, secondary_y=True
    )
    
    # Right chart: Efficiency vs Availability Impact
    fig.add_trace(
        go.Scatter(x=threshold_data["threshold"], y=threshold_data["solve_efficiency"],
                  mode="lines+markers", name="Efficiency (%)", line=dict(color="blue")),
        row=1, col=2, secondary_y=False
    )
    fig.add_trace(
        go.Scatter(x=threshold_data["threshold"], y=threshold_data["availability_impact"],
                  mode="lines+markers", name="Availability Impact (%)", line=dict(color="orange")),
        row=1, col=2, secondary_y=True
    )
    
    # Add current threshold line
    fig.add_vline(x=threshold, line_dash="dash", line_color="red", 
                 annotation_text=f"Current: {threshold}min", row=1, col=1)
    fig.add_vline(x=threshold, line_dash="dash", line_color="red", 
                 annotation_text=f"Current: {threshold}min", row=1, col=2)
    
    fig.update_layout(height=400, showlegend=True)
    fig.update_xaxes(title_text="Threshold (minutes)")
    fig.update_yaxes(title_text="Count", secondary_y=False, row=1, col=1)
    fig.update_yaxes(title_text="Count", secondary_y=True, row=1, col=1)
    fig.update_yaxes(title_text="Percentage (%)", secondary_y=False, row=1, col=2)
    fig.update_yaxes(title_text="Percentage (%)", secondary_y=True, row=1, col=2)
    
    st.plotly_chart(fig, use_container_width=True)
    
    # Scope comparison
    st.markdown('<div class="section-header">Scope Comparison: All Cars vs Connect Only</div>', unsafe_allow_html=True)
    
    all_metrics = calculate_metrics(df, threshold, "all")
    connect_metrics = calculate_metrics(df, threshold, "connect")
    
    col1, col2 = st.columns(2)
    
    with col1:
        st.markdown("### All Cars")
        st.markdown(f"""
        **Problems Solved:** {all_metrics['problems_solved']:,}  
        **Blocked Rentals:** {all_metrics['blocked_rentals']:,} ({all_metrics['blocked_percentage']:.1f}%)  
        **Efficiency:** {all_metrics['solve_efficiency']:.1f}%  
        **Availability Impact:** {all_metrics['availability_impact']:.1f}%
        """)
    
    with col2:
        st.markdown("### Connect Cars Only")
        st.markdown(f"""
        **Problems Solved:** {connect_metrics['problems_solved']:,}  
        **Blocked Rentals:** {connect_metrics['blocked_rentals']:,} ({connect_metrics['blocked_percentage']:.1f}%)  
        **Efficiency:** {connect_metrics['solve_efficiency']:.1f}%  
        **Availability Impact:** {connect_metrics['availability_impact']:.1f}%
        """)
    
    # Scope comparison chart
    all_data = create_threshold_analysis(df, thresholds, "all")
    connect_data = create_threshold_analysis(df, thresholds, "connect")
    
    fig_scope = go.Figure()
    
    # Calculate percentage of problems solved for fair comparison
    all_data["problems_solved_percent"] = (all_data["problems_solved"] / all_data["current_problems"].iloc[0] * 100).fillna(0)
    connect_data["problems_solved_percent"] = (connect_data["problems_solved"] / connect_data["current_problems"].iloc[0] * 100).fillna(0)
    
    fig_scope.add_trace(go.Scatter(x=all_data["threshold"], y=all_data["problems_solved_percent"],
                                  mode="lines+markers", name="All Cars - % Problems Solved"))
    fig_scope.add_trace(go.Scatter(x=connect_data["threshold"], y=connect_data["problems_solved_percent"],
                                  mode="lines+markers", name="Connect Only - % Problems Solved"))
    fig_scope.add_vline(x=threshold, line_dash="dash", line_color="red", 
                       annotation_text=f"Current: {threshold}min")
    fig_scope.update_layout(title="Percentage of Problems Solved by Scope", 
                           xaxis_title="Threshold (minutes)", 
                           yaxis_title="% of Problems Solved")
    st.plotly_chart(fig_scope, use_container_width=True)
    
    # Recommendations
    st.markdown('<div class="section-header">Business Decision Framework</div>', unsafe_allow_html=True)
    
    st.markdown("""
    <div class="insight-box">
    <strong>Key Trade-off:</strong> Customer experience improvements vs. availability reduction
    </div>
    """, unsafe_allow_html=True)
    
    # Show current trade-offs
    col1, col2 = st.columns(2)
    with col1:
        st.markdown("**Benefits**")
        st.write(f"• Eliminates {current_metrics['problems_solved']:,} wait situations")
        st.write(f"• {current_metrics['solve_efficiency']:.1f}% efficiency rate")
        st.write(f"• Reduces customer complaints")
    
    with col2:
        st.markdown("**Costs**")
        st.write(f"• Blocks {current_metrics['blocked_rentals']:,} booking opportunities")
        st.write(f"• {current_metrics['availability_impact']:.1f}% availability reduction")
        st.write(f"• Operational implementation required")
    
    # Strategic recommendations with 120min suggestion
    st.markdown("### Recommended Strategy")
    
    # Get 120min metrics for recommendation
    metrics_120 = calculate_metrics(df, 120, scope)
    
    col1, col2 = st.columns(2)
    
    with col1:
        st.markdown(f"""
        <div class="recommendation-box">
        <h3>Threshold: 120 minutes</h3>
        <p>Balanced approach for customer experience</p>
        <small>Solves {metrics_120['problems_solved']:,} problems, blocks {metrics_120['availability_impact']:.1f}% availability</small>
        </div>
        """, unsafe_allow_html=True)
    
    with col2:
        # Scope recommendation logic
        all_120 = calculate_metrics(df, 120, "all")
        connect_120 = calculate_metrics(df, 120, "connect")
        
        if connect_120['solve_efficiency'] > all_120['solve_efficiency'] and connect_120['problems_solved'] >= all_120['problems_solved'] * 0.7:
            recommended_scope = "Connect Only"
        else:
            recommended_scope = "All Cars"
        
        st.markdown(f"""
        <div class="recommendation-box">
        <h3>Scope: {recommended_scope}</h3>
        <p>Optimal efficiency and coverage</p>
        <small>Based on efficiency and problem-solving balance</small>
        </div>
        """, unsafe_allow_html=True)

# ========== FOOTER ==========
st.markdown("---")
st.markdown("""
<div style='text-align: center; color: #666; padding: 1rem;'>
<p><strong>Car Rental Delay Analysis</strong> - Supporting threshold and scope decisions</p>
</div>
""", unsafe_allow_html=True)