File size: 36,261 Bytes
4778771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
588dcba
 
 
 
4778771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68ff299
 
a77dd7c
 
68ff299
a77dd7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b11f294
 
a77dd7c
 
 
588dcba
a77dd7c
588dcba
a77dd7c
 
 
 
 
 
4778771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74f274b
4778771
74f274b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4778771
 
 
60c2ee7
 
 
74f274b
 
588dcba
74f274b
60c2ee7
 
 
 
 
 
 
588dcba
 
60c2ee7
588dcba
 
 
 
 
74f274b
588dcba
60c2ee7
 
 
 
 
588dcba
 
74f274b
588dcba
 
 
 
 
 
60c2ee7
 
 
 
819cf2c
 
 
 
 
60c2ee7
819cf2c
 
 
 
60c2ee7
819cf2c
 
 
60c2ee7
819cf2c
60c2ee7
 
 
 
 
819cf2c
 
60c2ee7
 
 
 
819cf2c
 
 
 
 
 
 
 
 
74f274b
 
4778771
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
"""
Main Streamlit Dashboard Application
MySpace Ooty Data Analytics - Enhanced Interactive Dashboard
"""

import streamlit as st
import pandas as pd
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta
import sys
from pathlib import Path
import warnings
warnings.filterwarnings('ignore')

# Add project root to path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))

LOGO_B64 = """
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
"""

from config.settings import *
from src.generate_powerpoint_report import PowerPointReportGenerator

# ═══════════════════════════════════════════════════════════════════════════
# PAGE CONFIGURATION & STYLING
# ═══════════════════════════════════════════════════════════════════════════

# Load logo for page icon
logo_file = project_root / "mypace-logo.png"

st.set_page_config(
    page_title="🏨 MySpace Ooty Analytics",
    page_icon=str(logo_file) if logo_file.exists() else "🏨",
    layout="wide",
    initial_sidebar_state="expanded",
)

# Custom CSS for enhanced UI and responsive design
st.markdown("""
    <style>
    /* Base styling */
    .main { padding: 0px; }
    .reportview-container { padding-top: 0px; }
    
    /* KPI Cards */
    .kpi-card {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        padding: 25px;
        border-radius: 12px;
        margin: 10px;
        box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        text-align: center;
    }
    
    .kpi-value {
        font-size: 32px;
        font-weight: bold;
        margin: 10px 0;
    }
    
    .kpi-label {
        font-size: 14px;
        opacity: 0.9;
        text-transform: uppercase;
        letter-spacing: 1px;
    }
    
    /* Section Headers */
    .section-header {
        border-left: 5px solid #667eea;
        padding: 15px;
        margin: 20px 0;
        background-color: #f5f5f5;
        border-radius: 5px;
    }
    
    /* Filter Box */
    .filter-box {
        background-color: #f0f2f6;
        padding: 15px;
        border-radius: 8px;
        margin: 10px 0;
    }
    
    /* Responsive Design for Mobile and Tablets */
    @media only screen and (max-width: 768px) {
        /* Mobile: Stack elements vertically */
        .kpi-card {
            margin: 5px 0;
            padding: 15px;
        }
        
        .kpi-value {
            font-size: 24px;
        }
        
        .kpi-label {
            font-size: 12px;
        }
        
        /* Adjust sidebar for mobile */
        [data-testid="stSidebar"] {
            width: 100% !important;
        }
        
        /* Make charts responsive */
        .js-plotly-plot {
            width: 100% !important;
            height: auto !important;
        }
        
        /* Adjust table font size for mobile */
        .dataframe {
            font-size: 12px !important;
        }
        
        /* Stack columns on mobile */
        .row-widget.stHorizontal {
            flex-direction: column !important;
        }
        
        /* Footer text size */
        .caption {
            font-size: 10px !important;
        }
    }
    
    /* Tablet Design */
    @media only screen and (min-width: 769px) and (max-width: 1024px) {
        .kpi-card {
            padding: 20px;
        }
        
        .kpi-value {
            font-size: 28px;
        }
        
        /* Adjust sidebar width for tablets */
        [data-testid="stSidebar"] {
            width: 280px !important;
        }
    }
    
    /* Desktop Large Screens */
    @media only screen and (min-width: 1025px) {
        [data-testid="stSidebar"] {
            width: 320px !important;
        }
    }
    
    /* Cross-browser compatibility */
    /* Firefox */
    @-moz-document url-prefix() {
        .kpi-card {
            -moz-border-radius: 12px;
        }
    }
    
    /* Safari and Chrome */
    @supports (-webkit-appearance: none) {
        .kpi-card {
            -webkit-border-radius: 12px;
        }
    }
    
    /* Improve touch targets for mobile */
    @media (hover: none) and (pointer: coarse) {
        button, [role="button"], select, input {
            min-height: 44px !important;
            min-width: 44px !important;
        }
    }
    
    /* Ensure images are responsive */
    img {
        max-width: 100%;
        height: auto;
    }
    
    /* Make plots responsive */
    .plot-container {
        width: 100% !important;
        height: auto !important;
    }
    
    /* Streamlit specific responsive fixes */
    .stPlotlyChart {
        width: 100% !important;
    }
    
    /* Improve readability on small screens */
    @media only screen and (max-width: 480px) {
        h1 { font-size: 24px !important; }
        h2 { font-size: 20px !important; }
        h3 { font-size: 18px !important; }
        p, li { font-size: 14px !important; }
    }
    </style>
    """, unsafe_allow_html=True)

