"""
Auto Report Generator for Land Classification
Tự động tạo báo cáo HTML chi tiết sau training/prediction
"""

import json
from datetime import datetime
from pathlib import Path
import base64
import io

# Optional: for generating charts
try:
    import matplotlib
    matplotlib.use('Agg')  # Non-interactive backend
    import matplotlib.pyplot as plt
    import numpy as np
    MATPLOTLIB_AVAILABLE = True
except ImportError:
    MATPLOTLIB_AVAILABLE = False


def generate_confusion_matrix_image(conf_matrix, class_names):
    """Tạo hình ảnh confusion matrix dạng base64"""
    if not MATPLOTLIB_AVAILABLE:
        return None
    
    try:
        fig, ax = plt.subplots(figsize=(10, 8))
        conf_matrix = np.array(conf_matrix)
        
        im = ax.imshow(conf_matrix, interpolation='nearest', cmap=plt.cm.Blues)
        ax.figure.colorbar(im, ax=ax)
        
        ax.set(xticks=np.arange(len(class_names)),
               yticks=np.arange(len(class_names)),
               xticklabels=class_names, yticklabels=class_names,
               title='Confusion Matrix',
               ylabel='Thực tế (True)',
               xlabel='Dự đoán (Predicted)')
        
        plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")
        
        # Add text annotations
        thresh = conf_matrix.max() / 2.
        for i in range(len(class_names)):
            for j in range(len(class_names)):
                ax.text(j, i, format(conf_matrix[i, j], 'd'),
                       ha="center", va="center",
                       color="white" if conf_matrix[i, j] > thresh else "black")
        
        fig.tight_layout()
        
        # Convert to base64
        buf = io.BytesIO()
        plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
        buf.seek(0)
        img_base64 = base64.b64encode(buf.read()).decode('utf-8')
        plt.close(fig)
        
        return img_base64
    except Exception as e:
        print(f"Error generating confusion matrix image: {e}")
        return None


def generate_class_distribution_chart(class_names, classification_report):
    """Tạo biểu đồ phân bố các class dạng base64"""
    if not MATPLOTLIB_AVAILABLE:
        return None
    
    try:
        # Extract support (number of samples) for each class
        supports = []
        for cls in class_names:
            if cls in classification_report:
                supports.append(classification_report[cls].get('support', 0))
            else:
                supports.append(0)
        
        fig, ax = plt.subplots(figsize=(10, 6))
        colors = plt.cm.Set3(np.linspace(0, 1, len(class_names)))
        
        bars = ax.bar(class_names, supports, color=colors)
        ax.set_xlabel('Loại đất')
        ax.set_ylabel('Số mẫu')
        ax.set_title('Phân bố số mẫu theo loại đất')
        plt.xticks(rotation=45, ha='right')
        
        # Add value labels on bars
        for bar, val in zip(bars, supports):
            ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5,
                   str(int(val)), ha='center', va='bottom', fontsize=9)
        
        fig.tight_layout()
        
        # Convert to base64
        buf = io.BytesIO()
        plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
        buf.seek(0)
        img_base64 = base64.b64encode(buf.read()).decode('utf-8')
        plt.close(fig)
        
        return img_base64
    except Exception as e:
        print(f"Error generating class distribution chart: {e}")
        return None


def generate_metrics_chart(class_names, classification_report):
    """Tạo biểu đồ precision/recall/f1 cho từng class"""
    if not MATPLOTLIB_AVAILABLE:
        return None
    
    try:
        precisions = []
        recalls = []
        f1_scores = []
        
        for cls in class_names:
            if cls in classification_report:
                precisions.append(classification_report[cls].get('precision', 0))
                recalls.append(classification_report[cls].get('recall', 0))
                f1_scores.append(classification_report[cls].get('f1-score', 0))
            else:
                precisions.append(0)
                recalls.append(0)
                f1_scores.append(0)
        
        x = np.arange(len(class_names))
        width = 0.25
        
        fig, ax = plt.subplots(figsize=(12, 6))
        
        bars1 = ax.bar(x - width, precisions, width, label='Precision', color='#3498db')
        bars2 = ax.bar(x, recalls, width, label='Recall', color='#2ecc71')
        bars3 = ax.bar(x + width, f1_scores, width, label='F1-Score', color='#e74c3c')
        
        ax.set_xlabel('Loại đất')
        ax.set_ylabel('Score')
        ax.set_title('Precision / Recall / F1-Score theo loại đất')
        ax.set_xticks(x)
        ax.set_xticklabels(class_names, rotation=45, ha='right')
        ax.legend()
        ax.set_ylim(0, 1.1)
        
        # Add grid
        ax.yaxis.grid(True, linestyle='--', alpha=0.7)
        
        fig.tight_layout()
        
        # Convert to base64
        buf = io.BytesIO()
        plt.savefig(buf, format='png', dpi=100, bbox_inches='tight')
        buf.seek(0)
        img_base64 = base64.b64encode(buf.read()).decode('utf-8')
        plt.close(fig)
        
        return img_base64
    except Exception as e:
        print(f"Error generating metrics chart: {e}")
        return None


