"""
AdamOps Reports Module

Generates HTML/PDF reports for model evaluation.
"""

from typing import Any, Dict, List, Optional
from pathlib import Path
from datetime import datetime
import json

import numpy as np
import pandas as pd

from adamops.utils.logging import get_logger
from adamops.evaluation.metrics import evaluate, classification_report

logger = get_logger(__name__)

HTML_TEMPLATE = """
<!DOCTYPE html>
<html>
<head>
    <title>{title}</title>
    <style>
        body {{ font-family: Arial, sans-serif; margin: 40px; background: #f5f5f5; }}
        .container {{ max-width: 1200px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }}
        h1 {{ color: #333; border-bottom: 2px solid #4a90d9; padding-bottom: 10px; }}
        h2 {{ color: #666; margin-top: 30px; }}
        table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }}
        th, td {{ border: 1px solid #ddd; padding: 12px; text-align: left; }}
        th {{ background: #4a90d9; color: white; }}
        tr:nth-child(even) {{ background: #f9f9f9; }}
        .metric {{ font-size: 24px; font-weight: bold; color: #4a90d9; }}
        .metric-card {{ display: inline-block; padding: 20px; margin: 10px; background: #f0f7ff; border-radius: 8px; text-align: center; min-width: 150px; }}
        .metric-label {{ color: #666; font-size: 14px; }}
        .section {{ margin: 30px 0; }}
        .footer {{ margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; color: #999; font-size: 12px; }}
    </style>
</head>
<body>
    <div class="container">
        <h1>{title}</h1>
        <p>Generated: {timestamp}</p>
        {content}
        <div class="footer">Generated by AdamOps v0.1.0</div>
    </div>
</body>
</html>
"""


class EvaluationReport:
    """Model evaluation report generator."""
    
    def __init__(self, model_name: str = "Model"):
        self.model_name = model_name
        self.sections = []
        self.metrics = {}
        self.timestamp = datetime.now().isoformat()
    
    def add_metrics(self, metrics: Dict[str, float], title: str = "Performance Metrics"):
        """Add metrics section."""
        self.metrics.update(metrics)
        
        cards = ""
        for name, value in metrics.items():
            if isinstance(value, float):
                value_str = f"{value:.4f}"
            else:
                value_str = str(value)
            cards += f'<div class="metric-card"><div class="metric">{value_str}</div><div class="metric-label">{name}</div></div>'
        
        self.sections.append(f'<div class="section"><h2>{title}</h2>{cards}</div>')
    
    def add_table(self, df: pd.DataFrame, title: str = "Results"):
        """Add table section."""
        table_html = df.to_html(index=False, classes='results-table')
        self.sections.append(f'<div class="section"><h2>{title}</h2>{table_html}</div>')
    
    def add_text(self, text: str, title: str = "Notes"):
        """Add text section."""
        self.sections.append(f'<div class="section"><h2>{title}</h2><p>{text}</p></div>')
    
    def add_confusion_matrix(self, y_true: np.ndarray, y_pred: np.ndarray,
                             labels: Optional[List[str]] = None):
        """Add confusion matrix section."""
        from sklearn.metrics import confusion_matrix
        cm = confusion_matrix(y_true, y_pred)
        cm_df = pd.DataFrame(cm, 
                            index=[f'Actual: {l}' for l in (labels or range(len(cm)))],
                            columns=[f'Pred: {l}' for l in (labels or range(len(cm)))])
        self.add_table(cm_df, "Confusion Matrix")
    
    def add_classification_report(self, y_true: np.ndarray, y_pred: np.ndarray):
        """Add classification report section."""
        report = classification_report(y_true, y_pred, output_dict=True)
        df = pd.DataFrame(report).T.reset_index().rename(columns={'index': 'class'})
        self.add_table(df.round(4), "Classification Report")
    
    def generate_html(self) -> str:
        """Generate HTML report."""
        content = "\n".join(self.sections)
        return HTML_TEMPLATE.format(
            title=f"{self.model_name} Evaluation Report",
            timestamp=self.timestamp,
            content=content
        )
    
    def save_html(self, filepath: str):
        """Save HTML report to file."""
        filepath = Path(filepath)
        filepath.parent.mkdir(parents=True, exist_ok=True)
        
        with open(filepath, 'w', encoding='utf-8') as f:
            f.write(self.generate_html())
        
        logger.info(f"Report saved to {filepath}")
    
    def save_json(self, filepath: str):
        """Save report data as JSON."""
        data = {
            "model_name": self.model_name,
            "timestamp": self.timestamp,
            "metrics": self.metrics,
        }
        
        with open(filepath, 'w') as f:
            json.dump(data, f, indent=2, default=str)


def generate_report(
    model_name: str, y_true: np.ndarray, y_pred: np.ndarray,
    y_prob: Optional[np.ndarray] = None, task: str = "classification",
    save_path: Optional[str] = None
) -> EvaluationReport:
    """
    Generate evaluation report.
    
    Args:
        model_name: Name of the model.
        y_true: True labels.
        y_pred: Predicted labels.
        y_prob: Probability predictions.
        task: 'classification' or 'regression'.
        save_path: Optional path to save HTML report.
    
    Returns:
        EvaluationReport object.
    """
    report = EvaluationReport(model_name)
    
    # Add metrics
    metrics = evaluate(y_true, y_pred, task, y_prob)
    report.add_metrics(metrics)
    
    # Add task-specific sections
    if task == "classification":
        report.add_confusion_matrix(y_true, y_pred)
        report.add_classification_report(y_true, y_pred)
    
    if save_path:
        report.save_html(save_path)
    
    return report