# ═══════════════════════════════════════════════════════════════════════════
# DATA LOADING FUNCTION
# ═══════════════════════════════════════════════════════════════════════════

@st.cache_data(ttl=3600)
def load_data():
    """Load processed data from CSV"""
    try:
        file_path = Path(project_root) / "data" / "processed" / "data_cleaned_with_kpi.csv"
        if file_path.exists():
            df = pd.read_csv(file_path)
            # Convert date columns
            date_cols = ['Year', 'Month', 'Quarter', 'Week', 'Day']
            for col in date_cols:
                if col in df.columns:
                    if col == 'Month_Name':
                        df[col] = df[col].astype(str)
            return df
        else:
            return None
    except Exception as e:
        st.error(f"Error loading data: {e}")
        return None

@st.cache_data
def load_kpi_summary():
    """Load KPI summary"""
    try:
        file_path = Path(project_root) / "data" / "processed" / "kpi_summary.csv"
        if file_path.exists():
            return pd.read_csv(file_path)
        return None
    except:
        return None

# ═══════════════════════════════════════════════════════════════════════════
# SIDEBAR - FILTERS & NAVIGATION
# ═══════════════════════════════════════════════════════════════════════════

with st.sidebar:
    # Display logo
    try:
        from PIL import Image
        
        # Try to load logo from streamlit_app directory first (most direct path)
        logo_direct = Path(__file__).parent / "mypace-logo.png"
        
        if logo_direct.exists():
            # Load directly from streamlit_app folder
            logo_img = Image.open(logo_direct)
            st.image(logo_img, use_container_width=True)
        else:
            # Fallback: Try other paths
            logo_candidates = [
                Path(project_root) / "mypace-logo.png",
                Path.cwd() / "mypace-logo.png",
            ]
            
            logo_path = None
            for candidate in logo_candidates:
                if candidate.exists():
                    logo_path = candidate
                    break
            
            if logo_path:
                logo_img = Image.open(logo_path)
                st.image(logo_img, use_container_width=True)
            else:
                # Try HF URL
                hf_logo_url = "https://huggingface.co/spaces/abrahamcbe/myspace-ooty-analytics/resolve/main/mypace-logo.png"
                try:
                    st.image(hf_logo_url, use_container_width=True)
                except Exception:
                    # Use base64
                    try:
                        logo_b64 = "".join(LOGO_B64.split())
                        st.image(f"data:image/png;base64,{logo_b64}", use_container_width=True)
                    except Exception:
                        st.markdown("<h1 style='text-align: center; font-size: 80px;'>🏨</h1>", unsafe_allow_html=True)
    except Exception as e:
        st.markdown("<h1 style='text-align: center; font-size: 80px;'>🏨</h1>", unsafe_allow_html=True)
    
    st.title("🏨 MySpace Ooty Holiday Inn")
    st.markdown("πŸ“Š Data Analytics Dashboard")
    st.markdown("---")
    
    # Navigation
    page = st.radio(
        "πŸ“ Navigation",
        ["πŸ“Š Overview", "πŸ“ˆ KPIs & Metrics", "πŸ” Data Exploration", 
         "πŸ“‰ Trends & Analysis", "🎯 Custom Reports"]
    )
    
    st.markdown("---")
    
    # Load data
    df = load_data()
    
    if df is not None:
        st.success("βœ“ Data Loaded Successfully!")
        st.metric("Records", f"{len(df):,}")
        
        st.markdown("---")
        st.subheader("πŸ”§ Filters")
        
        # Date range filter
        if 'Year' in df.columns and 'Month' in df.columns:
            year_options = sorted([y for y in df['Year'].unique() if pd.notna(y)])
            selected_year = st.multiselect(
                "πŸ“… Select Year(s)",
                year_options,
                default=year_options if year_options else [],
                help="Filter by booking year"
            )
            
            month_options = sorted([m for m in df['Month'].unique() if pd.notna(m)])
            selected_month = st.multiselect(
                "πŸ“† Select Month(s)",
                month_options,
                default=month_options if month_options else [],
                help="Filter by booking month (1-12)"
            )
        else:
            selected_year = []
            selected_month = []
        
        # Filter by booking status
        if 'Booking_Status' in df.columns:
            status_options = [s for s in df['Booking_Status'].unique() if pd.notna(s)]
            selected_status = st.multiselect(
                "βœ… Select Booking Status",
                status_options,
                default=status_options if status_options else [],
                help="Filter by booking status"
            )
        else:
            selected_status = [None]
        
        # Apply filters
        df_filtered = df.copy()
        if 'Year' in df.columns and selected_year:
            df_filtered = df_filtered[df_filtered['Year'].isin(selected_year)]
        if 'Month' in df.columns and selected_month:
            df_filtered = df_filtered[df_filtered['Month'].isin(selected_month)]
        if 'Booking_Status' in df_filtered.columns and selected_status and len(selected_status) > 0:
            df_filtered = df_filtered[df_filtered['Booking_Status'].isin(selected_status)]
        
        st.metric("Filtered Records", f"{len(df_filtered):,}")
        
    else:
        st.warning("⚠ No data found. Please run the EDA notebook first.")
        df_filtered = None
    
    st.markdown("---")
    st.info("πŸ’‘ Tip: Use filters to customize your analysis")