def generate_training_report(training_result, config=None):
    """
    Tạo báo cáo HTML cho kết quả training
    
    Args:
        training_result: Dict chứa kết quả từ train_model()
        config: Dict chứa cấu hình training (optional)
    
    Returns:
        Tuple (report_path, report_html)
    """
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    
    # Extract data from result
    train_acc = training_result.get('train_accuracy', 0) * 100
    test_acc = training_result.get('test_accuracy', 0) * 100
    train_samples = training_result.get('training_samples', 0)
    test_samples = training_result.get('testing_samples', 0)
    test_size = training_result.get('test_size', 0.2)
    classes = training_result.get('classes', [])
    cls_report = training_result.get('classification_report', {})
    conf_matrix = training_result.get('confusion_matrix', [])
    model_type = training_result.get('model_type', 'unknown')
    model_path = training_result.get('model_path', '')
    bbox = training_result.get('bbox', [])
    time_range = training_result.get('time_range', '')
    resolution = training_result.get('resolution', 20)
    
    # Generate charts
    conf_matrix_img = generate_confusion_matrix_image(conf_matrix, classes) if conf_matrix else None
    class_dist_img = generate_class_distribution_chart(classes, cls_report) if cls_report else None
    metrics_img = generate_metrics_chart(classes, cls_report) if cls_report else None
    
    # Build classification report table
    cls_report_rows = ""
    for cls in classes:
        if cls in cls_report:
            metrics = cls_report[cls]
            cls_report_rows += f"""
            <tr>
                <td><strong>{cls}</strong></td>
                <td>{metrics.get('precision', 0):.3f}</td>
                <td>{metrics.get('recall', 0):.3f}</td>
                <td>{metrics.get('f1-score', 0):.3f}</td>
                <td>{int(metrics.get('support', 0))}</td>
            </tr>
            """
    
    # Add averages
    for avg_type in ['macro avg', 'weighted avg']:
        if avg_type in cls_report:
            metrics = cls_report[avg_type]
            cls_report_rows += f"""
            <tr style="background-color: #f0f0f0; font-weight: bold;">
                <td>{avg_type}</td>
                <td>{metrics.get('precision', 0):.3f}</td>
                <td>{metrics.get('recall', 0):.3f}</td>
                <td>{metrics.get('f1-score', 0):.3f}</td>
                <td>{int(metrics.get('support', 0))}</td>
            </tr>
            """
    
    # Build confusion matrix table (fallback if no image)
    conf_matrix_table = ""
    if conf_matrix:
        conf_matrix_table = "<table class='conf-matrix'><tr><th></th>"
        for cls in classes:
            conf_matrix_table += f"<th>{cls}</th>"
        conf_matrix_table += "</tr>"
        for i, row in enumerate(conf_matrix):
            conf_matrix_table += f"<tr><th>{classes[i]}</th>"
            for val in row:
                conf_matrix_table += f"<td>{val}</td>"
            conf_matrix_table += "</tr>"
        conf_matrix_table += "</table>"
    
    # HTML Template
    html = f"""
<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Training Report - {timestamp}</title>
    <style>
        * {{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }}
        body {{
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f5f5f5;
            padding: 20px;
            line-height: 1.6;
        }}
        .container {{
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }}
        .header {{
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 40px;
            text-align: center;
        }}
        .header h1 {{
            font-size: 2.5em;
            margin-bottom: 10px;
        }}
        .header .subtitle {{
            opacity: 0.9;
            font-size: 1.1em;
        }}
        .content {{
            padding: 40px;
        }}
        .section {{
            margin-bottom: 40px;
        }}
        .section h2 {{
            color: #667eea;
            border-bottom: 3px solid #667eea;
            padding-bottom: 10px;
            margin-bottom: 20px;
            font-size: 1.5em;
        }}
        .stats-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            margin-bottom: 30px;
        }}
        .stat-card {{
            background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
            padding: 25px;
            border-radius: 10px;
            text-align: center;
            border: 1px solid #667eea30;
        }}
        .stat-card .value {{
            font-size: 2.5em;
            font-weight: bold;
            color: #667eea;
        }}
        .stat-card .label {{
            color: #666;
            margin-top: 5px;
        }}
        .stat-card.success .value {{
            color: #28a745;
        }}
        .stat-card.warning .value {{
            color: #ffc107;
        }}
        table {{
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
        }}
        th, td {{
            padding: 12px 15px;
            text-align: left;
            border-bottom: 1px solid #ddd;
        }}
        th {{
            background: #667eea;
            color: white;
        }}
        tr:hover {{
            background-color: #f5f5f5;
        }}
        .conf-matrix {{
            font-size: 14px;
        }}
        .conf-matrix th, .conf-matrix td {{
            text-align: center;
            padding: 8px;
        }}
        .chart-container {{
            text-align: center;
            margin: 20px 0;
        }}
        .chart-container img {{
            max-width: 100%;
            border-radius: 10px;
            box-shadow: 0 4px 15px rgba(0,0,0,0.1);
        }}
        .info-box {{
            background: #e3f2fd;
            padding: 20px;
            border-radius: 10px;
            border-left: 5px solid #2196f3;
            margin: 20px 0;
        }}
        .info-row {{
            display: flex;
            margin: 10px 0;
        }}
        .info-label {{
            font-weight: bold;
            width: 200px;
            color: #555;
        }}
        .info-value {{
            color: #333;
        }}
        .footer {{
            background: #f8f9fa;
            padding: 20px;
            text-align: center;
            color: #666;
            font-size: 14px;
        }}
        @media print {{
            body {{
                background: white;
                padding: 0;
            }}
            .container {{
                box-shadow: none;
            }}
        }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📊 Báo Cáo Training Model</h1>
            <p class="subtitle">Land Classification - {datetime.now().strftime("%d/%m/%Y %H:%M:%S")}</p>
        </div>
        
        <div class="content">
            <!-- Summary Stats -->
            <div class="section">
                <h2>📈 Tóm Tắt Kết Quả</h2>
                <div class="stats-grid">
                    <div class="stat-card success">
                        <div class="value">{train_acc:.1f}%</div>
                        <div class="label">Train Accuracy</div>
                    </div>
                    <div class="stat-card {'success' if test_acc >= 80 else 'warning'}">
                        <div class="value">{test_acc:.1f}%</div>
                        <div class="label">Test Accuracy</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{train_samples}</div>
                        <div class="label">Training Samples</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{test_samples}</div>
                        <div class="label">Testing Samples</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{len(classes)}</div>
                        <div class="label">Số Classes</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{test_size*100:.0f}%</div>
                        <div class="label">Test Size</div>
                    </div>
                </div>
            </div>
            
            <!-- Configuration Info -->
            <div class="section">
                <h2>⚙️ Cấu Hình Training</h2>
                <div class="info-box">
                    <div class="info-row">
                        <span class="info-label">🤖 Model Type:</span>
                        <span class="info-value">{model_type.upper()}</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">📍 Khu vực (bbox):</span>
                        <span class="info-value">{bbox}</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">📅 Thời gian:</span>
                        <span class="info-value">{time_range}</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">📐 Độ phân giải:</span>
                        <span class="info-value">{resolution}m</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">💾 Model Path:</span>
                        <span class="info-value">{model_path}</span>
                    </div>
                </div>
            </div>
            
            <!-- Classification Report -->
            <div class="section">
                <h2>📋 Classification Report</h2>
                <table>
                    <thead>
                        <tr>
                            <th>Loại đất</th>
                            <th>Precision</th>
                            <th>Recall</th>
                            <th>F1-Score</th>
                            <th>Support</th>
                        </tr>
                    </thead>
                    <tbody>
                        {cls_report_rows}
                    </tbody>
                </table>
            </div>
            
            <!-- Metrics Chart -->
            {'<div class="section"><h2>📊 Biểu Đồ Metrics</h2><div class="chart-container"><img src="data:image/png;base64,' + metrics_img + '" alt="Metrics Chart"></div></div>' if metrics_img else ''}
            
            <!-- Class Distribution -->
            {'<div class="section"><h2>📊 Phân Bố Số Mẫu</h2><div class="chart-container"><img src="data:image/png;base64,' + class_dist_img + '" alt="Class Distribution"></div></div>' if class_dist_img else ''}
            
            <!-- Confusion Matrix -->
            <div class="section">
                <h2>🔢 Confusion Matrix</h2>
                {'<div class="chart-container"><img src="data:image/png;base64,' + conf_matrix_img + '" alt="Confusion Matrix"></div>' if conf_matrix_img else conf_matrix_table}
            </div>
            
            <!-- Classes List -->
            <div class="section">
                <h2>🏷️ Danh Sách Các Loại Đất</h2>
                <div class="info-box">
                    <ul style="list-style: none; display: flex; flex-wrap: wrap; gap: 10px;">
                        {''.join([f'<li style="background: #667eea; color: white; padding: 8px 15px; border-radius: 20px;">{cls}</li>' for cls in classes])}
                    </ul>
                </div>
            </div>
        </div>
        
        <div class="footer">
            <p>🌍 Land Classification Training System | Generated: {datetime.now().strftime("%d/%m/%Y %H:%M:%S")}</p>
            <p>Data Source: Microsoft Planetary Computer (Sentinel-2 L2A, Sentinel-1 RTC)</p>
        </div>
    </div>
</body>
</html>
"""
    
    # Save report
    reports_dir = Path("reports")
    reports_dir.mkdir(exist_ok=True)
    
    report_filename = f"training_report_{timestamp}.html"
    report_path = reports_dir / report_filename
    
    with open(report_path, 'w', encoding='utf-8') as f:
        f.write(html)
    
    return str(report_path), html


