File size: 27,192 Bytes
f4c3fca
79180e5
bad4173
 
3ea0b26
62b53a3
780ec95
 
07016ca
62b53a3
 
 
 
 
 
 
79180e5
62b53a3
 
 
07016ca
 
 
 
 
56455aa
07016ca
79180e5
91d2a21
56455aa
07016ca
 
56455aa
07016ca
 
56455aa
07016ca
 
56455aa
07016ca
 
56455aa
7b5f2bf
79180e5
7b5f2bf
 
 
 
 
 
 
 
07016ca
 
7b5f2bf
 
79180e5
7b5f2bf
ba50457
7b5f2bf
 
 
 
 
 
 
 
 
 
 
ba50457
07016ca
 
 
56455aa
7b5f2bf
56455aa
07016ca
 
56455aa
07016ca
91d2a21
56455aa
07016ca
7b5f2bf
07016ca
 
 
7b5f2bf
 
 
56455aa
7b5f2bf
 
56455aa
7b5f2bf
 
 
56455aa
7b5f2bf
 
56455aa
07016ca
 
56455aa
91d2a21
ba50457
07016ca
 
 
 
56455aa
07016ca
ba50457
91d2a21
56455aa
07016ca
 
56455aa
07016ca
 
56455aa
07016ca
62b53a3
07016ca
 
 
56455aa
07016ca
 
56455aa
ba50457
7b5f2bf
 
ba50457
 
 
7b5f2bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba50457
07016ca
 
 
56455aa
7b5f2bf
56455aa
07016ca
 
56455aa
07016ca
91d2a21
56455aa
7b5f2bf
 
56455aa
7b5f2bf
 
56455aa
07016ca
 
56455aa
91d2a21
ba50457
07016ca
7b5f2bf
ba50457
 
56455aa
07016ca
 
 
56455aa
ba50457
7b5f2bf
 
ba50457
 
 
7b5f2bf
ba50457
 
 
7b5f2bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94d6aac
7b5f2bf
 
 
 
 
 
 
 
 
ba50457
56455aa
7b5f2bf
ba50457
07016ca
7b5f2bf
ba50457
 
56455aa
ba50457
7b5f2bf
 
ba50457
 
 
7b5f2bf
ba50457
 
 
7b5f2bf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ba50457
56455aa
7b5f2bf
ba50457
62b53a3
 
 
 
56455aa
62b53a3
 
 
 
 
 
 
 
 
 
56455aa
62b53a3
 
 
 
 
 
 
 
 
56455aa
62b53a3
 
 
 
 
56455aa
62b53a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56455aa
62b53a3
 
07016ca
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56455aa
07016ca
 
91d2a21
c6beb28
365a345
 
 
 
 
56455aa
365a345
 
 
56455aa
365a345
 
 
 
 
 
 
 
 
 
 
56455aa
365a345
 
56455aa
365a345
 
 
 
 
 
 
 
 
 
 
56455aa
365a345
 
 
 
 
 
 
 
 
 
 
 
 
56455aa
365a345
 
 
 
 
 
 
 
ba50457
07016ca
 
56455aa
 
 
07016ca
 
 
 
 
 
 
 
 
 
 
 
 
 
56455aa
07016ca
 
ba50457
07016ca
ba50457
 
07016ca
ba50457
 
07016ca
 
 
ba50457
56455aa
ba50457
07016ca
ba50457
 
07016ca
ba50457
07016ca
ba50457
 
07016ca
 
 
ba50457
 
07016ca
 
 
 
ba50457
56455aa
91d2a21
07016ca
 
56455aa
07016ca
 
56455aa
07016ca
91d2a21
07016ca
91d2a21
 
 
56455aa
91d2a21
 
 
07016ca
 
 
91d2a21
 
 
56455aa
91d2a21
 
19b1ede
07016ca
 
91d2a21
 
56455aa
07016ca
ba50457
 
 
07016ca
 
 
 
 
ba50457
 
07016ca
56455aa
07016ca
56455aa
c6beb28
91d2a21
c6beb28
91d2a21
 
 
 
56455aa
ba50457
 
91d2a21
ba50457
 
 
56455aa
91d2a21
07016ca
91d2a21
07016ca
91d2a21
56455aa
ba50457
07016ca
ba50457
56455aa
07016ca
ba50457
91d2a21
ba50457
91d2a21
ba50457
 
07016ca
 
 
ba50457
 
07016ca
 
 
 