# ═══════════════════════════════════════════════════════════════════════════
# MAIN CONTENT - PAGE ROUTING
# ═══════════════════════════════════════════════════════════════════════════

if df_filtered is None or len(df_filtered) == 0:
    st.error("🚨 No data available. Please ensure the data file exists at `data/processed/data_cleaned_with_kpi.csv`")
    st.stop()

# PAGE 1: OVERVIEW
if page == "πŸ“Š Overview":
    st.title("πŸ“Š Dashboard Overview")
    st.markdown("Get a quick summary of your business metrics")
    
    # Expandable filters section
    with st.expander("πŸ”§ Active Filters", expanded=True):
        col1, col2, col3 = st.columns(3)
        with col1:
            st.metric("Years Selected", len(selected_year))
        with col2:
            st.metric("Months Selected", len(selected_month))
        with col3:
            st.metric("Status Selected", len(selected_status))
        st.info(f"πŸ“Š Showing {len(df_filtered):,} records out of {len(df):,} total")
    
    # Load KPI summary
    kpi_summary = load_kpi_summary()
    
    if kpi_summary is not None:
        kpis_dict = dict(zip(kpi_summary['Metric'], kpi_summary['Value']))
    else:
        kpis_dict = {}
    
    # KPI Cards with Custom Styling
    st.markdown("### πŸ“ˆ Key Performance Indicators")
    
    # Calculate KPI values
    total_bookings = len(df_filtered)
    total_revenue = df_filtered[[col for col in df_filtered.columns if 'amount' in col.lower() or 'revenue' in col.lower()]].sum().sum()
    
    # Calculate average length of stay
    if 'No. Nights' in df_filtered.columns:
        avg_los = df_filtered['No. Nights'].fillna(0).astype(float).mean()
    elif 'Room_Nights' in df_filtered.columns:
        avg_los = df_filtered['Room_Nights'].fillna(0).astype(float).mean()
    else:
        nights_col = [col for col in df_filtered.columns if 'night' in col.lower()]
        avg_los = df_filtered[nights_col[0]].fillna(0).astype(float).mean() if nights_col else 0
    
    avg_revenue = total_revenue / total_bookings if total_bookings > 0 else 0
    
    # Display KPI cards using columns
    kpi_col1, kpi_col2, kpi_col3, kpi_col4 = st.columns([0.8, 1.1, 1.1, 1.1], gap="small")
    
    with kpi_col1:
        st.markdown(f"""
        <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 12px; text-align: center; color: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1);">
            <div style="font-size: 12px; font-weight: 600; letter-spacing: 1px; opacity: 0.9; margin-bottom: 10px;">TOTAL RECORDS</div>
            <div style="font-size: 32px; font-weight: bold;">{total_bookings:,}</div>
        </div>
        """, unsafe_allow_html=True)
    
    with kpi_col2:
        st.markdown(f"""
        <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 12px; text-align: center; color: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1);">
            <div style="font-size: 12px; font-weight: 600; letter-spacing: 1px; opacity: 0.9; margin-bottom: 10px;">TOTAL REVENUE</div>
            <div style="font-size: 32px; font-weight: bold;">β‚Ή{total_revenue:,.0f}</div>
        </div>
        """, unsafe_allow_html=True)
    
    with kpi_col3:
        st.markdown(f"""
        <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 12px; text-align: center; color: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1);">
            <div style="font-size: 12px; font-weight: 600; letter-spacing: 1px; opacity: 0.9; margin-bottom: 10px;">AVG. LENGTH OF STAY</div>
            <div style="font-size: 32px; font-weight: bold;">{avg_los:.1f} <span style="font-size: 14px; font-weight: 500;">nights</span></div>
        </div>
        """, unsafe_allow_html=True)
    
    with kpi_col4:
        st.markdown(f"""
        <div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 12px; text-align: center; color: white; box-shadow: 0 4px 15px rgba(0,0,0,0.1);">
            <div style="font-size: 12px; font-weight: 600; letter-spacing: 1px; opacity: 0.9; margin-bottom: 10px;">REVENUE PER BOOKING</div>
            <div style="font-size: 32px; font-weight: bold;">β‚Ή{avg_revenue:,.0f}</div>
        </div>
        """, unsafe_allow_html=True)
    

    # Charts Row 1
    st.markdown("---")
    st.markdown("### πŸ“Š Analytics")
    
    col1, col2 = st.columns(2)
    
    with col1:
        st.subheader("Bookings by Month")
        month_series = None
        if 'Month' in df_filtered.columns:
            month_series = df_filtered['Month']
        else:
            date_col = next((c for c in df_filtered.columns if 'date' in c.lower()), None)
            if date_col:
                month_series = pd.to_datetime(df_filtered[date_col], errors='coerce').dt.month

        if month_series is not None:
            month_series = pd.to_numeric(month_series, errors='coerce').dropna().astype(int)
            if not month_series.empty:
                month_order = list(range(1, 13))
                monthly_data = month_series.value_counts().reindex(month_order, fill_value=0).reset_index()
                monthly_data.columns = ['MonthNum', 'Bookings']
                monthly_data['Month'] = pd.to_datetime(monthly_data['MonthNum'], format='%m').dt.strftime('%b')
                fig = px.bar(
                    monthly_data,
                    x='Month',
                    y='Bookings',
                    title="Monthly Booking Distribution",
                    color='Bookings',
                    color_continuous_scale='Blues'
                )
                fig.update_layout(height=400, showlegend=False)
                st.plotly_chart(fig, use_container_width=True)
            else:
                st.info("No month data available for the current filters.")
        else:
            st.info("Month data not found. Add a Month or Date column to plot this chart.")
    
    with col2:
        st.subheader("Revenue Distribution")
        
        # Prioritize certain columns for revenue
        priority_cols = ['Total Amount', 'Booking Amount', 'Received Amount']
        revenue_candidates = [
            col for col in df_filtered.columns
            if any(k in col.lower() for k in ['amount', 'revenue', 'total', 'rate', 'price', 'cost'])
        ]
        
        # Sort by priority
        revenue_candidates = sorted(
            revenue_candidates,
            key=lambda x: (priority_cols.index(x) if x in priority_cols else len(priority_cols))
        )
        
        best_col = None
        best_score = 0
        
        for col in revenue_candidates:
            cleaned = (
                df_filtered[col]
                .astype(str)
                .str.replace(r'[^0-9.-]', '', regex=True)
            )
            vals = pd.to_numeric(cleaned, errors='coerce')
            # Filter to positive values only (revenue should be > 0)
            positive_vals = vals[vals > 0]
            score = len(positive_vals)
            
            if score > best_score and positive_vals.sum() > 0:
                best_score = score
                best_col = col

        if best_col:
            cleaned = (
                df_filtered[best_col]
                .astype(str)
                .str.replace(r'[^0-9.-]', '', regex=True)
            )
            revenue_values = pd.to_numeric(cleaned, errors='coerce')
            # Filter to positive values only
            revenue_values = revenue_values[revenue_values > 0].dropna()
            
            if revenue_values.empty:
                st.info(f"No positive revenue values found in {best_col}")
            elif len(revenue_values) <= 5:
                st.info("Insufficient data for distribution chart")
            else:
                try:
                    # Create histogram using DataFrame format for better Streamlit compatibility
                    nbins = min(30, max(5, len(revenue_values) // 10))
                    df_hist = pd.DataFrame({'Revenue': revenue_values})
                    
                    fig = px.histogram(
                        df_hist,
                        x='Revenue',
                        nbins=nbins,
                        title=f"Revenue Distribution - {best_col}",
                        color_discrete_sequence=['#636EFA']
                    )
                    fig.update_layout(
                        height=400,
                        xaxis_title=best_col,
                        yaxis_title="Count",
                        hovermode='x unified',
                        showlegend=False
                    )
                    fig.update_traces(marker=dict(line=dict(width=0)))
                    st.plotly_chart(fig, use_container_width=True)
                except Exception as e:
                    st.error(f"Error creating histogram: {str(e)}")
                    # Fallback: show summary stats in columns
                    col_stats1, col_stats2, col_stats3 = st.columns(3)
                    with col_stats1:
                        st.metric("Average", f"β‚Ή{revenue_values.mean():,.0f}")
                    with col_stats2:
                        st.metric("Median", f"β‚Ή{revenue_values.median():,.0f}")
                    with col_stats3:
                        st.metric("Max", f"β‚Ή{revenue_values.max():,.0f}")
        else:
            st.info("Revenue column not found. Add a revenue/amount column to plot this chart.")
    
    # Charts Row 2
    col1, col2 = st.columns(2)
    
    with col1:
        st.subheader("Bookings by Day of Week")
        if 'Day_of_Week' in df_filtered.columns:
            dow_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
            dow_data = df_filtered['Day_of_Week'].value_counts().reindex(
                [d for d in dow_order if d in df_filtered['Day_of_Week'].values]
            ).reset_index(name='Bookings')
            dow_data.columns = ['Day', 'Bookings']
            fig = px.bar(dow_data, x='Day', y='Bookings',
                        title="Bookings by Day of Week",
                        color='Bookings', color_continuous_scale='Greens')
            fig.update_layout(height=400)
            st.plotly_chart(fig, use_container_width=True)
    
    with col2:
        st.subheader("Holiday vs Regular Season")
        if 'Is_Holiday_Season' in df_filtered.columns:
            season_data = df_filtered['Is_Holiday_Season'].map({1: 'Holiday Season', 0: 'Regular Season'}).value_counts()
            fig = px.pie(values=season_data.values, names=season_data.index,
                        title="Booking Distribution by Season",
                        color_discrete_sequence=['#FF6B6B', '#4ECDC4'])
            fig.update_layout(height=400)
            st.plotly_chart(fig, use_container_width=True)

# PAGE 2: KPIs & METRICS
elif page == "πŸ“ˆ KPIs & Metrics":
    st.title("πŸ“ˆ Key Performance Indicators")
    st.markdown("Detailed business metrics and performance indicators")
    
    kpi_summary = load_kpi_summary()
    
    if kpi_summary is not None:
        # Display KPI table
        st.subheader("Summary Metrics")
        st.dataframe(
            kpi_summary.head(15),
            use_container_width=True,
            height=400
        )
    
    # Calculate additional metrics
    st.markdown("---")
    st.subheader("Performance Analysis")
    
    col1, col2, col3 = st.columns(3)
    
    with col1:
        total_bookings = len(df_filtered)
        st.info(f"πŸ“Š Total Bookings\n\n**{total_bookings:,}** bookings")
    
    with col2:
        if 'Is_Weekend' in df_filtered.columns:
            weekend_bookings = (df_filtered['Is_Weekend'] == 1).sum()
            pct = (weekend_bookings / len(df_filtered) * 100) if len(df_filtered) > 0 else 0
            st.info(f"πŸŽ‰ Weekend Bookings\n\n**{pct:.1f}%** of total")
    
    with col3:
        if 'Is_Holiday_Season' in df_filtered.columns:
            holiday_bookings = (df_filtered['Is_Holiday_Season'] == 1).sum()
            pct = (holiday_bookings / len(df_filtered) * 100) if len(df_filtered) > 0 else 0
            st.info(f"πŸŽ„ Holiday Season\n\n**{pct:.1f}%** of bookings")

# PAGE 3: DATA EXPLORATION
elif page == "πŸ” Data Exploration":
    st.title("πŸ” Exploratory Data Analysis")
    
    # Data Overview
    st.subheader("Dataset Overview")
    
    col1, col2, col3, col4 = st.columns(4)
    with col1:
        st.metric("Rows", f"{len(df_filtered):,}")
    with col2:
        st.metric("Columns", df_filtered.shape[1])
    with col3:
        st.metric("Missing Values", f"{df_filtered.isnull().sum().sum():,}")
    with col4:
        st.metric("Duplicates", "0")
    
    # Display data
    st.subheader("Data Sample")
    st.dataframe(df_filtered.head(10), use_container_width=True)
    
    # Column statistics
    st.subheader("Column Statistics")
    numeric_cols = df_filtered.select_dtypes(include=[np.number]).columns.tolist()
    
    if numeric_cols:
        selected_cols = st.multiselect("Select columns to analyze", numeric_cols, default=numeric_cols[:5])
        st.dataframe(
            df_filtered[selected_cols].describe().round(2),
            use_container_width=True
        )

# PAGE 4: TRENDS & ANALYSIS
elif page == "πŸ“‰ Trends & Analysis":
    st.title("πŸ“‰ Trends & Statistical Analysis")
    
    # Monthly Trend
    st.subheader("Monthly Trends")
    if 'Month' in df_filtered.columns:
        monthly_bookings = df_filtered.groupby('Month').size()
        fig = px.line(x=monthly_bookings.index, y=monthly_bookings.values,
                     labels={'x': 'Month', 'y': 'Bookings'},
                     title="Booking Trend Over Months",
                     markers=True)
        fig.update_traces(line=dict(color='#FF6B6B', width=3), marker=dict(size=10))
        st.plotly_chart(fig, use_container_width=True)
    
    # Revenue Trends
    st.markdown("---")
    st.subheader("Revenue Trends")
    
    revenue_cols = [col for col in df_filtered.columns if any(kw in col.lower() for kw in ['amount', 'revenue', 'total'])]
    if revenue_cols and 'Month' in df_filtered.columns:
        revenue_col = revenue_cols[0]
        monthly_revenue = df_filtered.groupby('Month')[revenue_col].sum()
        fig = px.line(x=monthly_revenue.index, y=monthly_revenue.values,
                     labels={'x': 'Month', 'y': 'Revenue (β‚Ή)'},
                     title="Revenue Trend Over Months",
                     markers=True)
        fig.update_traces(line=dict(color='#00CC96', width=3), marker=dict(size=10))
        st.plotly_chart(fig, use_container_width=True)

# PAGE 5: CUSTOM REPORTS
elif page == "🎯 Custom Reports":
    st.title("🎯 Custom Reports & Export")
    st.markdown("Generate personalized reports with selected filters")
    
    # Report options
    st.subheader("Report Configuration")
    
    col1, col2 = st.columns(2)
    
    with col1:
        report_type = st.selectbox(
            "Report Type",
            ["Summary Report", "Detailed Analysis", "Executive Summary", "Seasonal Analysis"]
        )
    
    with col2:
        export_format = st.selectbox(
            "Export Format",
            ["CSV", "Excel", "PDF (Coming Soon)"]
        )
    
    # Report preview
    st.subheader("Report Preview")
    st.info(f"πŸ“„ {report_type} - {len(df_filtered):,} records")
    st.dataframe(df_filtered.head(20), use_container_width=True)
    
    # Export button
    col1, col2, col3 = st.columns(3)
    
    with col1:
        if st.button("πŸ“₯ Download CSV", key="csv"):
            csv = df_filtered.to_csv(index=False)
            st.download_button(
                label="CSV Report",
                data=csv,
                file_name=f"myspace_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
                mime="text/csv"
            )
    
    with col2:
        if st.button("πŸ“Š Download Excel", key="excel"):
            excel_buffer = pd.ExcelWriter('/tmp/report.xlsx', engine='openpyxl')
            df_filtered.to_excel(excel_buffer, index=False)
            excel_buffer.close()
            with open('/tmp/report.xlsx', 'rb') as f:
                st.download_button(
                    label="Excel Report",
                    data=f.read(),
                    file_name=f"myspace_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx",
                    mime="application/vnd.ms-excel"
                )
    
    with col3:
        if st.button("πŸ“Š Generate PowerPoint", key="ppt"):
            with st.spinner("πŸ”„ Generating PowerPoint presentation..."):
                try:
                    # Generate PowerPoint report
                    generator = PowerPointReportGenerator()
                    ppt_path = generator.generate_report()
                    
                    # Read the file and provide download
                    with open(ppt_path, 'rb') as f:
                        st.download_button(
                            label="πŸ“₯ Download PowerPoint",
                            data=f.read(),
                            file_name=f"MySpace_Ooty_Report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.pptx",
                            mime="application/vnd.openxmlformats-officedocument.presentationml.presentation"
                        )
                    st.success("βœ… PowerPoint report generated successfully!")
                except Exception as e:
                    st.error(f"❌ Error generating PowerPoint: {str(e)}")

# Footer
st.markdown("---")
st.markdown("")
with st.container():
    st.markdown("<h4 style='text-align: center; color: #193264;'>🏨 MySpace Holiday Inn - Ooty</h4>", unsafe_allow_html=True)
    
    col1, col2, col3 = st.columns([1, 2, 1])
    with col2:
        st.markdown("""
        <div style='text-align: center; font-size: 12px;'>
            <p><b>πŸ“ HEAD OFFICE</b><br/>Kotagiri – 643217</p>
            <p><b>πŸ“ž CONTACT US</b><br/>
            +91 82206 62206 | +91-6369052954 | +91-6369973006<br/>
            πŸ“§ myspaceholidayinn@gmail.com<br/>
            πŸ“± +916381911228</p>
            <p><b>πŸ• TIMINGS</b><br/>
            Check-In: 12:00 PM | Check-Out: 10:00 AM</p>
        </div>
        """, unsafe_allow_html=True)
    
    st.caption(f"πŸ“Š Data Analytics Dashboard | Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")