from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.database import get_db
from app.models.vulnerability import Vulnerability, VulnerabilitySeverity, VulnerabilityStatus
from app.auth.dependencies import get_current_user, RequireEditor
from app.models.user import User
import csv
import io
from fastapi.responses import StreamingResponse
from datetime import datetime
from reportlab.lib import colors
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from datetime import timedelta

router = APIRouter(prefix="/api/v1/reports", tags=["Reports"])

@router.get("/vulnerabilities/csv")
async def export_vulnerabilities_csv(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    Exports all vulnerabilities to a CSV file.
    """
    vulns = db.query(Vulnerability).all()

    output = io.StringIO()
    writer = csv.writer(output)
    
    # Header
    writer.writerow([
        "ID", "CVE ID", "Asset", "IP Address", "Severity", "CVSS", 
        "Status", "Package", "Version", "Fixed Version", 
        "Detected At", "Assigned User", "Assigned Group"
    ])

    for v in vulns:
        assigned_user = v.assigned_user.username if v.assigned_user else ""
        assigned_group = v.group.name if v.group else ""
        
        writer.writerow([
            v.id,
            v.cve_id,
            v.asset.hostname if v.asset else "Unknown",
            v.asset.ip_address if v.asset else "",
            v.severity.value if v.severity else "",
            v.cvss_score,
            v.status.value if v.status else "",
            v.package_name,
            v.package_version,
            v.fixed_version,
            v.detected_at.isoformat() if v.detected_at else "",
            assigned_user,
            assigned_group
        ])

    output.seek(0)
    
    response = StreamingResponse(iter([output.getvalue()]), media_type="text/csv")
    response.headers["Content-Disposition"] = f"attachment; filename=vulnerabilities_report_{datetime.now().strftime('%Y%m%d')}.csv"
    return response


@router.get("/executive-summary/pdf")
async def export_executive_summary_pdf(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    Generates an Executive Summary PDF report.
    """
    buffer = io.BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=letter)
    story = []
    styles = getSampleStyleSheet()

    # Title
    title_style = styles['Title']
    story.append(Paragraph(f"Executive Security Summary", title_style))
    story.append(Paragraph(f"Date: {datetime.now().strftime('%Y-%m-%d')}", styles['Normal']))
    story.append(Spacer(1, 12))

    # Stats
    total_vulns = db.query(Vulnerability).count()
    critical = db.query(Vulnerability).filter(Vulnerability.severity == VulnerabilitySeverity.critical).count()
    high = db.query(Vulnerability).filter(Vulnerability.severity == VulnerabilitySeverity.high).count()
    medium = db.query(Vulnerability).filter(Vulnerability.severity == VulnerabilitySeverity.medium).count()
    low = db.query(Vulnerability).filter(Vulnerability.severity == VulnerabilitySeverity.low).count()

    open_vulns = db.query(Vulnerability).filter(Vulnerability.status == VulnerabilityStatus.open).count()
    patched = db.query(Vulnerability).filter(Vulnerability.status == VulnerabilityStatus.patched).count()

    story.append(Paragraph("Vulnerability Overview", styles['Heading2']))
    
    data = [
        ['Metric', 'Count'],
        ['Total Vulnerabilities', str(total_vulns)],
        ['Critical Severity', str(critical)],
        ['High Severity', str(high)],
        ['Medium Severity', str(medium)],
        ['Low Severity', str(low)],
        ['Open Status', str(open_vulns)],
        ['Patched Status', str(patched)],
    ]

    t = Table(data)
    t.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (1, 0), colors.grey),
        ('TEXTCOLOR', (0, 0), (1, 0), colors.whitesmoke),
        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
        ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
        ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
        ('BACKGROUND', (0, 1), (-1, -1), colors.beige),
        ('GRID', (0, 0), (-1, -1), 1, colors.black),
    ]))
    story.append(t)
    story.append(Spacer(1, 12))

    # Top Risks (Critical & Open)
    story.append(Paragraph("Top Priority Risks (Critical & Open)", styles['Heading2']))
    
    top_risks = db.query(Vulnerability).filter(
        Vulnerability.severity == VulnerabilitySeverity.critical,
        Vulnerability.status == VulnerabilityStatus.open
    ).limit(5).all()

    if top_risks:
        risk_data = [['CVE ID', 'Description', 'Asset']]
        for v in top_risks:
            risk_data.append([
                v.cve_id, 
                Paragraph(v.description[:100] + "..." if v.description else "N/A", styles['BodyText']),
                v.asset.hostname if v.asset else "Unknown"
            ])
        
        t2 = Table(risk_data, colWidths=[1.5*inch, 4*inch, 1.5*inch])
        t2.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.red),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
            ('VALIGN', (0, 0), (-1, -1), 'TOP'),
        ]))
        story.append(t2)
    else:
        story.append(Paragraph("No critical open vulnerabilities found. Great job!", styles['Normal']))

    doc.build(story)
    buffer.seek(0)
    
    response = StreamingResponse(buffer, media_type="application/pdf")
    response.headers["Content-Disposition"] = f"attachment; filename=executive_summary_{datetime.now().strftime('%Y%m%d')}.pdf"
    return response