ba50457
56455aa
91d2a21
07016ca
 
56455aa
07016ca
 
56455aa
07016ca
91d2a21
07016ca
91d2a21
 
 
56455aa
91d2a21
 
 
07016ca
 
 
91d2a21
 
 
56455aa
91d2a21
 
19b1ede
07016ca
 
91d2a21
 
56455aa
07016ca
ba50457
 
 
07016ca
 
 
 
 
ba50457
 
07016ca
56455aa
07016ca
56455aa
c6beb28
91d2a21
c6beb28
91d2a21
 
 
 
56455aa
ba50457
 
91d2a21
ba50457
 
 
56455aa
91d2a21
07016ca
91d2a21
07016ca
91d2a21
56455aa
ba50457
07016ca
ba50457
56455aa
07016ca
ba50457
91d2a21
ba50457
91d2a21
ba50457
 
91d2a21
07016ca
846c1ec
56455aa
 
846c1ec
 
56455aa
c6beb28
 
 
 
 
56455aa
c6beb28
 
 
 
 
91d2a21
07016ca
f8230de
 
07016ca
 
 
 
 
 
 
 
 
 
 
 
 
f8230de
ba50457
b73721f
 
ba50457
ea7ce73
f4c3fca
7cea8a7
ba50457
b73721f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f4c3fca
 
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
import os
import gradio as gr
import json
import plotly.express as px
import pandas as pd
from typing import Tuple, Dict, Optional, List
import logging
logger = logging.getLogger(__name__)

# Import from our modules
from utils import (
    validate_apex_syntax, perform_skeptical_evaluation, extract_code_blocks,
    format_structured_explanation, format_object_conversion_explanation,
    extract_validation_metrics, normalize_metrics, generate_test_cases,
    VALIDATION_SCHEMA, B2B_COMMERCE_PATTERNS, logger
)

from api_client import (
    all_models, together_models, anthropic_models, call_llm
)

def correct_apex_trigger(model: str, trigger_code: str, progress=None) -> Tuple[str, str, str]:
    """Correct Apex Trigger with skeptical evaluation."""
    if progress:
        progress(0.1, desc="Validating input...")

    # Input validation
    if not trigger_code.strip():
        return "Please provide Apex Trigger code to correct.", "", ""

    if len(trigger_code.strip()) < 50:
        return "Code too short to be a valid Apex trigger. Please provide complete code.", "", ""

    # Perform initial syntax check
    is_valid, syntax_issues = validate_apex_syntax(trigger_code)

    if progress:
        progress(0.3, desc="Analyzing code structure...")

    # Perform skeptical evaluation
    evaluation = perform_skeptical_evaluation(trigger_code, "trigger")

    # Build comprehensive prompt with structured output format
    prompt = f"""
Correct this Apex Trigger for B2B Lightning Experience migration. Be BRIEF and DIRECT.
ORIGINAL CODE:
```apex
{trigger_code}
```
DETECTED ISSUES:
- Syntax Errors: {len(syntax_issues)}
- Security Issues: {len(evaluation['security_concerns'])}
- Performance Issues: {len(evaluation['performance_issues'])}
- B2B Commerce Issues: {len(evaluation['b2b_commerce_issues'])}
PROVIDE EXACTLY THIS FORMAT:
## CORRECTED CODE
```apex
[Put the complete corrected trigger here with inline comments for changes]
```
## KEY CHANGES (bullet points only)
- [Change 1: Brief description]
- [Change 2: Brief description]
- [Maximum 7 bullet points]
## CRITICAL ISSUES FIXED
1. [Most important issue]: [One-line explanation]
2. [Second issue]: [One-line explanation]
3. [Third issue]: [One-line explanation]
## REMAINING WARNINGS
- [Any issues that need manual review]
BE CONCISE. NO VERBOSE EXPLANATIONS. FOCUS ON CODE QUALITY.
"""

    if progress:
        progress(0.5, desc="Calling AI model...")

    response = call_llm(model, prompt, temperature=0.2)  # Even lower temperature for consistency

    if progress:
        progress(0.8, desc="Processing response...")

    # Extract code and explanations
    code_output = extract_code_blocks(response)

    # Validate the corrected code
    validation_warnings = []
    if code_output:
        corrected_valid, corrected_issues = validate_apex_syntax(code_output)
        if not corrected_valid:
            error_count = len([i for i in corrected_issues if i["type"] == "error"])
            warning_count = len([i for i in corrected_issues if i["type"] == "warning"])
            validation_warnings.append(f"⚠️ Validation: {error_count} errors, {warning_count} warnings remain")

    # Extract structured explanation
    explanation = format_structured_explanation(response, code_output)

    # Add validation warnings if any
    if validation_warnings:
        explanation = "\n".join(validation_warnings) + "\n\n" + explanation

    # Add test case reference (brief)
    explanation += "\n\n**Test Template:** Available in Full Response section"

    if progress:
        progress(1.0, desc="Complete!")

    return response, code_output, explanation

