import pandas as pd
import matplotlib.pyplot as plt
from fpdf import FPDF
import os

def generate_report(data: pd.DataFrame, method="topsis", filename="decision_report.pdf"):
    """
    Generate a comprehensive PDF report for decision analysis results
    
    Parameters:
    - data: DataFrame with analysis results
    - method: Method used ('topsis' or 'vikor')
    - filename: Output PDF filename
    """
    pdf = FPDF()
    pdf.add_page()
    pdf.set_font("Arial", 'B', size=20)

    # Title
    pdf.cell(200, 10, txt=f"{method.upper()} Decision Analysis Report", ln=True, align="C")
    pdf.ln(10)
    
    pdf.set_font("Arial", size=10)
    pdf.cell(200, 6, txt="Generated by TOPSISX - Multi-Criteria Decision Making Tool", ln=True, align="C")
    pdf.ln(10)

    # Summary Section
    pdf.set_font("Arial", 'B', size=14)
    pdf.cell(200, 10, txt="Executive Summary", ln=True)
    pdf.set_font("Arial", size=11)
    pdf.ln(5)
    
    # Get score column
    score_col = 'Topsis_Score' if 'Topsis_Score' in data.columns else 'Q'
    
    # Summary statistics
    pdf.cell(200, 8, txt=f"Total Alternatives Evaluated: {len(data)}", ln=True)
    pdf.cell(200, 8, txt=f"Analysis Method: {method.upper()}", ln=True)
    if score_col in data.columns:
        pdf.cell(200, 8, txt=f"Average Score: {data[score_col].mean():.4f}", ln=True)
        pdf.cell(200, 8, txt=f"Score Range: {data[score_col].min():.4f} - {data[score_col].max():.4f}", ln=True)
    pdf.ln(10)

    # Top 3 Recommendations
    pdf.set_font("Arial", 'B', size=14)
    pdf.cell(200, 10, txt="Top 3 Recommendations", ln=True)
    pdf.set_font("Arial", size=11)
    pdf.ln(5)
    
    top_3 = data.head(3)
    for idx, row in top_3.iterrows():
        rank = int(row['Rank'])
        medal = ["🥇", "🥈", "🥉"][idx] if idx < 3 else f"#{rank}"
        
        # Alternative identifier (first non-numeric column or index)
        alt_name = None
        for col in data.columns:
            if col not in ['Rank', 'Topsis_Score', 'Q', 'S', 'R'] and data[col].dtype == 'object':
                alt_name = str(row[col])
                break
        
        if alt_name is None:
            alt_name = f"Alternative {idx + 1}"
        
        pdf.set_font("Arial", 'B', size=12)
        pdf.cell(200, 8, txt=f"Rank {rank}: {alt_name}", ln=True)
        
        pdf.set_font("Arial", size=10)
        if score_col in data.columns:
            pdf.cell(200, 6, txt=f"   Score: {row[score_col]:.4f}", ln=True)
        pdf.ln(3)
    
    pdf.ln(5)

    # Rankings Table
    pdf.add_page()
    pdf.set_font("Arial", 'B', size=14)
    pdf.cell(200, 10, txt="Complete Rankings Table", ln=True)
    pdf.ln(5)
    
    # Table header
    pdf.set_font("Arial", 'B', size=9)
    pdf.set_fill_color(200, 220, 255)
    
    # Determine columns to show (limit to prevent overflow)
    display_cols = []
    for col in data.columns:
        if len(display_cols) < 6:  # Limit to 6 columns
            display_cols.append(col)
    
    col_width = 190 / len(display_cols)
    
    # Header row
    for col in display_cols:
        pdf.cell(col_width, 8, txt=str(col)[:15], border=1, align='C', fill=True)
    pdf.ln()
    
    # Data rows
    pdf.set_font("Arial", size=8)
    for idx, row in data.iterrows():
        for col in display_cols:
            value = row[col]
            if isinstance(value, (int, float)):
                text = f"{value:.3f}" if isinstance(value, float) else str(value)
            else:
                text = str(value)[:15]
            pdf.cell(col_width, 7, txt=text, border=1, align='C')
        pdf.ln()
    
    # Generate chart if possible
    chart_path = "chart_temp.png"
    try:
        if score_col in data.columns:
            plt.figure(figsize=(10, 6))
            
            # Get alternative names
            alt_names = []
            for idx, row in data.iterrows():
                name_found = False
                for col in data.columns:
                    if col not in ['Rank', 'Topsis_Score', 'Q', 'S', 'R'] and data[col].dtype == 'object':
                        alt_names.append(str(row[col])[:20])
                        name_found = True
                        break
                if not name_found:
                    alt_names.append(f"Alt {idx + 1}")
            
            # Create horizontal bar chart
            plt.barh(alt_names, data[score_col], color='skyblue', edgecolor='navy')
            plt.xlabel(score_col, fontsize=12)
            plt.ylabel('Alternatives', fontsize=12)
            plt.title(f'{method.upper()} Ranking Scores', fontsize=14, fontweight='bold')
            plt.grid(axis='x', alpha=0.3)
            plt.tight_layout()
            plt.savefig(chart_path, dpi=150, bbox_inches='tight')
            plt.close()

            # Add chart to PDF
            pdf.add_page()
            pdf.set_font("Arial", 'B', size=14)
            pdf.cell(200, 10, txt="Visual Analysis", ln=True)
            pdf.ln(5)
            pdf.image(chart_path, x=10, y=40, w=190)
            
            # Clean up
            if os.path.exists(chart_path):
                os.remove(chart_path)
    except Exception as e:
        print(f"Warning: Could not generate chart: {e}")

    # Methodology Section
    pdf.add_page()
    pdf.set_font("Arial", 'B', size=14)
    pdf.cell(200, 10, txt="Methodology", ln=True)
    pdf.ln(5)
    
    pdf.set_font("Arial", size=10)
    
    if method.lower() == "topsis":
        methodology_text = """
TOPSIS (Technique for Order of Preference by Similarity to Ideal Solution) is a 
multi-criteria decision analysis method that ranks alternatives based on their 
geometric distance from the ideal best and ideal worst solutions.

Steps:
1. Normalize the decision matrix
2. Calculate weighted normalized matrix
3. Determine ideal best and ideal worst solutions
4. Calculate separation measures (distances)
5. Calculate relative closeness to ideal solution
6. Rank alternatives by closeness coefficient

Higher TOPSIS scores indicate better alternatives.
        """
    else:  # VIKOR
        methodology_text = """
VIKOR (VIseKriterijumska Optimizacija I Kompromisno Resenje) is a multi-criteria 
decision making method that focuses on ranking and selecting from alternatives with 
conflicting criteria.

The method introduces the multi-criteria ranking index based on the particular measure 
of "closeness" to the "ideal" solution. It provides a maximum group utility of the 
majority and a minimum individual regret of the opponent.

Steps:
1. Calculate S (group utility) and R (individual regret)
2. Compute Q values using strategy weight v
3. Rank alternatives by Q values
4. Propose compromise solution

Lower Q values indicate better alternatives.
        """
    
    # Write methodology text
    pdf.multi_cell(0, 6, txt=methodology_text.strip())
    
    # Footer
    pdf.ln(10)
    pdf.set_font("Arial", 'I', size=9)
    pdf.cell(200, 6, txt="Generated by TOPSISX v0.1.4", ln=True, align='C')
    pdf.cell(200, 6, txt="https://github.com/SuvitKumar003/ranklib", ln=True, align='C')

    # Save PDF
    pdf.output(filename)
    print(f"✅ PDF Report saved as {filename}")