@router.get("/patching-progress/pdf")
async def export_patching_progress_pdf(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    Generates a Patching Progress PDF report (Last 30 Days).
    """
    buffer = io.BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=letter)
    story = []
    styles = getSampleStyleSheet()

    # Title
    story.append(Paragraph(f"Patching Progress Report", styles['Title']))
    story.append(Paragraph(f"Date: {datetime.now().strftime('%Y-%m-%d')}", styles['Normal']))
    story.append(Spacer(1, 12))

    # Query Patched in last 30 days
    last_30_days = datetime.now() - timedelta(days=30)
    patched_vulns = db.query(Vulnerability).filter(
        Vulnerability.status == VulnerabilityStatus.patched,
        Vulnerability.patched_at >= last_30_days
    ).all()

    story.append(Paragraph(f"Remediation Summary (Last 30 Days)", styles['Heading2']))
    story.append(Paragraph(f"Total Vulnerabilities Patched: {len(patched_vulns)}", styles['Normal']))
    story.append(Spacer(1, 12))

    if patched_vulns:
        data = [['CVE ID', 'Asset', 'Severity', 'Patched Date']]
        for v in patched_vulns:
            data.append([
                v.cve_id,
                v.asset.hostname if v.asset else "Unknown",
                v.severity.value,
                v.patched_at.strftime('%Y-%m-%d') if v.patched_at else "Unknown"
            ])
        
        t = Table(data, colWidths=[2*inch, 2.5*inch, 1.5*inch, 1.5*inch])
        t.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.green),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
        ]))
        story.append(t)
    else:
        story.append(Paragraph("No patched vulnerabilities found in the last 30 days.", styles['Normal']))

    doc.build(story)
    buffer.seek(0)
    
    response = StreamingResponse(buffer, media_type="application/pdf")
    response.headers["Content-Disposition"] = f"attachment; filename=patching_progress_{datetime.now().strftime('%Y%m%d')}.pdf"
    return response


@router.get("/compliance/iso27001/pdf")
async def export_compliance_audit_pdf(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_user)
):
    """
    Generates an ISO 27001 Compliance Audit PDF report. 
    Focuses on A.12.6.1 (Technical Vulnerability Management).
    """
    buffer = io.BytesIO()
    doc = SimpleDocTemplate(buffer, pagesize=letter)
    story = []
    styles = getSampleStyleSheet()

    # Title
    story.append(Paragraph(f"ISO 27001 Compliance Audit Report", styles['Title']))
    story.append(Paragraph(f"Date: {datetime.now().strftime('%Y-%m-%d')}", styles['Normal']))
    story.append(Spacer(1, 12))

    story.append(Paragraph("Control A.12.6.1 - Technical Vulnerability Management", styles['Heading2']))
    story.append(Paragraph("Objective: To prevent exploitation of technical vulnerabilities.", styles['Normal']))
    story.append(Spacer(1, 12))

    # Audit Logic: Check for Open Critical/High vulnerabilities
    non_compliant_vulns = db.query(Vulnerability).filter(
        Vulnerability.status == VulnerabilityStatus.open,
        Vulnerability.severity.in_([VulnerabilitySeverity.critical, VulnerabilitySeverity.high])
    ).all()

    is_compliant = len(non_compliant_vulns) == 0

    # Status Banner
    status_text = "COMPLIANT" if is_compliant else "NON-COMPLIANT"
    status_color = colors.green if is_compliant else colors.red
    
    t_status = Table([[f"Audit Status: {status_text}"]], colWidths=[7*inch])
    t_status.setStyle(TableStyle([
        ('BACKGROUND', (0, 0), (-1, -1), status_color),
        ('TEXTCOLOR', (0, 0), (-1, -1), colors.white),
        ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
        ('FONTNAME', (0, 0), (-1, -1), 'Helvetica-Bold'),
        ('FONTSIZE', (0, 0), (-1, -1), 14),
        ('TOPPADDING', (0, 0), (-1, -1), 12),
        ('BOTTOMPADDING', (0, 0), (-1, -1), 12),
    ]))
    story.append(t_status)
    story.append(Spacer(1, 12))

    if not is_compliant:
        story.append(Paragraph(f"Findings: {len(non_compliant_vulns)} Critical/High vulnerabilities detected which violate timely remediation requirements.", styles['BodyText']))
        story.append(Spacer(1, 6))
        
        data = [['CVE ID', 'Severity', 'Asset', 'Detected At']]
        for v in non_compliant_vulns[:20]: # Limit to top 20 to avoid confusing PDF overflow
            data.append([
                v.cve_id,
                v.severity.value,
                v.asset.hostname if v.asset else "Unknown",
                v.detected_at.strftime('%Y-%m-%d %H:%M')
            ])
        
        t = Table(data, colWidths=[2*inch, 1*inch, 2.5*inch, 1.5*inch])
        t.setStyle(TableStyle([
            ('BACKGROUND', (0, 0), (-1, 0), colors.grey),
            ('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
            ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
            ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
            ('GRID', (0, 0), (-1, -1), 1, colors.black),
        ]))
        story.append(t)
        
        if len(non_compliant_vulns) > 20:
             story.append(Paragraph(f"...and {len(non_compliant_vulns) - 20} more items.", styles['Normal']))

    else:
        story.append(Paragraph("No critical or high vulnerabilities found. System management appears to be in line with control requirements.", styles['Normal']))

    doc.build(story)
    buffer.seek(0)
    
    response = StreamingResponse(buffer, media_type="application/pdf")
    response.headers["Content-Disposition"] = f"attachment; filename=compliance_audit_{datetime.now().strftime('%Y%m%d')}.pdf"
    return response