def convert_cc_object(model: str, cc_object_code: str, progress=None) -> Tuple[str, str, str]:
    """Convert CloudCraze Object with skeptical evaluation."""
    if progress:
        progress(0.1, desc="Validating input...")

    # Input validation
    if not cc_object_code.strip():
        return "Please provide CloudCraze Object code to convert.", "", ""

    if len(cc_object_code.strip()) < 30:
        return "Code too short to be a valid CloudCraze object. Please provide complete code.", "", ""

    if progress:
        progress(0.3, desc="Analyzing CloudCraze structure...")

    # Check for CloudCraze patterns
    import re
    has_cc_pattern = bool(re.search(B2B_COMMERCE_PATTERNS["cloudcraze_reference"], cc_object_code))
    if not has_cc_pattern:
        logger.warning("No obvious CloudCraze patterns found in input")

    # Perform evaluation
    evaluation = perform_skeptical_evaluation(cc_object_code, "object")

    prompt = f"""
Convert this CloudCraze Object to B2B Lightning Experience. Be BRIEF and PRECISE.
CLOUDCRAZE OBJECT:
```
{cc_object_code}
```
PROVIDE EXACTLY THIS FORMAT:
## B2B LEX OBJECT MAPPING
- Source: [CloudCraze object name]
- Target: [B2B LEX object name]
- Migration Complexity: [Low/Medium/High]
## CONVERTED CODE
```apex
[Complete B2B LEX implementation with inline comments]
```
## FIELD MAPPINGS (table format)
| CC Field | B2B Field | Type | Notes |
|----------|-----------|------|-------|
| field1   | newField1 | Text | Required |
| field2   | newField2 | Number | Optional |
## MIGRATION STEPS
1. [Step 1 - one line]
2. [Step 2 - one line]
3. [Maximum 5 steps]
## DATA MIGRATION SCRIPT
```apex
[Brief data migration code if needed, otherwise state "Not Required"]
```
## WARNINGS
- [Any manual steps or considerations]
BE CONCISE. FOCUS ON ACTIONABLE INFORMATION.
"""

    if progress:
        progress(0.5, desc="Calling AI model...")

    response = call_llm(model, prompt, temperature=0.2)

    if progress:
        progress(0.8, desc="Processing response...")

    # Extract code and explanations
    code_output = extract_code_blocks(response)

    # Extract structured explanation
    explanation = format_object_conversion_explanation(response, code_output)

    # Add brief test reference
    explanation += "\n\n**Test Utilities:** See Full Response for test data creation utilities"

    if progress:
        progress(1.0, desc="Complete!")

    return response, code_output, explanation

def validate_apex_trigger(validation_model: str, original_code: str, corrected_code: str) -> str:
    """Enhanced validation with skeptical evaluation and structured output."""
    if not validation_model or not original_code.strip() or not corrected_code.strip():
        return "Please provide all required inputs for validation."

    # Perform syntax validation on both
    orig_valid, orig_issues = validate_apex_syntax(original_code)
    corr_valid, corr_issues = validate_apex_syntax(corrected_code)

    prompt = f"""
Validate this Apex trigger correction. Be CRITICAL but CONCISE.
ORIGINAL ({len(orig_issues)} issues detected):
```apex
{original_code}
```
CORRECTED ({len(corr_issues)} issues detected):
```apex
{corrected_code}
```
PROVIDE THIS EXACT JSON FORMAT:
```json
{{
    "quality_rating": [1-10],
    "accuracy": [0.0-1.0],
    "completeness": [0.0-1.0],
    "best_practices_alignment": [0.0-1.0],
    "syntax_validity": [0.0-1.0],
    "security_score": [0.0-1.0],
    "performance_score": [0.0-1.0],
    "errors": [
        "Error 1: [specific line/issue]",
        "Error 2: [specific line/issue]"
    ],
    "warnings": [
        "Warning 1: [potential issue]",
        "Warning 2: [potential issue]"
    ],
    "suggestions": [
        "Improvement 1: [actionable suggestion]",
        "Improvement 2: [actionable suggestion]"
    ]
}}
``` 
SCORING CRITERIA:
- quality_rating: Overall code quality (1=terrible, 10=excellent)
- accuracy: Correctness of fixes (0=wrong, 1=perfect)
- completeness: All issues addressed (0=none, 1=all)
- best_practices_alignment: Follows Salesforce standards (0=poor, 1=excellent)
- syntax_validity: No syntax errors (0=many errors, 1=error-free)
- security_score: Security best practices (0=vulnerable, 1=secure)
- performance_score: Efficiency and scalability (0=poor, 1=optimal)
BE HARSH. FIND PROBLEMS. Maximum 3 items per category.
"""

    return call_llm(validation_model, prompt, temperature=0.1)  # Very low temperature for consistent JSON

