CoolFace
Apppublic

Alpha108/GenerativeEngineOptimization

sourceHugging Facemitupdated 1y agoView on Hugging Face
0likes
export.py1896 linesDownload Raw Back to utils
1"""
2Results Export and Reporting Module
3Handles export of analysis results, reports, and data for external use
4"""
5
6import json
7import csv
8import io
9import zipfile
10import tempfile
11import os
12from datetime import datetime
13from typing import Dict, Any, List, Optional, Union
14import pandas as pd
15from dataclasses import dataclass, asdict
16
17
18@dataclass
19class GEOReport:
20    """Data class for GEO analysis reports"""
21    website_url: str
22    analysis_date: str
23    overall_score: float
24    pages_analyzed: int
25    geo_scores: Dict[str, float]
26    recommendations: List[str]
27    optimization_opportunities: List[Dict[str, Any]]
28    competitive_position: str
29    
30    def to_dict(self) -> Dict[str, Any]:
31        """Convert report to dictionary"""
32        return asdict(self)
33
34
35@dataclass
36class ContentAnalysis:
37    """Data class for content optimization analysis"""
38    original_content: str
39    analysis_date: str
40    clarity_score: float
41    structure_score: float
42    answerability_score: float
43    keywords: List[str]
44    optimized_content: Optional[str]
45    improvements_made: List[str]
46    
47    def to_dict(self) -> Dict[str, Any]:
48        """Convert analysis to dictionary"""
49        return asdict(self)
50
51
52class ResultExporter:
53    """Main class for exporting analysis results and generating reports"""
54    
55    def __init__(self):
56        self.export_formats = ['json', 'csv', 'html', 'pdf', 'xlsx']
57        self.supported_types = ['geo_analysis', 'content_optimization', 'qa_results', 'batch_analysis']
58    
59    def export_geo_results(self, geo_results: List[Dict[str, Any]], 
60                          website_url: str, format_type: str = 'json') -> Union[str, bytes, Dict[str, Any]]:
61        """
62        Export GEO analysis results in specified format
63        
64        Args:
65            geo_results (List[Dict]): List of GEO analysis results
66            website_url (str): URL of analyzed website
67            format_type (str): Export format ('json', 'csv', 'html', 'xlsx')
68            
69        Returns:
70            Union[str, bytes, Dict]: Exported data in requested format
71        """
72        try:
73            # Prepare consolidated data
74            export_data = self._prepare_geo_export_data(geo_results, website_url)
75            
76            if format_type.lower() == 'json':
77                return self._export_geo_json(export_data)
78            elif format_type.lower() == 'csv':
79                return self._export_geo_csv(export_data)
80            elif format_type.lower() == 'html':
81                return self._export_geo_html(export_data)
82            elif format_type.lower() == 'xlsx':
83                return self._export_geo_excel(export_data)
84            elif format_type.lower() == 'pdf':
85                return self._export_geo_pdf(export_data)
86            else:
87                raise ValueError(f"Unsupported export format: {format_type}")
88                
89        except Exception as e:
90            return {'error': f"Export failed: {str(e)}"}
91    
92    def export_enhancement_results(self, enhancement_result: Dict[str, Any], 
93                                  format_type: str = 'json') -> Union[str, bytes, Dict[str, Any]]:
94        """
95        Export content enhancement results
96        
97        Args:
98            enhancement_result (Dict): Content enhancement analysis result
99            format_type (str): Export format
100            
101        Returns:
102            Union[str, bytes, Dict]: Exported data
103        """
104        try:
105            # Prepare data for export
106            export_data = self._prepare_enhancement_export_data(enhancement_result)
107            
108            if format_type.lower() == 'json':
109                return json.dumps(export_data, indent=2, ensure_ascii=False)
110            elif format_type.lower() == 'html':
111                return self._export_enhancement_html(export_data)
112            elif format_type.lower() == 'csv':
113                return self._export_enhancement_csv(export_data)
114            else:
115                return json.dumps(export_data, indent=2, ensure_ascii=False)
116                
117        except Exception as e:
118            return {'error': f"Enhancement export failed: {str(e)}"}
119    
120    def export_qa_results(self, qa_results: List[Dict[str, Any]], 
121                         format_type: str = 'json') -> Union[str, bytes, Dict[str, Any]]:
122        """
123        Export Q&A session results
124        
125        Args:
126            qa_results (List[Dict]): List of Q&A interactions
127            format_type (str): Export format
128            
129        Returns:
130            Union[str, bytes, Dict]: Exported data
131        """
132        try:
133            export_data = {
134                'qa_session': {
135                    'session_date': datetime.now().isoformat(),
136                    'total_questions': len(qa_results),
137                    'interactions': qa_results
138                },
139                'summary': {
140                    'successful_answers': len([r for r in qa_results if not r.get('error')]),
141                    'average_response_length': self._calculate_avg_response_length(qa_results),
142                    'most_common_topics': self._extract_common_topics(qa_results)
143                }
144            }
145            
146            if format_type.lower() == 'json':
147                return json.dumps(export_data, indent=2, ensure_ascii=False)
148            elif format_type.lower() == 'html':
149                return self._export_qa_html(export_data)
150            elif format_type.lower() == 'csv':
151                return self._export_qa_csv(export_data)
152            else:
153                return json.dumps(export_data, indent=2, ensure_ascii=False)
154                
155        except Exception as e:
156            return {'error': f"Q&A export failed: {str(e)}"}
157    
158    def create_comprehensive_report(self, analysis_data: Dict[str, Any], 
159                                   report_type: str = 'full') -> Dict[str, Any]:
160        """
161        Create comprehensive analysis report
162        
163        Args:
164            analysis_data (Dict): Combined analysis data from multiple sources
165            report_type (str): Type of report ('full', 'summary', 'executive')
166            
167        Returns:
168            Dict: Comprehensive report data
169        """
170        try:
171            report = {
172                'report_metadata': {
173                    'generated_at': datetime.now().isoformat(),
174                    'report_type': report_type,
175                    'generator': 'GEO SEO AI Optimizer',
176                    'version': '1.0'
177                }
178            }
179            
180            if report_type == 'executive':
181                report.update(self._create_executive_summary(analysis_data))
182            elif report_type == 'summary':
183                report.update(self._create_summary_report(analysis_data))
184            else:  # full report
185                report.update(self._create_full_report(analysis_data))
186            
187            return report
188            
189        except Exception as e:
190            return {'error': f"Report creation failed: {str(e)}"}
191    
192    def export_batch_results(self, batch_results: List[Dict[str, Any]], 
193                           batch_metadata: Dict[str, Any],
194                           format_type: str = 'xlsx') -> Union[str, bytes, Dict[str, Any]]:
195        """
196        Export batch analysis results
197        
198        Args:
199            batch_results (List[Dict]): List of batch analysis results
200            batch_metadata (Dict): Metadata about the batch process
201            format_type (str): Export format
202            
203        Returns:
204            Union[str, bytes, Dict]: Exported batch data
205        """
206        try:
207            export_data = {
208                'batch_metadata': batch_metadata,
209                'batch_results': batch_results,
210                'batch_summary': self._create_batch_summary(batch_results),
211                'export_timestamp': datetime.now().isoformat()
212            }
213            
214            if format_type.lower() == 'xlsx':
215                return self._export_batch_excel(export_data)
216            elif format_type.lower() == 'json':
217                return json.dumps(export_data, indent=2, ensure_ascii=False)
218            elif format_type.lower() == 'csv':
219                return self._export_batch_csv(export_data)
220            else:
221                return json.dumps(export_data, indent=2, ensure_ascii=False)
222                
223        except Exception as e:
224            return {'error': f"Batch export failed: {str(e)}"}
225    
226    def create_export_package(self, analysis_data: Dict[str, Any], 
227                             package_name: str = "geo_analysis") -> bytes:
228        """
229        Create a ZIP package with multiple export formats
230        
231        Args:
232            analysis_data (Dict): Analysis data to package
233            package_name (str): Name for the package
234            
235        Returns:
236            bytes: ZIP file content
237        """
238        try:
239            # Create temporary directory
240            with tempfile.TemporaryDirectory() as temp_dir:
241                zip_path = os.path.join(temp_dir, f"{package_name}.zip")
242                
243                with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zip_file:
244                    # Add JSON export
245                    json_data = json.dumps(analysis_data, indent=2, ensure_ascii=False)
246                    zip_file.writestr(f"{package_name}.json", json_data)
247                    
248                    # Add HTML report
249                    if 'geo_results' in analysis_data:
250                        html_data = self._export_geo_html(analysis_data)
251                        zip_file.writestr(f"{package_name}_report.html", html_data)
252                    
253                    # Add CSV data
254                    if 'geo_results' in analysis_data:
255                        csv_data = self._export_geo_csv(analysis_data)
256                        zip_file.writestr(f"{package_name}_data.csv", csv_data)
257                    
258                    # Add README
259                    readme_content = self._generate_package_readme(analysis_data)
260                    zip_file.writestr("README.txt", readme_content)
261                
262                # Read the ZIP file
263                with open(zip_path, 'rb') as zip_file:
264                    return zip_file.read()
265                    
266        except Exception as e:
267            raise Exception(f"Package creation failed: {str(e)}")
268    
269    def _prepare_geo_export_data(self, geo_results: List[Dict[str, Any]], website_url: str) -> Dict[str, Any]:
270        """Prepare GEO data for export"""
271        try:
272            # Calculate aggregate metrics
273            valid_results = [r for r in geo_results if 'geo_scores' in r and not r.get('error')]
274            
275            if not valid_results:
276                return {
277                    'error': 'No valid GEO results to export',
278                    'website_url': website_url,
279                    'export_timestamp': datetime.now().isoformat()
280                }
281            
282            # Aggregate scores
283            all_scores = {}
284            for result in valid_results:
285                for metric, score in result.get('geo_scores', {}).items():
286                    if metric not in all_scores:
287                        all_scores[metric] = []
288                    all_scores[metric].append(score)
289            
290            avg_scores = {metric: sum(scores) / len(scores) for metric, scores in all_scores.items()}
291            overall_avg = sum(avg_scores.values()) / len(avg_scores) if avg_scores else 0
292            
293            # Collect recommendations
294            all_recommendations = []
295            all_opportunities = []
296            
297            for result in valid_results:
298                all_recommendations.extend(result.get('recommendations', []))
299                all_opportunities.extend(result.get('optimization_opportunities', []))
300            
301            # Remove duplicates
302            unique_recommendations = list(set(all_recommendations))
303            
304            return {
305                'website_analysis': {
306                    'url': website_url,
307                    'analysis_date': datetime.now().isoformat(),
308                    'pages_analyzed': len(valid_results),
309                    'overall_geo_score': round(overall_avg, 2)
310                },
311                'aggregate_scores': avg_scores,
312                'individual_page_results': valid_results,
313                'recommendations': unique_recommendations[:10],  # Top 10
314                'optimization_opportunities': all_opportunities,
315                'performance_insights': self._generate_performance_insights(avg_scores, overall_avg),
316                'export_metadata': {
317                    'exported_by': 'GEO SEO AI Optimizer',
318                    'export_timestamp': datetime.now().isoformat(),
319                    'data_format': 'GEO Analysis Results v1.0'
320                }
321            }
322            
323        except Exception as e:
324            return {'error': f"Data preparation failed: {str(e)}"}
325    
326    def _prepare_enhancement_export_data(self, enhancement_result: Dict[str, Any]) -> Dict[str, Any]:
327        """Prepare content enhancement data for export"""
328        try:
329            scores = enhancement_result.get('scores', {})
330            
331            return {
332                'content_analysis': {
333                    'analysis_date': datetime.now().isoformat(),
334                    'original_content_length': enhancement_result.get('original_length', 0),
335                    'original_word_count': enhancement_result.get('original_word_count', 0),
336                    'analysis_type': enhancement_result.get('optimization_type', 'standard')
337                },
338                'performance_scores': {
339                    'clarity': scores.get('clarity', 0),
340                    'structure': scores.get('structuredness', 0),
341                    'answerability': scores.get('answerability', 0),
342                    'overall_average': sum(scores.values()) / len(scores) if scores else 0
343                },
344                'optimization_results': {
345                    'keywords_identified': enhancement_result.get('keywords', []),
346                    'optimized_content': enhancement_result.get('optimized_text', ''),
347                    'improvements_made': enhancement_result.get('optimization_suggestions', []),
348                    'analyze_only': enhancement_result.get('analyze_only', False)
349                },
350                'export_metadata': {
351                    'exported_by': 'GEO SEO AI Optimizer',
352                    'export_timestamp': datetime.now().isoformat(),
353                    'data_format': 'Content Enhancement Results v1.0'
354                }
355            }
356            
357        except Exception as e:
358            return {'error': f"Enhancement data preparation failed: {str(e)}"}
359    
360    def _export_geo_json(self, data: Dict[str, Any]) -> str:
361        """Export GEO data as JSON"""
362        return json.dumps(data, indent=2, ensure_ascii=False)
363    
364    def _export_geo_csv(self, data: Dict[str, Any]) -> str:
365        """Export GEO data as CSV"""
366        try:
367            output = io.StringIO()
368            
369            # Write aggregate scores
370            writer = csv.writer(output)
371            writer.writerow(['GEO Analysis Results'])
372            writer.writerow(['Website:', data.get('website_analysis', {}).get('url', 'Unknown')])
373            writer.writerow(['Analysis Date:', data.get('website_analysis', {}).get('analysis_date', 'Unknown')])
374            writer.writerow(['Overall Score:', data.get('website_analysis', {}).get('overall_geo_score', 0)])
375            writer.writerow([])
376            
377            # Write aggregate scores
378            writer.writerow(['Metric', 'Score'])
379            for metric, score in data.get('aggregate_scores', {}).items():
380                writer.writerow([metric.replace('_', ' ').title(), round(score, 2)])
381            
382            writer.writerow([])
383            writer.writerow(['Recommendations'])
384            for i, rec in enumerate(data.get('recommendations', []), 1):
385                writer.writerow([f"{i}.", rec])
386            
387            # Individual page results
388            if data.get('individual_page_results'):
389                writer.writerow([])
390                writer.writerow(['Individual Page Results'])
391                
392                # Header for page results
393                first_result = data['individual_page_results'][0]
394                if 'geo_scores' in first_result:
395                    headers = ['Page Index', 'Page URL', 'Page Title'] + list(first_result['geo_scores'].keys())
396                    writer.writerow(headers)
397                    
398                    for i, result in enumerate(data['individual_page_results']):
399                        page_data = result.get('page_data', {})
400                        scores = result.get('geo_scores', {})
401                        
402                        row = [
403                            i + 1,
404                            page_data.get('url', 'Unknown'),
405                            page_data.get('title', 'Unknown')
406                        ] + [round(scores.get(metric, 0), 2) for metric in headers[3:]]
407                        
408                        writer.writerow(row)
409            
410            return output.getvalue()
411            
412        except Exception as e:
413            return f"CSV export error: {str(e)}"
414    
415    def _export_geo_html(self, data: Dict[str, Any]) -> str:
416        """Export GEO data as HTML report"""
417        try:
418            website_info = data.get('website_analysis', {})
419            scores = data.get('aggregate_scores', {})
420            recommendations = data.get('recommendations', [])
421            
422            html_content = f"""
423<!DOCTYPE html>
424<html lang="en">
425<head>
426    <meta charset="UTF-8">
427    <meta name="viewport" content="width=device-width, initial-scale=1.0">
428    <title>GEO Analysis Report - {website_info.get('url', 'Website')}</title>
429    <style>
430        body {{
431            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
432            line-height: 1.6;
433            color: #333;
434            max-width: 1200px;
435            margin: 0 auto;
436            padding: 20px;
437            background-color: #f5f5f5;
438        }}
439        .header {{
440            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
441            color: white;
442            padding: 30px;
443            border-radius: 10px;
444            margin-bottom: 30px;
445            text-align: center;
446        }}
447        .header h1 {{
448            margin: 0;
449            font-size: 2.5em;
450        }}
451        .summary-cards {{
452            display: grid;
453            grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
454            gap: 20px;
455            margin-bottom: 30px;
456        }}
457        .card {{
458            background: white;
459            padding: 20px;
460            border-radius: 10px;
461            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
462            text-align: center;
463        }}
464        .card h3 {{
465            margin-top: 0;
466            color: #667eea;
467        }}
468        .score {{
469            font-size: 2em;
470            font-weight: bold;
471            color: #333;
472        }}
473        .scores-grid {{
474            display: grid;
475            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
476            gap: 20px;
477            margin-bottom: 30px;
478        }}
479        .score-item {{
480            background: white;
481            padding: 15px;
482            border-radius: 8px;
483            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
484            display: flex;
485            justify-content: space-between;
486            align-items: center;
487        }}
488        .score-bar {{
489            width: 100px;
490            height: 10px;
491            background: #e0e0e0;
492            border-radius: 5px;
493            overflow: hidden;
494        }}
495        .score-fill {{
496            height: 100%;
497            background: linear-gradient(90deg, #ff6b6b, #ffa500, #4ecdc4);
498            transition: width 0.3s ease;
499        }}
500        .recommendations {{
501            background: white;
502            padding: 30px;
503            border-radius: 10px;
504            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
505            margin-bottom: 30px;
506        }}
507        .recommendations h2 {{
508            color: #667eea;
509            border-bottom: 2px solid #667eea;
510            padding-bottom: 10px;
511        }}
512        .rec-item {{
513            padding: 10px 0;
514            border-bottom: 1px solid #eee;
515        }}
516        .footer {{
517            text-align: center;
518            color: #666;
519            margin-top: 40px;
520            padding-top: 20px;
521            border-top: 1px solid #ddd;
522        }}
523    </style>
524</head>
525<body>
526    <div class="header">
527        <h1>🚀 GEO Analysis Report</h1>
528        <p>Generative Engine Optimization Performance Analysis</p>
529        <p><strong>Website:</strong> {website_info.get('url', 'Not specified')}</p>
530        <p><strong>Analysis Date:</strong> {website_info.get('analysis_date', 'Not specified')}</p>
531    </div>
532    
533    <div class="summary-cards">
534        <div class="card">
535            <h3>Overall GEO Score</h3>
536            <div class="score">{website_info.get('overall_geo_score', 0)}/10</div>
537        </div>
538        <div class="card">
539            <h3>Pages Analyzed</h3>
540            <div class="score">{website_info.get('pages_analyzed', 0)}</div>
541        </div>
542        <div class="card">
543            <h3>Recommendations</h3>
544            <div class="score">{len(recommendations)}</div>
545        </div>
546    </div>
547    
548    <h2>📊 Detailed GEO Metrics</h2>
549    <div class="scores-grid">
550    """
551            
552            # Add individual scores
553            for metric, score in scores.items():
554                metric_display = metric.replace('_', ' ').title()
555                score_percentage = min(score * 10, 100)  # Convert to percentage
556                
557                html_content += f"""
558        <div class="score-item">
559            <div>
560                <strong>{metric_display}</strong><br>
561                <span style="color: #666;">{score:.1f}/10</span>
562            </div>
563            <div class="score-bar">
564                <div class="score-fill" style="width: {score_percentage}%;"></div>
565            </div>
566        </div>
567                """
568            
569            html_content += """
570    </div>
571    
572    <div class="recommendations">
573        <h2>💡 Optimization Recommendations</h2>
574    """
575            
576            # Add recommendations
577            for i, rec in enumerate(recommendations, 1):
578                html_content += f'<div class="rec-item"><strong>{i}.</strong> {rec}</div>'
579            
580            html_content += f"""
581    </div>
582    
583    <div class="footer">
584        <p>Generated by GEO SEO AI Optimizer | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
585        <p>This report provides AI-first SEO optimization insights for better generative engine performance.</p>
586    </div>
587</body>
588</html>
589            """
590            
591            return html_content
592            
593        except Exception as e:
594            return f"<html><body><h1>HTML Export Error</h1><p>{str(e)}</p></body></html>"
595    
596    def _export_geo_excel(self, data: Dict[str, Any]) -> bytes:
597        """Export GEO data as Excel file"""
598        try:
599            output = io.BytesIO()
600            
601            with pd.ExcelWriter(output, engine='openpyxl') as writer:
602                # Summary sheet
603                summary_data = {
604                    'Metric': ['Website URL', 'Analysis Date', 'Pages Analyzed', 'Overall Score'],
605                    'Value': [
606                        data.get('website_analysis', {}).get('url', 'Unknown'),
607                        data.get('website_analysis', {}).get('analysis_date', 'Unknown'),
608                        data.get('website_analysis', {}).get('pages_analyzed', 0),
609                        data.get('website_analysis', {}).get('overall_geo_score', 0)
610                    ]
611                }
612                pd.DataFrame(summary_data).to_excel(writer, sheet_name='Summary', index=False)
613                
614                # Scores sheet
615                scores_data = []
616                for metric, score in data.get('aggregate_scores', {}).items():
617                    scores_data.append({
618                        'Metric': metric.replace('_', ' ').title(),
619                        'Score': round(score, 2),
620                        'Performance': self._get_performance_level(score)
621                    })
622                
623                pd.DataFrame(scores_data).to_excel(writer, sheet_name='GEO Scores', index=False)
624                
625                # Recommendations sheet
626                rec_data = []
627                for i, rec in enumerate(data.get('recommendations', []), 1):
628                    rec_data.append({
629                        'Priority': i,
630                        'Recommendation': rec,
631                        'Category': self._categorize_recommendation(rec)
632                    })
633                
634                if rec_data:
635                    pd.DataFrame(rec_data).to_excel(writer, sheet_name='Recommendations', index=False)
636                
637                # Individual pages sheet
638                if data.get('individual_page_results'):
639                    pages_data = []
640                    for i, result in enumerate(data['individual_page_results']):
641                        page_data = result.get('page_data', {})
642                        scores = result.get('geo_scores', {})
643                        
644                        page_row = {
645                            'Page_Index': i + 1,
646                            'URL': page_data.get('url', 'Unknown'),
647                            'Title': page_data.get('title', 'Unknown'),
648                            'Word_Count': page_data.get('word_count', 0)
649                        }
650                        
651                        # Add all GEO scores
652                        for metric, score in scores.items():
653                            page_row[metric.replace('_', ' ').title()] = round(score, 2)
654                        
655                        pages_data.append(page_row)
656                    
657                    pd.DataFrame(pages_data).to_excel(writer, sheet_name='Individual Pages', index=False)
658            
659            output.seek(0)
660            return output.getvalue()
661            
662        except Exception as e:
663            # Return error as text file if Excel creation fails
664            error_content = f"Excel export failed: {str(e)}\n\nData:\n{json.dumps(data, indent=2)}"
665            return error_content.encode('utf-8')
666    
667    def _export_enhancement_html(self, data: Dict[str, Any]) -> str:
668        """Export content enhancement results as HTML"""
669        try:
670            analysis = data.get('content_analysis', {})
671            scores = data.get('performance_scores', {})
672            optimization = data.get('optimization_results', {})
673            
674            html_content = f"""
675<!DOCTYPE html>
676<html lang="en">
677<head>
678    <meta charset="UTF-8">
679    <meta name="viewport" content="width=device-width, initial-scale=1.0">
680    <title>Content Enhancement Report</title>
681    <style>
682        body {{
683            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
684            line-height: 1.6;
685            color: #333;
686            max-width: 1000px;
687            margin: 0 auto;
688            padding: 20px;
689            background-color: #f8f9fa;
690        }}
691        .header {{
692            background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
693            color: white;
694            padding: 30px;
695            border-radius: 10px;
696            margin-bottom: 30px;
697            text-align: center;
698        }}
699        .scores {{
700            display: grid;
701            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
702            gap: 20px;
703            margin-bottom: 30px;
704        }}
705        .score-card {{
706            background: white;
707            padding: 20px;
708            border-radius: 10px;
709            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
710            text-align: center;
711        }}
712        .content-section {{
713            background: white;
714            padding: 30px;
715            border-radius: 10px;
716            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
717            margin-bottom: 20px;
718        }}
719        .keywords {{
720            display: flex;
721            flex-wrap: wrap;
722            gap: 10px;
723            margin-top: 15px;
724        }}
725        .keyword {{
726            background: #e9ecef;
727            padding: 5px 10px;
728            border-radius: 20px;
729            font-size: 0.9em;
730        }}
731        .optimized-content {{
732            background: #f8f9fa;
733            padding: 20px;
734            border-left: 4px solid #28a745;
735            border-radius: 5px;
736            font-style: italic;
737        }}
738    </style>
739</head>
740<body>
741    <div class="header">
742        <h1>🔧 Content Enhancement Report</h1>
743        <p>AI-Optimized Content Analysis Results</p>
744        <p><strong>Analysis Date:</strong> {analysis.get('analysis_date', 'Unknown')}</p>
745    </div>
746    
747    <div class="scores">
748        <div class="score-card">
749            <h3>Clarity Score</h3>
750            <div style="font-size: 2em; font-weight: bold; color: #28a745;">
751                {scores.get('clarity', 0):.1f}/10
752            </div>
753        </div>
754        <div class="score-card">
755            <h3>Structure Score</h3>
756            <div style="font-size: 2em; font-weight: bold; color: #28a745;">
757                {scores.get('structure', 0):.1f}/10
758            </div>
759        </div>
760        <div class="score-card">
761            <h3>Answerability Score</h3>
762            <div style="font-size: 2em; font-weight: bold; color: #28a745;">
763                {scores.get('answerability', 0):.1f}/10
764            </div>
765        </div>
766        <div class="score-card">
767            <h3>Overall Average</h3>
768            <div style="font-size: 2em; font-weight: bold; color: #28a745;">
769                {scores.get('overall_average', 0):.1f}/10
770            </div>
771        </div>
772    </div>
773    
774    <div class="content-section">
775        <h2>🔑 Identified Keywords</h2>
776        <div class="keywords">
777            {' '.join([f'<span class="keyword">{keyword}</span>' for keyword in optimization.get('keywords_identified', [])])}
778        </div>
779    </div>
780    
781    {'<div class="content-section"><h2>✨ Optimized Content</h2><div class="optimized-content">' + optimization.get('optimized_content', '') + '</div></div>' if optimization.get('optimized_content') and not optimization.get('analyze_only') else ''}
782    
783    <div class="content-section">
784        <h2>💡 Improvements Made</h2>
785        <ul>
786            {' '.join([f'<li>{improvement}</li>' for improvement in optimization.get('improvements_made', [])])}
787        </ul>
788    </div>
789    
790    <div style="text-align: center; color: #666; margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd;">
791        <p>Generated by GEO SEO AI Optimizer | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
792    </div>
793</body>
794</html>
795            """
796            
797            return html_content
798            
799        except Exception as e:
800            return f"<html><body><h1>Enhancement HTML Export Error</h1><p>{str(e)}</p></body></html>"
801    
802    def _export_enhancement_csv(self, data: Dict[str, Any]) -> str:
803        """Export content enhancement results as CSV"""
804        try:
805            output = io.StringIO()
806            writer = csv.writer(output)
807            
808            # Header information
809            analysis = data.get('content_analysis', {})
810            scores = data.get('performance_scores', {})
811            optimization = data.get('optimization_results', {})
812            
813            writer.writerow(['Content Enhancement Analysis Report'])
814            writer.writerow(['Analysis Date:', analysis.get('analysis_date', 'Unknown')])
815            writer.writerow(['Original Content Length:', analysis.get('original_content_length', 0)])
816            writer.writerow(['Original Word Count:', analysis.get('original_word_count', 0)])
817            writer.writerow([])
818            
819            # Performance scores
820            writer.writerow(['Performance Scores'])
821            writer.writerow(['Metric', 'Score'])
822            for metric, score in scores.items():
823                writer.writerow([metric.replace('_', ' ').title(), round(score, 2)])
824            
825            writer.writerow([])
826            writer.writerow(['Keywords Identified'])
827            for keyword in optimization.get('keywords_identified', []):
828                writer.writerow([keyword])
829            
830            writer.writerow([])
831            writer.writerow(['Improvements Made'])
832            for improvement in optimization.get('improvements_made', []):
833                writer.writerow([improvement])
834            
835            return output.getvalue()
836            
837        except Exception as e:
838            return f"Enhancement CSV export error: {str(e)}"
839    
840    def _export_qa_html(self, data: Dict[str, Any]) -> str:
841        """Export Q&A results as HTML"""
842        try:
843            session = data.get('qa_session', {})
844            summary = data.get('summary', {})
845            interactions = session.get('interactions', [])
846            
847            html_content = f"""
848<!DOCTYPE html>
849<html lang="en">
850<head>
851    <meta charset="UTF-8">
852    <meta name="viewport" content="width=device-width, initial-scale=1.0">
853    <title>Q&A Session Report</title>
854    <style>
855        body {{
856            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
857            line-height: 1.6;
858            color: #333;
859            max-width: 1000px;
860            margin: 0 auto;
861            padding: 20px;
862            background-color: #f8f9fa;
863        }}
864        .header {{
865            background: linear-gradient(135deg, #6f42c1 0%, #e83e8c 100%);
866            color: white;
867            padding: 30px;
868            border-radius: 10px;
869            margin-bottom: 30px;
870            text-align: center;
871        }}
872        .summary {{
873            display: grid;
874            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
875            gap: 20px;
876            margin-bottom: 30px;
877        }}
878        .summary-card {{
879            background: white;
880            padding: 20px;
881            border-radius: 10px;
882            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
883            text-align: center;
884        }}
885        .qa-item {{
886            background: white;
887            padding: 20px;
888            border-radius: 10px;
889            box-shadow: 0 4px 6px rgba(0,0,0,0.1);
890            margin-bottom: 20px;
891        }}
892        .question {{
893            background: #e9ecef;
894            padding: 15px;
895            border-left: 4px solid #6f42c1;
896            border-radius: 5px;
897            margin-bottom: 15px;
898        }}
899        .answer {{
900            padding: 15px;
901            border-left: 4px solid #28a745;
902            border-radius: 5px;
903            background: #f8f9fa;
904        }}
905        .sources {{
906            margin-top: 15px;
907            padding: 10px;
908            background: #fff3cd;
909            border-radius: 5px;
910            font-size: 0.9em;
911        }}
912    </style>
913</head>
914<body>
915    <div class="header">
916        <h1>💬 Q&A Session Report</h1>
917        <p>Document Question & Answer Analysis</p>
918        <p><strong>Session Date:</strong> {session.get('session_date', 'Unknown')}</p>
919    </div>
920    
921    <div class="summary">
922        <div class="summary-card">
923            <h3>Total Questions</h3>
924            <div style="font-size: 2em; font-weight: bold; color: #6f42c1;">
925                {session.get('total_questions', 0)}
926            </div>
927        </div>
928        <div class="summary-card">
929            <h3>Successful Answers</h3>
930            <div style="font-size: 2em; font-weight: bold; color: #28a745;">
931                {summary.get('successful_answers', 0)}
932            </div>
933        </div>
934        <div class="summary-card">
935            <h3>Avg Response Length</h3>
936            <div style="font-size: 2em; font-weight: bold; color: #17a2b8;">
937                {summary.get('average_response_length', 0):.0f}
938            </div>
939        </div>
940    </div>
941    
942    <h2>📝 Q&A Interactions</h2>
943    """
944            
945            # Add individual Q&A items
946            for i, interaction in enumerate(interactions, 1):
947                question = interaction.get('query', 'No question')
948                answer = interaction.get('result', interaction.get('answer', 'No answer'))
949                sources = interaction.get('sources', [])
950                
951                html_content += f"""
952    <div class="qa-item">
953        <h3>Question {i}</h3>
954        <div class="question">
955            <strong>Q:</strong> {question}
956        </div>
957        <div class="answer">
958            <strong>A:</strong> {answer}
959        </div>
960        """
961                
962                if sources:
963                    html_content += '<div class="sources"><strong>Sources:</strong><ul>'
964                    for source in sources[:3]:  # Limit to first 3 sources
965                        content_preview = source.get('content', '')[:200] + '...' if len(source.get('content', '')) > 200 else source.get('content', '')
966                        html_content += f'<li>{content_preview}</li>'
967                    html_content += '</ul></div>'
968                
969                html_content += '</div>'
970            
971            html_content += f"""
972    
973    <div style="text-align: center; color: #666; margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd;">
974        <p>Generated by GEO SEO AI Optimizer | {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
975    </div>
976</body>
977</html>
978            """
979            
980            return html_content
981            
982        except Exception as e:
983            return f"<html><body><h1>Q&A HTML Export Error</h1><p>{str(e)}</p></body></html>"
984    
985    def _export_qa_csv(self, data: Dict[str, Any]) -> str:
986        """Export Q&A results as CSV"""
987        try:
988            output = io.StringIO()
989            writer = csv.writer(output)
990            
991            session = data.get('qa_session', {})
992            summary = data.get('summary', {})
993            interactions = session.get('interactions', [])
994            
995            # Header
996            writer.writerow(['Q&A Session Report'])
997            writer.writerow(['Session Date:', session.get('session_date', 'Unknown')])
998            writer.writerow(['Total Questions:', session.get('total_questions', 0)])
999            writer.writerow(['Successful Answers:', summary.get('successful_answers', 0)])
1000            writer.writerow([])
1001            
1002            # Q&A data
1003            writer.writerow(['Question Index', 'Question', 'Answer', 'Has Sources', 'Answer Length'])
1004            
1005            for i, interaction in enumerate(interactions, 1):
1006                question = interaction.get('query', 'No question')
1007                answer = interaction.get('result', interaction.get('answer', 'No answer'))
1008                has_sources = 'Yes' if interaction.get('sources') else 'No'
1009                answer_length = len(answer) if answer else 0
1010                
1011                writer.writerow([i, question, answer, has_sources, answer_length])
1012            
1013            return output.getvalue()
1014            
1015        except Exception as e:
1016            return f"Q&A CSV export error: {str(e)}"
1017    
1018    def _export_batch_excel(self, data: Dict[str, Any]) -> bytes:
1019        """Export batch results as Excel file"""
1020        try:
1021            output = io.BytesIO()
1022            
1023            with pd.ExcelWriter(output, engine='openpyxl') as writer:
1024                # Batch metadata sheet
1025                metadata = data.get('batch_metadata', {})
1026                metadata_df = pd.DataFrame([
1027                    {'Property': k, 'Value': v} for k, v in metadata.items()
1028                ])
1029                metadata_df.to_excel(writer, sheet_name='Batch Metadata', index=False)
1030                
1031                # Batch summary sheet
1032                summary = data.get('batch_summary', {})
1033                summary_df = pd.DataFrame([
1034                    {'Metric': k, 'Value': v} for k, v in summary.items()
1035                ])
1036                summary_df.to_excel(writer, sheet_name='Batch Summary', index=False)
1037                
1038                # Individual results sheet
1039                results = data.get('batch_results', [])
1040                if results:
1041                    # Flatten results for tabular format
1042                    flattened_results = []
1043                    for i, result in enumerate(results):
1044                        flat_result = {'Batch_Index': i}
1045                        self._flatten_dict(result, flat_result)
1046                        flattened_results.append(flat_result)
1047                    
1048                    results_df = pd.DataFrame(flattened_results)
1049                    results_df.to_excel(writer, sheet_name='Batch Results', index=False)
1050            
1051            output.seek(0)
1052            return output.getvalue()
1053            
1054        except Exception as e:
1055            error_content = f"Batch Excel export failed: {str(e)}\n\nData:\n{json.dumps(data, indent=2)}"
1056            return error_content.encode('utf-8')
1057    
1058    def _export_batch_csv(self, data: Dict[str, Any]) -> str:
1059        """Export batch results as CSV"""
1060        try:
1061            output = io.StringIO()
1062            writer = csv.writer(output)
1063            
1064            # Batch metadata
1065            metadata = data.get('batch_metadata', {})
1066            writer.writerow(['Batch Analysis Results'])
1067            writer.writerow(['Export Timestamp:', data.get('export_timestamp', 'Unknown')])
1068            writer.writerow([])
1069            
1070            writer.writerow(['Batch Metadata'])
1071            for key, value in metadata.items():
1072                writer.writerow([key, value])
1073            
1074            writer.writerow([])
1075            
1076            # Batch summary
1077            summary = data.get('batch_summary', {})
1078            writer.writerow(['Batch Summary'])
1079            for key, value in summary.items():
1080                writer.writerow([key, value])
1081            
1082            writer.writerow([])
1083            
1084            # Individual results (simplified)
1085            results = data.get('batch_results', [])
1086            if results:
1087                writer.writerow(['Individual Results'])
1088                writer.writerow(['Index', 'Status', 'Summary'])
1089                
1090                for i, result in enumerate(results):
1091                    status = 'Success' if not result.get('error') else 'Error'
1092                    summary_text = str(result)[:100] + '...' if len(str(result)) > 100 else str(result)
1093                    writer.writerow([i, status, summary_text])
1094            
1095            return output.getvalue()
1096            
1097        except Exception as e:
1098            return f"Batch CSV export error: {str(e)}"
1099    
1100    def _export_geo_pdf(self, data: Dict[str, Any]) -> bytes:
1101        """Export GEO data as PDF (placeholder - would need reportlab)"""
1102        try:
1103            # For now, return HTML content as bytes
1104            # In a full implementation, you'd use reportlab or weasyprint
1105            html_content = self._export_geo_html(data)
1106            return html_content.encode('utf-8')
1107            
1108        except Exception as e:
1109            error_content = f"PDF export not fully implemented. Error: {str(e)}"
1110            return error_content.encode('utf-8')
1111    
1112    def _create_executive_summary(self, analysis_data: Dict[str, Any]) -> Dict[str, Any]:
1113        """Create executive summary report"""
1114        try:
1115            geo_results = analysis_data.get('geo_results', [])
1116            enhancement_results = analysis_data.get('enhancement_results', {})
1117            qa_results = analysis_data.get('qa_results', [])
1118            
1119            # Calculate key metrics
1120            overall_performance = self._calculate_overall_performance(analysis_data)
1121            
1122            return {
1123                'executive_summary': {
1124                    'overall_performance_score': overall_performance,
1125                    'key_findings': self._extract_key_findings(analysis_data),
1126                    'priority_recommendations': self._get_priority_recommendations(analysis_data),
1127                    'roi_potential': self._estimate_roi_potential(overall_performance),
1128                    'implementation_timeline': self._suggest_implementation_timeline(analysis_data),
1129                    'resource_requirements': self._estimate_resource_requirements(analysis_data)
1130                }
1131            }
1132            
1133        except Exception as e:
1134            return {'error': f"Executive summary creation failed: {str(e)}"}
1135    
1136    def _create_summary_report(self, analysis_data: Dict[str, Any]) -> Dict[str, Any]:
1137        """Create summary report"""
1138        try:
1139            return {
1140                'summary_report': {
1141                    'analysis_overview': self._create_analysis_overview(analysis_data),
1142                    'performance_metrics': self._summarize_performance_metrics(analysis_data),
1143                    'improvement_opportunities': self._identify_improvement_opportunities(analysis_data),
1144                    'competitive_position': self._assess_competitive_position(analysis_data),
1145                    'next_steps': self._recommend_next_steps(analysis_data)
1146                }
1147            }
1148            
1149        except Exception as e:
1150            return {'error': f"Summary report creation failed: {str(e)}"}
1151    
1152    def _create_full_report(self, analysis_data: Dict[str, Any]) -> Dict[str, Any]:
1153        """Create full detailed report"""
1154        try:
1155            return {
1156                'full_report': {
1157                    'executive_summary': self._create_executive_summary(analysis_data).get('executive_summary', {}),
1158                    'detailed_analysis': {
1159                        'geo_analysis_details': analysis_data.get('geo_results', []),
1160                        'content_optimization_details': analysis_data.get('enhancement_results', {}),
1161                        'qa_performance_details': analysis_data.get('qa_results', [])
1162                    },
1163                    'methodology': self._document_methodology(),
1164                    'data_sources': self._document_data_sources(analysis_data),
1165                    'limitations': self._document_limitations(),
1166                    'appendices': self._create_appendices(analysis_data)
1167                }
1168            }
1169            
1170        except Exception as e:
1171            return {'error': f"Full report creation failed: {str(e)}"}
1172    
1173    def _create_batch_summary(self, batch_results: List[Dict[str, Any]]) -> Dict[str, Any]:
1174        """Create summary of batch processing results"""
1175        try:
1176            total_items = len(batch_results)
1177            successful_items = len([r for r in batch_results if not r.get('error')])
1178            failed_items = total_items - successful_items
1179            
1180            return {
1181                'total_items': total_items,
1182                'successful_items': successful_items,
1183                'failed_items': failed_items,
1184                'success_rate': (successful_items / total_items * 100) if total_items > 0 else 0,
1185                'processing_status': 'Completed',
1186                'average_processing_time': self._calculate_avg_processing_time(batch_results),
1187                'common_errors': self._identify_common_errors(batch_results)
1188            }
1189            
1190        except Exception as e:
1191            return {'error': f"Batch summary creation failed: {str(e)}"}
1192    
1193    def _generate_performance_insights(self, scores: Dict[str, float], overall_avg: float) -> List[str]:
1194        """Generate performance insights from scores"""
1195        insights = []
1196        
1197        try:
1198            # Overall performance insight
1199            if overall_avg >= 8.0:
1200                insights.append("Excellent overall GEO performance - content is well-optimized for AI search engines")

Showing the first 1,200 of 1896 lines. Download the file for the rest.