def generate_prediction_report(prediction_result, config=None):
    """
    Tạo báo cáo HTML cho kết quả prediction
    
    Args:
        prediction_result: Dict chứa kết quả prediction
        config: Dict chứa cấu hình prediction (optional)
    
    Returns:
        Tuple (report_path, report_html)
    """
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    
    # Extract data
    output_file = prediction_result.get('output_file', '')
    shape = prediction_result.get('shape', [0, 0])
    unique_classes = prediction_result.get('unique_classes', [])
    bbox = prediction_result.get('bbox', [])
    time_range = prediction_result.get('time_range', '')
    n_features = prediction_result.get('n_features', 0)
    used_radar = prediction_result.get('used_radar', False)
    model_used = prediction_result.get('model_used', '')
    
    # Calculate area (approximate)
    if len(bbox) == 4:
        # Approximate calculation (1 degree ≈ 111km at equator)
        width_km = (bbox[2] - bbox[0]) * 111 * 0.85  # cos adjustment for Vietnam
        height_km = (bbox[3] - bbox[1]) * 111
        area_km2 = width_km * height_km
    else:
        area_km2 = 0
    
    total_pixels = shape[0] * shape[1] if len(shape) == 2 else 0
    
    # HTML Template
    html = f"""
<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Prediction Report - {timestamp}</title>
    <style>
        * {{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }}
        body {{
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: #f5f5f5;
            padding: 20px;
            line-height: 1.6;
        }}
        .container {{
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 15px;
            box-shadow: 0 10px 40px rgba(0,0,0,0.1);
            overflow: hidden;
        }}
        .header {{
            background: linear-gradient(135deg, #ff6b6b 0%, #ee5a6f 100%);
            color: white;
            padding: 40px;
            text-align: center;
        }}
        .header h1 {{
            font-size: 2.5em;
            margin-bottom: 10px;
        }}
        .content {{
            padding: 40px;
        }}
        .section {{
            margin-bottom: 40px;
        }}
        .section h2 {{
            color: #ff6b6b;
            border-bottom: 3px solid #ff6b6b;
            padding-bottom: 10px;
            margin-bottom: 20px;
        }}
        .stats-grid {{
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
        }}
        .stat-card {{
            background: linear-gradient(135deg, #ff6b6b15 0%, #ee5a6f15 100%);
            padding: 25px;
            border-radius: 10px;
            text-align: center;
            border: 1px solid #ff6b6b30;
        }}
        .stat-card .value {{
            font-size: 2em;
            font-weight: bold;
            color: #ff6b6b;
        }}
        .stat-card .label {{
            color: #666;
            margin-top: 5px;
        }}
        .info-box {{
            background: #fff3cd;
            padding: 20px;
            border-radius: 10px;
            border-left: 5px solid #ff6b6b;
            margin: 20px 0;
        }}
        .info-row {{
            display: flex;
            margin: 10px 0;
        }}
        .info-label {{
            font-weight: bold;
            width: 200px;
            color: #555;
        }}
        .class-badge {{
            display: inline-block;
            background: #ff6b6b;
            color: white;
            padding: 8px 15px;
            border-radius: 20px;
            margin: 5px;
        }}
        .footer {{
            background: #f8f9fa;
            padding: 20px;
            text-align: center;
            color: #666;
        }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🗺️ Báo Cáo Dự Đoán</h1>
            <p>Land Classification Prediction - {datetime.now().strftime("%d/%m/%Y %H:%M:%S")}</p>
        </div>
        
        <div class="content">
            <div class="section">
                <h2>📈 Tóm Tắt Kết Quả</h2>
                <div class="stats-grid">
                    <div class="stat-card">
                        <div class="value">{total_pixels:,}</div>
                        <div class="label">Tổng số Pixels</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{shape[0]}x{shape[1]}</div>
                        <div class="label">Kích thước (px)</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{area_km2:.1f}</div>
                        <div class="label">Diện tích (km²)</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{len(unique_classes)}</div>
                        <div class="label">Số Classes</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{n_features}</div>
                        <div class="label">Số Features</div>
                    </div>
                    <div class="stat-card">
                        <div class="value">{'✅' if used_radar else '❌'}</div>
                        <div class="label">Sử dụng Radar</div>
                    </div>
                </div>
            </div>
            
            <div class="section">
                <h2>⚙️ Thông Tin Chi Tiết</h2>
                <div class="info-box">
                    <div class="info-row">
                        <span class="info-label">🤖 Model sử dụng:</span>
                        <span>{model_used}</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">📍 Khu vực (bbox):</span>
                        <span>{bbox}</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">📅 Thời gian:</span>
                        <span>{time_range}</span>
                    </div>
                    <div class="info-row">
                        <span class="info-label">💾 Output file:</span>
                        <span>{output_file}</span>
                    </div>
                </div>
            </div>
            
            <div class="section">
                <h2>🏷️ Các Classes Phát Hiện</h2>
                <div>
                    {''.join([f'<span class="class-badge">{cls}</span>' for cls in unique_classes])}
                </div>
            </div>
        </div>
        
        <div class="footer">
            <p>🌍 Land Classification System | Generated: {datetime.now().strftime("%d/%m/%Y %H:%M:%S")}</p>
        </div>
    </div>
</body>
</html>
"""
    
    # Save report
    reports_dir = Path("reports")
    reports_dir.mkdir(exist_ok=True)
    
    report_filename = f"prediction_report_{timestamp}.html"
    report_path = reports_dir / report_filename
    
    with open(report_path, 'w', encoding='utf-8') as f:
        f.write(html)
    
    return str(report_path), html