def validate_cc_object_conversion(validation_model: str, original_object: str, converted_object: str) -> str:
    """Enhanced validation for CloudCraze object conversion with structured output."""
    if not validation_model or not original_object.strip() or not converted_object.strip():
        return "Please provide all required inputs for validation."

    prompt = f"""
Validate this CloudCraze to B2B LEX conversion. Be CRITICAL and BRIEF.
ORIGINAL CLOUDCRAZE:
```
{original_object}
```
CONVERTED B2B LEX:
```
{converted_object}
```
PROVIDE THIS EXACT JSON FORMAT:
```json
{{
    "quality_rating": [1-10],
    "accuracy": [0.0-1.0],
    "completeness": [0.0-1.0],
    "best_practices_alignment": [0.0-1.0],
    "syntax_validity": [0.0-1.0],
    "security_score": [0.0-1.0],
    "performance_score": [0.0-1.0],
    "errors": [
        "Missing field: [field_name]",
        "Wrong mapping: [issue]"
    ],
    "warnings": [
        "Data type mismatch: [field]",
        "Custom logic not migrated: [what]"
    ],
    "suggestions": [
        "Add validation for: [field]",
        "Consider indexing: [field]"
    ]
}}
```
FOCUS ON:
1. Missing field mappings
2. Data type conversions
3. Relationship integrity
4. Custom field handling
5. Performance at scale
BE HARSH. Maximum 3 items per category. Focus on REAL issues.
"""

    return call_llm(validation_model, prompt, temperature=0.1)

def create_enhanced_radar_chart(metrics: Optional[Dict[str, float]]) -> Optional[object]:
    """Create an enhanced radar chart with more metrics."""
    if not metrics:
        return None

    # Create data for the radar chart
    categories = [
        "Quality",
        "Accuracy",
        "Completeness",
        "Best Practices",
        "Syntax Valid",
        "Security",
        "Performance"
    ]

    values = [
        metrics.get("quality_rating", 0) / 10,  # Normalize to 0-1 scale
        metrics.get("accuracy", 0),
        metrics.get("completeness", 0),
        metrics.get("best_practices_alignment", 0),
        metrics.get("syntax_validity", 0),
        metrics.get("security_score", 0),
        metrics.get("performance_score", 0)
    ]

    # Create a DataFrame for plotting
    df = pd.DataFrame({
        'Category': categories,
        'Value': values
    })

    # Create the radar chart
    fig = px.line_polar(
        df, r='Value', theta='Category', line_close=True,
        range_r=[0, 1], title="Comprehensive Validation Assessment"
    )
    fig.update_traces(fill='toself', fillcolor='rgba(0, 100, 255, 0.2)')
    fig.update_layout(
        polar=dict(
            radialaxis=dict(
                visible=True,
                range=[0, 1]
            )
        ),
        showlegend=False,
        height=400
    )

    return fig

