File size: 34,366 Bytes
b309c22
 
 
 
 
 
 
 
770544d
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac246b3
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac246b3
 
 
b309c22
ac246b3
 
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac246b3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b309c22
 
 
 
 
 
3789a0e
b309c22
3789a0e
 
 
 
 
 
 
 
 
b309c22
 
3789a0e
 
 
 
b309c22
3789a0e
 
 
 
 
 
b309c22
3789a0e
 
 
 
 
b309c22
3789a0e
 
 
 
 
 
 
 
 
b309c22
 
3789a0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b309c22
3789a0e
 
 
 
b309c22
3789a0e
 
 
 
 
 
 
ac246b3
3789a0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b309c22
 
3789a0e
 
 
b309c22
 
3789a0e
 
 
b309c22
770544d
3789a0e
b309c22
 
 
3789a0e
 
 
 
b309c22
3789a0e
 
b309c22
 
 
 
3789a0e
 
b309c22
3789a0e
 
b309c22
 
 
 
3789a0e
b309c22
3789a0e
 
 
 
b309c22
 
3789a0e
 
ac246b3
 
3789a0e
 
 
 
 
ac246b3
3789a0e
 
ac246b3
 
3789a0e
ac246b3
 
 
3789a0e
 
ac246b3
3789a0e
ac246b3
 
3789a0e
ac246b3
 
3789a0e
 
 
ac246b3
 
 
3789a0e
 
b309c22
 
 
 
 
3789a0e
 
b309c22
 
3789a0e
 
 
 
 
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770544d
 
b309c22
770544d
 
 
 
 
 
 
b309c22
 
 
 
770544d
b309c22
770544d
b309c22
770544d
b309c22
 
 
 
3789a0e
 
 
b309c22
3789a0e
 
b309c22
3789a0e
 
b309c22
 
3789a0e
 
 
 
 
 
b309c22
3789a0e
 
 
 
b309c22
 
3789a0e
b309c22
 
3789a0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b309c22
 
 
3789a0e
 
b309c22
 
 
3789a0e
 
b309c22
 
 
3789a0e
 
770544d
b309c22
 
 
3789a0e
b309c22
 
 
ac246b3
 
 
 
 
 
 
 
 
 
b309c22
 
 
 
 
 
 
 
 
770544d
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
770544d
 
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ac246b3
 
 
 
 
 
 
 
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
770544d
 
b309c22
 
 
 
3789a0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b309c22
 
 
 
 
 
 
ac246b3
b309c22
ac246b3
 
 
 
 
 
 
b309c22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
#!/usr/bin/env python3
"""
Smart Auto-Complete - Main Application
A context-aware text completion tool built with Gradio
"""

from typing import List, Tuple

import gradio as gr

from config.settings import AppSettings
from src.autocomplete import SmartAutoComplete
from src.utils import setup_logging

# Initialize logging
logger = setup_logging()

# Initialize settings and autocomplete engine
settings = AppSettings()
autocomplete = SmartAutoComplete(settings)