if __name__ == "__main__":
    # Test report generation
    test_result = {
        "success": True,
        "train_accuracy": 0.95,
        "test_accuracy": 0.87,
        "training_samples": 800,
        "testing_samples": 200,
        "test_size": 0.2,
        "classes": ["Lua", "Rung", "Nuoc", "Dan_cu", "Cay_lau_nam"],
        "model_type": "xgboost",
        "model_path": "model_train/model_xgboost_20251221.joblib",
        "bbox": [105.6, 9.3, 106.2, 9.8],
        "time_range": "2023-03-01/2023-05-31",
        "resolution": 20,
        "classification_report": {
            "Lua": {"precision": 0.92, "recall": 0.89, "f1-score": 0.90, "support": 50},
            "Rung": {"precision": 0.88, "recall": 0.91, "f1-score": 0.89, "support": 45},
            "Nuoc": {"precision": 0.95, "recall": 0.93, "f1-score": 0.94, "support": 40},
            "Dan_cu": {"precision": 0.85, "recall": 0.82, "f1-score": 0.83, "support": 35},
            "Cay_lau_nam": {"precision": 0.80, "recall": 0.85, "f1-score": 0.82, "support": 30},
            "macro avg": {"precision": 0.88, "recall": 0.88, "f1-score": 0.88, "support": 200},
            "weighted avg": {"precision": 0.88, "recall": 0.87, "f1-score": 0.87, "support": 200}
        },
        "confusion_matrix": [
            [45, 2, 1, 1, 1],
            [3, 41, 0, 1, 0],
            [1, 0, 37, 1, 1],
            [2, 1, 1, 29, 2],
            [1, 1, 1, 2, 26]
        ]
    }
    
    path, html = generate_training_report(test_result)
    print(f"Report generated: {path}")