def get_theme_styles(theme_choice: str) -> Tuple[str, str, str, str]:
    """Get theme styles for different UI elements."""
    themes = {
        "Dark": {
            "explanation": "background-color: #1e1e1e; color: #e0e0e0; padding: 15px; border-radius: 8px; font-family: 'Inter', sans-serif; line-height: 1.6;",
            "code": "background-color: #0d1117; color: #c9d1d9; font-family: 'Fira Code', 'Consolas', monospace; padding: 15px; border-radius: 8px; border: 1px solid #30363d; font-size: 14px; line-height: 1.5;",
            "validation": "background-color: #161b22; color: #c9d1d9; padding: 15px; border-radius: 8px; border: 1px solid #30363d;",
            "error": "background-color: #3d1418; color: #f85149; padding: 10px; border-radius: 5px; border: 1px solid #f85149;"
        },
        "Light": {
            "explanation": "background-color: #ffffff; color: #24292e; padding: 15px; border-radius: 8px; border: 1px solid #e1e4e8; font-family: 'Inter', sans-serif; line-height: 1.6;",
            "code": "background-color: #f6f8fa; color: #24292e; font-family: 'Fira Code', 'Consolas', monospace; padding: 15px; border-radius: 8px; border: 1px solid #e1e4e8; font-size: 14px; line-height: 1.5;",
            "validation": "background-color: #f6f8fa; color: #24292e; padding: 15px; border-radius: 8px; border: 1px solid #e1e4e8;",
            "error": "background-color: #ffe4e6; color: #d73a49; padding: 10px; border-radius: 5px; border: 1px solid #d73a49;"
        }
    }

    theme = themes.get(theme_choice, themes["Light"])
    return (theme["explanation"], theme["code"], theme["explanation"], theme["code"])

# Wrapper functions with proper error handling
def trigger_correction_wrapper(model, code):
    """Wrapper for trigger correction with proper error handling."""
    try:
        if not model or not code.strip():
            return "Please select a model and provide code.", "", "Please provide valid inputs."

        # Create dummy progress function since Gradio progress doesn't work in lambda
        def dummy_progress(value, desc=""):
            pass

        return correct_apex_trigger(model, code, progress=dummy_progress)
    except Exception as e:
        logger.error(f"Trigger correction error: {str(e)}")
        error_msg = f"Error processing request: {str(e)}"
        return error_msg, "", error_msg

def object_conversion_wrapper(model, code):
    """Wrapper for object conversion with proper error handling."""
    try:
        if not model or not code.strip():
            return "Please select a model and provide code.", "", "Please provide valid inputs."

        def dummy_progress(value, desc=""):
            pass

        return convert_cc_object(model, code, progress=dummy_progress)
    except Exception as e:
        logger.error(f"Object conversion error: {str(e)}")
        error_msg = f"Error processing request: {str(e)}"
        return error_msg, "", error_msg

def validate_and_chart_trigger(model, original, corrected):
    """Wrapper for trigger validation with error handling."""
    try:
        if not model or not original.strip() or not corrected.strip():
            return "Please provide all required inputs for validation.", None

        validation_text = validate_apex_trigger(model, original, corrected)
        metrics = extract_validation_metrics(validation_text)
        chart = create_enhanced_radar_chart(metrics) if metrics else None
        return validation_text, chart
    except Exception as e:
        logger.error(f"Trigger validation error: {str(e)}")
        return f"Validation error: {str(e)}", None

def validate_and_chart_object(model, original, converted):
    """Wrapper for object validation with error handling."""
    try:
        if not model or not original.strip() or not converted.strip():
            return "Please provide all required inputs for validation.", None

        validation_text = validate_cc_object_conversion(model, original, converted)
        metrics = extract_validation_metrics(validation_text)
        chart = create_enhanced_radar_chart(metrics) if metrics else None
        return validation_text, chart
    except Exception as e:
        logger.error(f"Object validation error: {str(e)}")
        return f"Validation error: {str(e)}", None