class AutoCompleteApp:
    def __init__(self):
        self.last_request_time = 0
        self.current_suggestions = []
        self.user_api_key = None
        self.custom_autocomplete = None

    def get_suggestions(
        self, text: str, context: str, output_tokens: int = 150, user_context: str = ""
    ) -> Tuple[List[str], str]:
        """
        Get auto-complete suggestions for the given text and context
        Returns: (suggestions_list, status_message)
        """
        try:
            # Input validation
            if not text or len(text.strip()) < 2:
                return [], "โœ๏ธ Please enter some text to get suggestions..."

            if len(text) > settings.MAX_INPUT_LENGTH:
                return (
                    [],
                    f"โš ๏ธ Text too long (max {settings.MAX_INPUT_LENGTH} characters)",
                )

            # Get suggestions from autocomplete engine
            suggestions = autocomplete.get_suggestions(
                text=text,
                context=context,
                max_tokens=output_tokens,
                user_context=user_context,
            )

            self.current_suggestions = suggestions

            if suggestions:
                status = f"โœ… Found {len(suggestions)} suggestions"
            else:
                status = "๐Ÿค” No suggestions available for this text"

            return suggestions, status

        except Exception as e:
            logger.error(f"Error getting suggestions: {str(e)}")
            return [], f"โŒ Error: {str(e)}"

    def get_suggestions_with_custom_prompts(
        self,
        text: str,
        context: str,
        output_tokens: int = 150,
        user_context: str = "",
        custom_prompts: dict = None,
    ) -> Tuple[List[str], str]:
        """
        Get auto-complete suggestions with custom prompts
        Returns: (suggestions_list, status_message)
        """
        try:
            # Input validation
            if not text or len(text.strip()) < 2:
                return [], "โœ๏ธ Please enter some text to get suggestions..."

            if len(text) > settings.MAX_INPUT_LENGTH:
                return (
                    [],
                    f"โš ๏ธ Text too long (max {settings.MAX_INPUT_LENGTH} characters)",
                )

            # Use the active autocomplete instance (user's custom or default)
            active_autocomplete = self.get_active_autocomplete()

            # Create a temporary autocomplete instance with custom prompts
            temp_autocomplete = SmartAutoComplete(
                active_autocomplete.settings if active_autocomplete else settings
            )
            if custom_prompts:
                temp_autocomplete.CONTEXT_PROMPTS = custom_prompts

            # Get suggestions from autocomplete engine
            suggestions = temp_autocomplete.get_suggestions(
                text=text,
                context=context,
                max_tokens=output_tokens,
                user_context=user_context,
            )

            self.current_suggestions = suggestions

            if suggestions:
                status = f"โœ… Found {len(suggestions)} suggestions"
            else:
                status = "๐Ÿค” No suggestions available for this text"

            return suggestions, status

        except Exception as e:
            logger.error(f"Error getting suggestions with custom prompts: {str(e)}")
            return [], f"โŒ Error: {str(e)}"

    def insert_suggestion(
        self, current_text: str, suggestion: str, cursor_position: int = None
    ) -> str:
        """Insert the selected suggestion into the current text"""
        try:
            # Simple append for now - in a real implementation, this would be more sophisticated
            if not current_text:
                return suggestion

            # If text ends with incomplete sentence, replace the last part
            words = current_text.split()
            if words and not current_text.endswith((".", "!", "?", "\n")):
                # Replace the last partial word/sentence with the suggestion
                return current_text + " " + suggestion.strip()
            else:
                return current_text + " " + suggestion.strip()

        except Exception as e:
            logger.error(f"Error inserting suggestion: {str(e)}")
            return current_text

    def update_api_key(self, api_key: str) -> str:
        """Update the OpenAI API key and reinitialize the autocomplete engine"""
        try:
            if not api_key or not api_key.strip():
                self.user_api_key = None
                self.custom_autocomplete = None
                return "๐Ÿ”„ Reverted to default configuration"

            # Validate the API key format
            if not api_key.startswith("sk-"):
                return "โŒ Invalid API key format. OpenAI keys start with 'sk-'"

            # Create a custom settings object with the user's API key
            from config.settings import AppSettings

            custom_settings = AppSettings()
            custom_settings.OPENAI_API_KEY = api_key.strip()

            # Create a new autocomplete instance with the custom settings
            self.custom_autocomplete = SmartAutoComplete(custom_settings)
            self.user_api_key = api_key.strip()

            return "โœ… API key updated successfully! Using your personal quota."

        except Exception as e:
            logger.error(f"Error updating API key: {str(e)}")
            return f"โŒ Error updating API key: {str(e)}"

    def test_api_connection(self, api_key: str = None) -> str:
        """Test the API connection with the current or provided key"""
        try:
            # Use custom autocomplete if user has provided a key, otherwise use default
            test_autocomplete = (
                self.custom_autocomplete if self.user_api_key else autocomplete
            )

            if api_key and api_key.strip():
                # Test with the provided key
                from config.settings import AppSettings

                test_settings = AppSettings()
                test_settings.OPENAI_API_KEY = api_key.strip()
                test_autocomplete = SmartAutoComplete(test_settings)

            # Test with a simple completion
            test_result = test_autocomplete.get_suggestions(
                text="Hello, this is a test", context="linkedin", max_tokens=10
            )

            if test_result and len(test_result) > 0:
                return "โœ… API connection successful!"
            else:
                return "โŒ API connection failed - no response received"

        except Exception as e:
            logger.error(f"API connection test failed: {str(e)}")
            return f"โŒ API connection test failed: {str(e)}"

    def get_active_autocomplete(self):
        """Get the currently active autocomplete instance"""
        return self.custom_autocomplete if self.user_api_key else autocomplete


def create_interface():
    """Create and configure the Gradio interface"""

    app_instance = AutoCompleteApp()

    # Professional CSS styling
    custom_css = """
    /* Global Styles */
    .gradio-container {
        font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif !important;
        background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%) !important;
        min-height: 100vh;
    }

    /* Header Styling */
    .header-container {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        padding: 2rem;
        border-radius: 16px;
        margin-bottom: 2rem;
        box-shadow: 0 8px 32px rgba(0,0,0,0.1);
    }

    .header-container h1 {
        font-size: 2.5rem;
        font-weight: 700;
        margin-bottom: 0.5rem;
        text-shadow: 0 2px 4px rgba(0,0,0,0.1);
    }

    .header-container p {
        font-size: 1.1rem;
        opacity: 0.9;
        margin-bottom: 0;
    }

    /* Card Styling */
    .main-card {
        background: white;
        border-radius: 16px;
        padding: 2rem;
        box-shadow: 0 4px 24px rgba(0,0,0,0.06);
        border: 1px solid rgba(255,255,255,0.2);
        backdrop-filter: blur(10px);
    }

    .output-card {
        background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
        border-radius: 16px;
        padding: 1.5rem;
        box-shadow: 0 4px 16px rgba(0,0,0,0.04);
        border: 1px solid #e2e8f0;
    }

    /* Input Styling */
    .gradio-textbox textarea, .gradio-textbox input {
        border: 2px solid #e2e8f0 !important;
        border-radius: 12px !important;
        padding: 16px !important;
        font-size: 16px !important;
        transition: all 0.3s ease !important;
        background: #fafbfc !important;
    }

    .gradio-textbox textarea:focus, .gradio-textbox input:focus {
        border-color: #667eea !important;
        box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
        background: white !important;
    }

    /* Button Styling */
    .gradio-button {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
        border: none !important;
        border-radius: 12px !important;
        padding: 16px 32px !important;
        font-weight: 600 !important;
        font-size: 16px !important;
        color: white !important;
        transition: all 0.3s ease !important;
        box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3) !important;
    }

    .gradio-button:hover {
        transform: translateY(-2px) !important;
        box-shadow: 0 8px 24px rgba(102, 126, 234, 0.4) !important;
    }

    .gradio-button.secondary {
        background: linear-gradient(135deg, #64748b 0%, #475569 100%) !important;
        box-shadow: 0 4px 16px rgba(100, 116, 139, 0.3) !important;
    }

    /* Radio Button Styling */
    .gradio-radio {
        background: white;
        border-radius: 12px;
        padding: 1rem;
        border: 2px solid #e2e8f0;
    }

    .gradio-radio label {
        font-weight: 500;
        color: #374151;
        padding: 12px 16px;
        border-radius: 8px;
        transition: all 0.2s ease;
    }

    .gradio-radio input:checked + label {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        color: white;
        box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
    }

    /* Accordion Styling */
    .gradio-accordion {
        border: 2px solid #e2e8f0 !important;
        border-radius: 12px !important;
        background: white !important;
        margin: 1rem 0 !important;
    }

    .gradio-accordion summary {
        background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%) !important;
        padding: 1rem 1.5rem !important;
        border-radius: 10px !important;
        font-weight: 600 !important;
        color: #374151 !important;
    }

    /* Status Display */
    .status-display {
        background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%);
        border: 2px solid #10b981;
        border-radius: 12px;
        padding: 1rem;
        color: #065f46;
        font-weight: 500;
    }

    /* Output Text Area */
    .output-text {
        background: linear-gradient(135deg, #fefce8 0%, #fef3c7 100%) !important;
        border: 2px solid #f59e0b !important;
        border-radius: 12px !important;
        font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace !important;
        font-size: 14px !important;
    }

    /* Slider Styling */
    .gradio-slider input[type="range"] {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
        border-radius: 8px !important;
    }

    /* Tab Styling */
    .gradio-tabs {
        border-radius: 12px !important;
        overflow: hidden !important;
    }

    .gradio-tab-nav {
        background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%) !important;
        border-bottom: 2px solid #e2e8f0 !important;
    }

    .gradio-tab-nav button {
        border-radius: 8px 8px 0 0 !important;
        font-weight: 500 !important;
        padding: 12px 24px !important;
    }

    .gradio-tab-nav button.selected {
        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
        color: white !important;
    }

    /* Examples Styling */
    .gradio-examples {
        background: white;
        border-radius: 12px;
        padding: 1.5rem;
        border: 2px solid #e2e8f0;
    }

    /* Footer Styling */
    .footer-content {
        background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%);
        color: #374151;
        padding: 2rem;
        border-radius: 16px;
        margin-top: 2rem;
        border: 2px solid #e2e8f0;
        box-shadow: 0 4px 16px rgba(0,0,0,0.04);
    }

    .footer-content h3 {
        color: #1f2937;
        border-bottom: 2px solid #667eea;
        padding-bottom: 0.5rem;
        margin-bottom: 1rem;
        font-weight: 600;
    }

    /* Responsive Design */
    @media (max-width: 768px) {
        .header-container h1 {
            font-size: 2rem;
        }

        .main-card, .output-card {
            padding: 1rem;
        }

        .gradio-button {
            padding: 12px 24px !important;
            font-size: 14px !important;
        }
    }
    """

    with gr.Blocks(
        title="LinkedIn Smart Auto-Complete | Professional AI Writing Assistant",
        theme=gr.themes.Soft(),
        css=custom_css,
    ) as interface:
        # Professional Header
        with gr.Row(elem_classes=["header-container"]):
            gr.HTML("""
            <div style="text-align: center;">
                <h1>๐Ÿš€ LinkedIn Smart Auto-Complete</h1>
                <p style="font-size: 1.2rem; margin-bottom: 0.5rem;">Professional AI Writing Assistant</p>
                <p style="opacity: 0.9;">Transform your ideas into compelling LinkedIn content with AI-powered intelligence</p>
                <div style="margin-top: 1rem; padding: 1rem; background: rgba(255,255,255,0.1); border-radius: 8px; border-left: 4px solid #fbbf24;">
                    <strong>๐Ÿ’ก Pro Tip:</strong> Add your OpenAI API key in Settings for unlimited personal usage
                </div>
            </div>
            """)

        with gr.Row():
            with gr.Column(scale=2, elem_classes=["main-card"]):
                # Professional Context Selection
                gr.Markdown("### ๐ŸŽฏ **Choose Your Writing Context**")
                context_selector = gr.Radio(
                    choices=[
                        ("๐Ÿ“ง Professional Email", "email"),
                        ("โœ๏ธ Creative Content", "creative"),
                        ("๐Ÿ’ผ LinkedIn Post", "linkedin"),
                    ],
                    value="linkedin",
                    label="",
                    elem_classes=["context-selector"],
                )

                gr.Markdown("---")

                # Enhanced Context Input
                gr.Markdown("### ๐Ÿ“‹ **Reference Information** *(Optional)*")
                context_input = gr.Textbox(
                    label="",
                    placeholder="๐Ÿ’ก Add background info, company details, industry context, or previous conversations to enhance AI understanding...",
                    lines=4,
                    elem_classes=["context-input"],
                )

                # Professional Main Input
                gr.Markdown("### โœ๏ธ **Your Content**")
                text_input = gr.Textbox(
                    label="",
                    placeholder="๐Ÿš€ Start typing your content here... The AI will intelligently complete your thoughts!",
                    lines=8,
                    elem_classes=["main-input"],
                )

                # Enhanced Submit Button
                submit_btn = gr.Button(
                    "โœจ Generate AI Completion",
                    variant="primary",
                    size="lg",
                    elem_classes=["primary-button"],
                )

                # Professional Settings
                with gr.Accordion("โš™๏ธ **Advanced Settings**", open=False):
                    # API Key Configuration
                    with gr.Group():
                        gr.Markdown("### ๐Ÿ”‘ **API Configuration**")
                        gr.Markdown(
                            "*Secure your own OpenAI quota for unlimited usage*"
                        )

                        openai_key_input = gr.Textbox(
                            label="OpenAI API Key",
                            placeholder="sk-proj-... (Paste your OpenAI API key here)",
                            type="password",
                            value="",
                            info="๐Ÿ”’ Your API key is encrypted and only used for this session. Never stored permanently.",
                        )

                        api_status = gr.Textbox(
                            label="Connection Status",
                            value="โœ… Using default configuration"
                            if settings.OPENAI_API_KEY
                            else "โš ๏ธ No API key configured - using shared quota",
                            interactive=False,
                            lines=1,
                            elem_classes=["status-display"],
                        )

                        test_api_btn = gr.Button(
                            "๐Ÿงช Test Connection", size="sm", elem_classes=["secondary"]
                        )

                    gr.Markdown("---")

                    # Enhanced Output Settings
                    gr.Markdown("### ๐Ÿ“ **Output Configuration**")
                    output_length = gr.Slider(
                        minimum=50,
                        maximum=500,
                        value=150,
                        step=10,
                        label="Response Length (tokens)",
                        info="Adjust the length of AI-generated content",
                    )

                    gr.Markdown("### ๐Ÿ”ง **Debug Options**")
                    gr.Checkbox(
                        label="Enable detailed logging",
                        value=False,
                        info="Show technical details for troubleshooting",
                    )

                # Context Prompt Editor
                with gr.Accordion("๐Ÿ”ง Edit Context Prompts", open=False):
                    gr.Markdown(
                        "**Customize your writing style for each context type. Changes apply immediately.**"
                    )

                    with gr.Tab("๐Ÿ“ง Email Context"):
                        email_system_prompt = gr.Textbox(
                            label="System Prompt",
                            value="""You are an expert email writing assistant. Generate professional,
            contextually appropriate email completions. Focus on:
            - Professional tone and structure
            - Clear, concise communication
            - Appropriate greetings and closings
            - Business communication best practices

            IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long.
            Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""",
                            lines=8,
                            placeholder="Enter the system prompt for email context...",
                        )
                        email_user_template = gr.Textbox(
                            label="User Message Template",
                            value="Complete this email text naturally and professionally with approximately {max_tokens} tokens: {text}",
                            lines=3,
                            placeholder="Enter the user message template...",
                        )

                    with gr.Tab("๐ŸŽจ Creative Context"):
                        creative_system_prompt = gr.Textbox(
                            label="System Prompt",
                            value="""You are a creative writing assistant. Generate engaging,
            imaginative story continuations. Focus on:
            - Narrative consistency and flow
            - Character development
            - Descriptive and engaging language
            - Plot advancement

            IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long.
            Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""",
                            lines=8,
                            placeholder="Enter the system prompt for creative context...",
                        )
                        creative_user_template = gr.Textbox(
                            label="User Message Template",
                            value="Continue this creative writing piece naturally with approximately {max_tokens} tokens: {text}",
                            lines=3,
                            placeholder="Enter the user message template...",
                        )

                    with gr.Tab("๐Ÿ’ผ LinkedIn Context"):
                        linkedin_system_prompt = gr.Textbox(
                            label="System Prompt",
                            value="""You are a LinkedIn writing assistant specialized in professional networking content. Generate engaging,
            professional LinkedIn-appropriate text completions. Focus on:
            - Professional networking tone
            - Industry-relevant language
            - Engaging and authentic voice
            - LinkedIn best practices (hashtags, mentions, professional insights)
            - Career development and business communication

            IMPORTANT: Generate a completion that is approximately {max_tokens} tokens long.
            Adjust your response length accordingly - shorter for fewer tokens, longer for more tokens.""",
                            lines=8,
                            placeholder="Enter the system prompt for LinkedIn context...",
                        )
                        linkedin_user_template = gr.Textbox(
                            label="User Message Template",
                            value="Complete this LinkedIn post/content naturally and professionally with approximately {max_tokens} tokens: {text}",
                            lines=3,
                            placeholder="Enter the user message template...",
                        )

            with gr.Column(scale=1, elem_classes=["output-card"]):
                # Professional Status Display
                gr.Markdown("### ๐Ÿ“Š **AI Assistant Status**")
                status_display = gr.Textbox(
                    label="",
                    value="๐Ÿค– Ready to assist! Choose your context and start writing...",
                    interactive=False,
                    lines=3,
                    elem_classes=["status-display"],
                )

                gr.Markdown("---")

                # Enhanced Output Area
                gr.Markdown("### ๐Ÿ“ **Generated Content**")
                gr.Markdown("*AI-powered completion will appear below*")

                copy_textbox = gr.Textbox(
                    label="",
                    placeholder="โœจ Your AI-generated content will appear here...\n\n๐Ÿ“‹ Simply select all text (Ctrl+A/Cmd+A) and copy (Ctrl+C/Cmd+C) to use in your LinkedIn post or email!",
                    lines=12,
                    max_lines=20,
                    interactive=True,
                    visible=False,
                    elem_classes=["output-text"],
                )

                # Quick Action Buttons (Future Enhancement)
                with gr.Row(visible=False):
                    gr.Button(
                        "๐Ÿ“‹ Copy to Clipboard", size="sm", elem_classes=["secondary"]
                    )
                    gr.Button("๐Ÿ”„ Regenerate", size="sm", elem_classes=["secondary"])
                    gr.Button("โœ๏ธ Edit & Refine", size="sm", elem_classes=["secondary"])

        # Professional Examples Section
        with gr.Accordion("๐ŸŽฏ **Try These Professional Examples**", open=False):
            gr.Markdown("""
            ### ๐Ÿš€ **Quick Start Templates**
            *Click any example below to instantly populate the form and see AI in action!*
            """)

            gr.Examples(
                examples=[
                    [
                        "Quarterly budget review meeting with stakeholders, discussing Q4 performance metrics and 2024 planning initiatives",
                        "Dear Mr. Johnson,\n\nI hope this email finds you well. Following our discussion yesterday, I wanted to confirm our meeting details for the quarterly budget review",
                        "email",
                    ],
                    [
                        "Epic fantasy adventure featuring a young mage discovering ancient powers in a world where magic and technology collide",
                        "In the neon-lit streets of Neo-Arcanum, where holographic spells danced alongside digital billboards, Zara clutched her grandmother's ancient grimoire and whispered",
                        "creative",
                    ],
                    [
                        "Sharing insights about AI transformation in the financial services industry, highlighting successful implementation strategies and future trends",
                        "๐Ÿš€ Excited to share key insights from our recent AI transformation journey at FinTech Solutions! After 18 months of implementation, here's what we've learned about",
                        "linkedin",
                    ],
                ],
                inputs=[context_input, text_input, context_selector],
                label="",
            )

        # Event handlers
        def update_api_key(api_key):
            """Handle API key updates"""
            status = app_instance.update_api_key(api_key)
            return status

        def test_api_connection(api_key):
            """Handle API connection testing"""
            status = app_instance.test_api_connection(api_key)
            return status

        def update_suggestions(
            text,
            context,
            output_tokens,
            user_context,
            email_sys,
            email_user,
            creative_sys,
            creative_user,
            linkedin_sys,
            linkedin_user,
        ):
            """Update suggestions based on input with custom prompts"""
            logger.info(
                f"Getting suggestions with context: '{user_context[:50] if user_context else 'None'}...'"
            )
            logger.info(f"Requested output tokens: {output_tokens}")

            # Create custom prompts dictionary
            custom_prompts = {
                "email": {
                    "system_prompt": email_sys,
                    "user_template": email_user,
                    "temperature": 0.6,
                },
                "creative": {
                    "system_prompt": creative_sys,
                    "user_template": creative_user,
                    "temperature": 0.8,
                },
                "linkedin": {
                    "system_prompt": linkedin_sys,
                    "user_template": linkedin_user,
                    "temperature": 0.7,
                },
            }

            suggestions, status = app_instance.get_suggestions_with_custom_prompts(
                text, context, output_tokens, user_context, custom_prompts
            )

            # Update the copy textbox with the suggestion
            if suggestions:
                copy_text = suggestions[0] if suggestions else ""
                copy_visible = True
            else:
                copy_text = ""
                copy_visible = False

            # Return the copy textbox update
            copy_update = gr.update(visible=copy_visible, value=copy_text)
            return status, copy_update

        # API Key event handlers
        openai_key_input.change(
            fn=update_api_key, inputs=[openai_key_input], outputs=[api_status]
        )

        test_api_btn.click(
            fn=test_api_connection, inputs=[openai_key_input], outputs=[api_status]
        )

        # Submit button handler
        submit_btn.click(
            fn=update_suggestions,
            inputs=[
                text_input,
                context_selector,
                output_length,
                context_input,
                email_system_prompt,
                email_user_template,
                creative_system_prompt,
                creative_user_template,
                linkedin_system_prompt,
                linkedin_user_template,
            ],
            outputs=[status_display, copy_textbox],
        )

        # Professional Footer
        with gr.Row(elem_classes=["footer-content"]):
            gr.HTML("""
            <div style="width: 100%;">
                <div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 2rem; margin-bottom: 2rem;">

                    <div>
                        <h3>๐ŸŽฎ Quick Start Guide</h3>
                        <ol style="line-height: 1.8; color: #4b5563;">
                            <li><strong>Choose Context:</strong> Select Email, Creative, or LinkedIn</li>
                            <li><strong>Add Context:</strong> Include background information (optional)</li>
                            <li><strong>Enter Text:</strong> Start typing your content</li>
                            <li><strong>Generate:</strong> Click the AI completion button</li>
                            <li><strong>Copy & Use:</strong> Select all and copy the result</li>
                        </ol>
                    </div>

                    <div>
                        <h3>๐ŸŒŸ Pro Features</h3>
                        <ul style="line-height: 1.8; color: #4b5563; list-style: none; padding: 0;">
                            <li>๐Ÿ”‘ <strong>Personal API Key:</strong> Unlimited usage with your OpenAI account</li>
                            <li>๐Ÿ“ <strong>Custom Length:</strong> Adjust output from 50-500 tokens</li>
                            <li>๐ŸŽฏ <strong>Context-Aware:</strong> AI adapts to your specific writing needs</li>
                            <li>โšก <strong>Real-time:</strong> Instant AI-powered completions</li>
                            <li>๐Ÿ”ง <strong>Customizable:</strong> Edit prompts for personalized results</li>
                        </ul>
                    </div>

                    <div>
                        <h3>๐Ÿ’ก Expert Tips</h3>
                        <ul style="line-height: 1.8; color: #4b5563; list-style: none; padding: 0;">
                            <li>๐Ÿ“ง <strong>Email:</strong> Start with greetings, add meeting context</li>
                            <li>โœ๏ธ <strong>Creative:</strong> Set the scene, describe characters</li>
                            <li>๐Ÿ’ผ <strong>LinkedIn:</strong> Include industry keywords, hashtags</li>
                            <li>๐ŸŽฏ <strong>Context:</strong> More background = better results</li>
                            <li>๐Ÿ”„ <strong>Iterate:</strong> Refine prompts for perfect output</li>
                        </ul>
                    </div>
                </div>

                <div style="border-top: 1px solid #cbd5e1; padding-top: 2rem; text-align: center;">
                    <div style="display: flex; justify-content: center; align-items: center; gap: 2rem; margin-bottom: 1rem;">
                        <div style="display: flex; align-items: center; gap: 0.5rem; color: #1f2937;">
                            <span style="font-size: 1.2rem;">๐Ÿš€</span>
                            <strong>Powered by OpenAI GPT</strong>
                        </div>
                        <div style="display: flex; align-items: center; gap: 0.5rem; color: #1f2937;">
                            <span style="font-size: 1.2rem;">โšก</span>
                            <strong>Built with Gradio</strong>
                        </div>
                        <div style="display: flex; align-items: center; gap: 0.5rem; color: #1f2937;">
                            <span style="font-size: 1.2rem;">๐Ÿ</span>
                            <strong>Python Backend</strong>
                        </div>
                    </div>
                    <p style="color: #6b7280; margin: 0; font-size: 0.9rem;">
                        Made with โค๏ธ for professionals, creators, and innovators worldwide
                    </p>
                </div>
            </div>
            """)

    return interface


def main():
    """Main function to run the application"""
    try:
        # Check API configuration - now optional since users can provide their own keys
        if not settings.validate_api_keys():
            logger.warning(
                "No default API keys found. Users can provide their own keys in the UI."
            )
            print("โš ๏ธ  No default API keys configured.")
            print("Users can enter their own OpenAI API key in the Settings section.")
        else:
            logger.info("Default API keys found and validated.")

        logger.info("Starting Smart Auto-Complete application...")

        # Create and launch interface
        interface = create_interface()

        interface.launch(
            server_name="0.0.0.0",
            server_port=7860,
            share=False,  # Set to True for public sharing
            show_error=True,
        )

    except Exception as e:
        logger.error(f"Failed to start application: {str(e)}")
        print(f"โŒ Error starting application: {str(e)}")


if __name__ == "__main__":
    main()