def main():
    """Main application entry point."""
    with gr.Blocks(
            title="Salesforce B2B Commerce Migration Assistant",
            theme=gr.themes.Soft(primary_hue="blue"),
            css="""
        .gradio-container {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
        }
        .gr-button-primary {
            background-color: #0969da !important;
        }
        .gr-button-primary:hover {
            background-color: #0860ca !important;
        }
        code {
            font-family: 'Fira Code', 'Consolas', 'Monaco', monospace;
        }
        """
    ) as app:

        gr.Markdown("# πŸš€ Salesforce B2B Commerce Migration Assistant")
        gr.Markdown("Advanced tool for migrating CloudCraze code to B2B Lightning Experience with skeptical AI validation.")

        # Model selection
        with gr.Row():
            with gr.Column():
                gr.Markdown("### πŸ€– Primary Model")
                primary_model_dropdown = gr.Dropdown(
                    choices=all_models,
                    value=anthropic_models[0],
                    label="Select Primary AI Model for Conversion",
                    info="This model performs the initial code conversion"
                )

            with gr.Column():
                gr.Markdown("### πŸ” Validation Model")
                validation_model_dropdown = gr.Dropdown(
                    choices=all_models,
                    value=anthropic_models[1],
                    label="Select Validation AI Model for Review",
                    info="This model skeptically reviews and validates the output"
                )

        with gr.Tab("⚑ Apex Trigger Correction"):
            gr.Markdown("### Apex Trigger Correction & Optimization")
            gr.Markdown("Paste your Apex Trigger code for analysis, correction, and optimization.")

            trigger_input = gr.Textbox(
                lines=15,
                placeholder="Paste your Apex Trigger code here...\n\nExample:\ntrigger AccountTrigger on Account (before insert, before update) {\n    // Your trigger logic\n}",
                label="Apex Trigger Code",
                elem_classes="code-input"
            )

            with gr.Row():
                trigger_button = gr.Button("πŸ”§ Correct & Optimize", variant="primary", size="lg")
                copy_code_button = gr.Button("πŸ“‹ Copy Code", variant="secondary")

            # Progress indicator
            trigger_progress = gr.Textbox(label="Progress", visible=False)

            with gr.Accordion("πŸ“„ Full Model Response", open=False):
                trigger_full_response = gr.Textbox(
                    lines=20,
                    label="Full Model Response",
                    interactive=False
                )

            with gr.Row():
                with gr.Column():
                    trigger_explanation = gr.Textbox(
                        lines=15,
                        label="πŸ“ Explanation & Analysis",
                        placeholder="Detailed explanation will appear here...",
                        interactive=False,
                        elem_id="trigger_explanation"
                    )

                with gr.Column():
                    trigger_code_output = gr.Code(
                        language="python",  # Using python highlighting as java is not supported
                        label="βœ… Corrected Code (Apex)",
                        value="// Corrected Apex code will appear here",
                        elem_id="trigger_code_output"
                    )

            gr.Markdown("### 🎯 Validation Results")
            with gr.Row():
                with gr.Column(scale=2):
                    trigger_validation_output = gr.Textbox(
                        lines=20,
                        label="πŸ” Skeptical Validation Assessment",
                        placeholder="Validation results will appear here...",
                        interactive=True,
                        elem_id="trigger_validation"
                    )
                with gr.Column(scale=1):
                    trigger_chart = gr.Plot(label="πŸ“Š Validation Metrics")

            validate_trigger_button = gr.Button("πŸ” Validate Correction", variant="secondary", size="lg")

            # Wire up functionality - INSIDE the main function where UI elements are defined
            trigger_button.click(
                fn=trigger_correction_wrapper,
                inputs=[primary_model_dropdown, trigger_input],
                outputs=[trigger_full_response, trigger_code_output, trigger_explanation],
                show_progress=True
            )

            validate_trigger_button.click(
                fn=validate_and_chart_trigger,
                inputs=[validation_model_dropdown, trigger_input, trigger_code_output],
                outputs=[trigger_validation_output, trigger_chart],
                show_progress=True
            )

            copy_code_button.click(
                fn=lambda: gr.Info("Code copied! Use Ctrl+C/Cmd+C if automatic copy fails."),
                inputs=[],
                outputs=[]
            )

            with gr.Row():
                trigger_clear = gr.Button("πŸ—‘οΈ Clear Input")
                trigger_clear.click(lambda: "", [], trigger_input)

                results_clear = gr.Button("🧹 Clear Results")
                results_clear.click(
                    lambda: ["", "", "", "", None],
                    [],
                    [trigger_full_response, trigger_code_output, trigger_explanation, trigger_validation_output, trigger_chart]
                )

        with gr.Tab("πŸ”„ CloudCraze Object Conversion"):
            gr.Markdown("### CloudCraze to B2B Lightning Experience Object Conversion")
            gr.Markdown("Convert CloudCraze custom objects to B2B Lightning Experience format.")

            object_input = gr.Textbox(
                lines=15,
                placeholder="Paste your CloudCraze Object definition here...\n\nExample:\nE_Product__c fields, relationships, and custom logic",
                label="CloudCraze Object Code",
                elem_classes="code-input"
            )

            with gr.Row():
                object_button = gr.Button("πŸ”„ Convert Object", variant="primary", size="lg")
                object_copy_code_button = gr.Button("πŸ“‹ Copy Code", variant="secondary")

            # Progress indicator
            object_progress = gr.Textbox(label="Progress", visible=False)

            with gr.Accordion("πŸ“„ Full Model Response", open=False):
                object_full_response = gr.Textbox(
                    lines=20,
                    label="Full Model Response",
                    interactive=False
                )

            with gr.Row():
                with gr.Column():
                    object_explanation = gr.Textbox(
                        lines=15,
                        label="πŸ“ Conversion Explanation",
                        placeholder="Detailed explanation will appear here...",
                        interactive=False,
                        elem_id="object_explanation"
                    )

                with gr.Column():
                    object_code_output = gr.Code(
                        language="python",  # Using python highlighting as java is not supported
                        label="βœ… Converted Code (B2B LEX)",
                        value="// Converted B2B Lightning Experience code will appear here",
                        elem_id="object_code_output"
                    )

            gr.Markdown("### 🎯 Validation Results")
            with gr.Row():
                with gr.Column(scale=2):
                    object_validation_output = gr.Textbox(
                        lines=20,
                        label="πŸ” Skeptical Validation Assessment",
                        placeholder="Validation results will appear here...",
                        interactive=True,
                        elem_id="object_validation"
                    )
                with gr.Column(scale=1):
                    object_chart = gr.Plot(label="πŸ“Š Validation Metrics")

            validate_object_button = gr.Button("πŸ” Validate Conversion", variant="secondary", size="lg")

            # Wire up functionality - INSIDE the main function where UI elements are defined
            object_button.click(
                fn=object_conversion_wrapper,
                inputs=[primary_model_dropdown, object_input],
                outputs=[object_full_response, object_code_output, object_explanation],
                show_progress=True
            )

            validate_object_button.click(
                fn=validate_and_chart_object,
                inputs=[validation_model_dropdown, object_input, object_code_output],
                outputs=[object_validation_output, object_chart],
                show_progress=True
            )

            object_copy_code_button.click(
                fn=lambda: gr.Info("Code copied! Use Ctrl+C/Cmd+C if automatic copy fails."),
                inputs=[],
                outputs=[]
            )

            with gr.Row():
                object_clear = gr.Button("πŸ—‘οΈ Clear Input")
                object_clear.click(lambda: "", [], object_input)

                object_results_clear = gr.Button("🧹 Clear Results")
                object_results_clear.click(
                    lambda: ["", "", "", "", None],
                    [],
                    [object_full_response, object_code_output, object_explanation, object_validation_output, object_chart]
                )

        # UI Preferences
        with gr.Accordion("βš™οΈ UI Preferences", open=False):
            theme_radio = gr.Radio(
                label="🎨 Theme",
                choices=["Light", "Dark"],
                value="Light"
            )

            # Comment out theme functionality for now to avoid conflicts
            # theme_radio.change(
            #     fn=get_theme_styles,
            #     inputs=[theme_radio],
            #     outputs=[
            #         trigger_explanation,
            #         trigger_code_output,
            #         object_explanation,
            #         object_code_output
            #     ]
            # )

        gr.Markdown("### πŸ“š About This Tool")
        gr.Markdown(
            """
            **πŸš€ Enhanced Features:**
            - **Skeptical AI Evaluation**: Models actively search for syntax errors, security issues, and performance problems
            - **Comprehensive Validation**: 7-metric assessment including syntax, security, and performance
            - **Edge Case Detection**: Identifies governor limits, bulkification issues, and B2B Commerce pitfalls
            - **Test Case Generation**: Automatic test class templates for migrated code
            - **Enhanced Error Detection**: Pattern-based syntax validation before AI processing
            
            **πŸ€– Model Roles:**
            - **Primary Model**: Performs initial conversion with skeptical analysis
            - **Validation Model**: Double-checks work with harsh but fair evaluation
            
            **⚠️ Important**: Always review and test AI-generated code in a sandbox before production deployment.
            """
        )

    app.launch()
    #return app




if __name__ == "__main__":
   main()


# print("βœ… Initializing Salesforce Migration Assistant")
# app = main()
# print("βœ… Application instance created")

# if __name__ == "__main__":
#     port = int(os.environ.get("PORT", 8080))
#     print(f"πŸš€ Starting server on port {port}")
#     try:
#         app.launch(
#             server_name="0.0.0.0",
#             server_port=port,
#             share=False
#         )
#     except Exception as e:
#         print(f"πŸ”₯ Server failed to start: {str(e)}")
#         raise
#     print("βœ… Server started successfully")