from fpdf import FPDF
from fpdf.enums import XPos, YPos
from datetime import datetime

def safe_str(val):
    if not val:
        return ""
    return str(val).encode('latin-1', 'replace').decode('latin-1')

def draw_pill(pdf, x, y, w, h, text, bg_color, text_color):
    pdf.set_fill_color(*bg_color)
    pdf.rect(x, y, w, h, style='F', round_corners=True, corner_radius=h/2)
    pdf.set_text_color(*text_color)
    pdf.set_xy(x, y + h/2 - 1.5)
    pdf.cell(w, 3, safe_str(text), align='C')

class PremiumPDFReport(FPDF):
    def __init__(self, project_json, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.project_json = project_json
        self.set_auto_page_break(auto=True, margin=15)
        
    def _draw_gradient_line(self):
        # Fake a gradient by drawing small rectangles
        steps = 210
        for i in range(steps):
            # Cyan (0,255,255) to Pink (255,0,255)
            r = int(0 + (255 - 0) * (i / steps))
            g = int(255 - (255 - 0) * (i / steps))
            b = 255
            self.set_fill_color(r, g, b)
            self.rect(i * (210 / steps), 0, (210 / steps), 1.5, 'F')

    def header(self):
        # Only do custom header for pages > 1
        if self.page_no() > 1:
            self._draw_gradient_line()
            
            # Header text
            self.set_font('helvetica', '', 7)
            self.set_text_color(148, 163, 184) # Slate 400
            
            title = "Project Summary" if self.page_no() == 2 else "Tickets Details"
            self.set_xy(15, 10)
            self.cell(0, 5, safe_str(f"{self.page_no():02d} · {title}"))
            
            self.set_xy(15, 10)
            self.set_text_color(99, 102, 241) # Indigo 500
            self.cell(0, 5, safe_str(self.project_json["project"]["key"]), align='R')
            self.ln(15)

    def footer(self):
        if self.page_no() > 1:
            self.set_y(-15)
            self.set_font('helvetica', '', 7)
            self.set_text_color(203, 213, 225) # Slate 300
            self.cell(0, 10, "Phoenix Platform v2.0 · Confidential")
            self.set_xy(15, -15)
            self.cell(0, 10, str(self.page_no()), align='R')

def generate_pdf_report(report_json, pdf_path):
    pdf = PremiumPDFReport(report_json, orientation='P', unit='mm', format='A4')
    
    # ===============================
    # PAGE 1: COVER (DARK MODE)
    # ===============================
    pdf.add_page()
    # Dark background
    pdf.set_fill_color(15, 23, 42) # slate-900
    pdf.rect(0, 0, 210, 297, 'F')
    
    pdf._draw_gradient_line()
    
    # "PROJECT INTELLIGENCE REPORT"
    pdf.set_xy(15, 20)
    pdf.set_font('helvetica', 'B', 7)
    pdf.set_text_color(56, 189, 248) # sky-400
    pdf.cell(0, 5, "PROJECT INTELLIGENCE REPORT")
    
    # Title
    pdf.set_xy(15, 35)
    pdf.set_font('helvetica', 'B', 24)
    pdf.set_text_color(255, 255, 255)
    pdf.cell(0, 10, safe_str(report_json['project']['name']))
    
    # Description
    if report_json['project']['description']:
        pdf.set_xy(15, 50)
        pdf.set_font('helvetica', '', 10)
        pdf.set_text_color(148, 163, 184) # slate-400
        pdf.multi_cell(180, 5, safe_str(report_json['project']['description']))
        
    # Bottom Footer
    pdf.set_draw_color(30, 41, 59) # slate-800
    pdf.line(15, 240, 195, 240)
    
    col_w = 45
    pdf.set_y(245)
    
    # Column 1
    pdf.set_x(15)
    pdf.set_font('helvetica', 'B', 6)
    pdf.set_text_color(100, 116, 139) # slate-500
    pdf.cell(col_w, 4, "PROJECT KEY", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
    pdf.set_x(15)
    pdf.set_font('helvetica', 'B', 9)
    pdf.set_text_color(248, 250, 252) # slate-50
    pdf.cell(col_w, 5, safe_str(report_json['project']['key']))
    
    # Column 2
    pdf.set_xy(15 + col_w, 245)
    pdf.set_font('helvetica', 'B', 6)
    pdf.set_text_color(100, 116, 139)
    pdf.cell(col_w, 4, "OWNER", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
    pdf.set_x(15 + col_w)
    pdf.set_font('helvetica', 'B', 9)
    pdf.set_text_color(248, 250, 252)
    pdf.cell(col_w, 5, safe_str(report_json['project']['owner']))
    
    # Column 3
    pdf.set_xy(15 + col_w*2, 245)
    pdf.set_font('helvetica', 'B', 6)
    pdf.set_text_color(100, 116, 139)
    pdf.cell(col_w, 4, "PERIOD", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
    pdf.set_x(15 + col_w*2)
    pdf.set_font('helvetica', 'B', 9)
    pdf.set_text_color(248, 250, 252)
    pdf.cell(col_w, 5, safe_str(report_json['project']['period']))
    
    # Column 4
    pdf.set_xy(15 + col_w*3, 245)
    pdf.set_font('helvetica', 'B', 6)
    pdf.set_text_color(100, 116, 139)
    pdf.cell(col_w, 4, "GENERATED", new_x=XPos.LMARGIN, new_y=YPos.NEXT)
    pdf.set_x(15 + col_w*3)
    pdf.set_font('helvetica', 'B', 9)
    pdf.set_text_color(248, 250, 252)
    pdf.cell(col_w, 5, safe_str(report_json['project']['generated_date']))

    # Very bottom
    pdf.set_xy(15, 275)
    pdf.set_font('helvetica', 'B', 6)
    pdf.set_text_color(71, 85, 105) # slate-600
    pdf.cell(50, 5, "CONFIDENTIAL - INTERNAL USE ONLY")
    
    # Pill badge
    pill_text = f"{report_json['project']['key']} \xb7 {report_json['summary']['total_tickets']} TICKETS \xb7 {report_json['project']['total_members']} MEMBERS"
    draw_pill(pdf, 135, 274, 60, 6, pill_text, bg_color=(15, 23, 42), text_color=(71, 85, 105)) # Actually wait, pill bg needs a border.
    # To draw a border pill, we use style='D'
    pdf.set_draw_color(30, 41, 59)
    pdf.rect(135, 274, 60, 6, style='D', round_corners=True, corner_radius=3)

    # ===============================
    # PAGE 2: SUMMARY DASHBOARD
    # ===============================
    pdf.add_page()
    
    # KPI Boxes
    box_w = 42
    box_h = 28
    gap = 4
    start_y = pdf.get_y()
    
    metrics = [
        ("TOTAL TICKETS", safe_str(report_json['summary']['total_tickets']), "across all statuses"),
        ("COMPLETED", safe_str(f"{report_json['summary']['completed_tickets']}"), f"{report_json['summary']['completion_rate']}% completion rate"),
        ("CRITICAL OPEN", safe_str(report_json['summary']['critical_open_count']), "action required"),
        ("STORY POINTS", safe_str(f"{report_json['summary']['story_points_burned']}/{report_json['summary']['story_points_total']}"), "burned down")
    ]
    
    colors = [
        {"bg": (238, 242, 255), "text": (79, 70, 229), "border": (199, 210, 254)}, # Indigo
        {"bg": (236, 253, 245), "text": (16, 185, 129), "border": (167, 243, 208)}, # Emerald
        {"bg": (254, 242, 242), "text": (239, 68, 68), "border": (254, 202, 202)}, # Red
        {"bg": (255, 247, 237), "text": (249, 115, 22), "border": (253, 186, 116)}  # Orange
    ]
    
    for i, metric in enumerate(metrics):
        x = 15 + (box_w + gap) * i
        
        pdf.set_fill_color(*colors[i]["bg"])
        pdf.set_draw_color(*colors[i]["border"])
        pdf.rect(x, start_y, box_w, box_h, style='DF', round_corners=True, corner_radius=2)
        
        pdf.set_xy(x + 3, start_y + 4)
        pdf.set_font('helvetica', 'B', 6)
        pdf.set_text_color(71, 85, 105)
        pdf.cell(box_w - 6, 4, metric[0], new_x=XPos.LMARGIN, new_y=YPos.NEXT)
        
        pdf.set_xy(x + 3, start_y + 9)
        pdf.set_font('helvetica', 'B', 18)
        pdf.set_text_color(*colors[i]["text"])
        pdf.cell(box_w - 6, 8, metric[1], new_x=XPos.LMARGIN, new_y=YPos.NEXT)
        
        pdf.set_xy(x + 3, start_y + 19)
        pdf.set_font('helvetica', '', 6)
        pdf.set_text_color(100, 116, 139)
        pdf.cell(box_w - 6, 4, metric[2])
        
    start_y += box_h + 10
    
    # Progress bars section
    box_w = 88
    box_h = max(25 + len(report_json['status_breakdown'])*10, 25 + len(report_json['type_split'])*10)
    
    # Status Breakdown Box
    pdf.set_fill_color(255, 255, 255)
    pdf.set_draw_color(226, 232, 240)
    pdf.rect(15, start_y, box_w, box_h, style='DF', round_corners=True, corner_radius=2)
    
    pdf.set_xy(18, start_y + 4)
    pdf.set_font('helvetica', 'B', 7)
    pdf.set_text_color(71, 85, 105)
    pdf.cell(box_w, 5, "STATUS BREAKDOWN")
    
    py = start_y + 12
    for sb in report_json['status_breakdown']:
        pdf.set_xy(18, py)
        pdf.set_font('helvetica', 'B', 6)
        pdf.set_text_color(15, 23, 42)
        pdf.cell(40, 4, safe_str(sb['status']))
        
        pdf.set_font('helvetica', 'B', 6)
        pdf.set_text_color(148, 163, 184)
        pdf.cell(40, 4, safe_str(f"{sb['count']} tickets"), align='R')
        
        # Draw bar
        py += 4.5
        pdf.set_fill_color(241, 245, 249) # slate-100
        pdf.rect(18, py, 80, 1.5, 'F')
        
        pct = (sb['count'] / report_json['summary']['total_tickets']) if report_json['summary']['total_tickets'] > 0 else 0
        pdf.set_fill_color(99, 102, 241) # indigo-500
        pdf.rect(18, py, 80 * pct, 1.5, 'F')
        py += 6
        
    # Type Split Box
    x = 15 + box_w + gap
    pdf.set_fill_color(255, 255, 255)
    pdf.set_draw_color(226, 232, 240)
    pdf.rect(x, start_y, box_w, box_h, style='DF', round_corners=True, corner_radius=2)
    
    pdf.set_xy(x + 3, start_y + 4)
    pdf.set_font('helvetica', 'B', 7)
    pdf.set_text_color(71, 85, 105)
    pdf.cell(box_w, 5, "TICKET TYPE SPLIT")
    
    py = start_y + 12
    for ts in report_json['type_split']:
        pdf.set_xy(x + 3, py)
        pdf.set_font('helvetica', 'B', 6)
        pdf.set_text_color(15, 23, 42)
        pdf.cell(40, 4, safe_str(ts['type']))
        
        pdf.set_font('helvetica', 'B', 6)
        pdf.set_text_color(148, 163, 184)
        pdf.cell(40, 4, safe_str(f"{ts['count']}"), align='R')
        
        # Draw bar
        py += 4.5
        pdf.set_fill_color(241, 245, 249) # slate-100
        pdf.rect(x + 3, py, 80, 1.5, 'F')
        
        pct = (ts['count'] / report_json['summary']['total_tickets']) if report_json['summary']['total_tickets'] > 0 else 0
        pdf.set_fill_color(14, 165, 233) # sky-500
        pdf.rect(x + 3, py, 80 * pct, 1.5, 'F')
        py += 6

    # ===============================
    # PAGE 3: DATA TABLES
    # ===============================
    pdf.add_page()
    
    # Table Header (Black)
    pdf.set_fill_color(15, 23, 42)
    pdf.set_draw_color(15, 23, 42)
    pdf.rect(15, pdf.get_y(), 180, 8, 'F')
    
    col_widths = [20, 40, 30, 25, 30, 25, 10]
    headers = ["TICKET", "TITLE", "TYPE", "STATUS", "PRIORITY", "ASSIGNEE(S)", "SP"]
    
    pdf.set_xy(15, pdf.get_y() + 2)
    pdf.set_font('helvetica', 'B', 6)
    pdf.set_text_color(255, 255, 255)
    for i, header in enumerate(headers):
        align = 'C' if i == 6 else 'L'
        pdf.cell(col_widths[i], 4, header, align=align)
    
    pdf.set_y(pdf.get_y() + 6)
    
    # Table Rows
    for t in report_json['tickets']:
        start_y = pdf.get_y()
        
        # Draw row bottom border
        pdf.set_draw_color(226, 232, 240)
        pdf.line(15, start_y + 8, 195, start_y + 8)
        
        title = t['title']
        if title and len(title) > 25:
            title = title[:22] + "..."
            
        assignees = ", ".join(t['assignees'])
        if len(assignees) > 15:
            assignees = assignees[:12] + "..."
            
        t_id = str(t.get('id', '') or "")
        t_type = str(t.get('type', '') or "")
        t_status = str(t.get('status', '') or "")
        t_priority = str(t.get('priority', '') or "")
        t_sp = str(t.get('story_points', '') or "-")
        
        # Ticket ID
        pdf.set_xy(15, start_y + 2)
        pdf.set_font('helvetica', 'B', 6)
        pdf.set_text_color(99, 102, 241) # Indigo
        pdf.cell(col_widths[0], 4, safe_str(t_id))
        
        # Title
        pdf.set_xy(15 + col_widths[0], start_y + 2)
        pdf.set_font('helvetica', '', 7)
        pdf.set_text_color(15, 23, 42)
        pdf.cell(col_widths[1], 4, safe_str(title))
        
        # Type (Pill)
        x = 15 + sum(col_widths[:2])
        draw_pill(pdf, x, start_y + 1.5, pdf.get_string_width(t_type)+4, 5, t_type, bg_color=(224,242,254), text_color=(2,132,199))
        
        # Status (Pill)
        x = 15 + sum(col_widths[:3])
        draw_pill(pdf, x, start_y + 1.5, pdf.get_string_width(t_status)+4, 5, t_status, bg_color=(220,252,231), text_color=(22,163,74))
        
        # Priority (Pill)
        x = 15 + sum(col_widths[:4])
        draw_pill(pdf, x, start_y + 1.5, pdf.get_string_width(t_priority)+4, 5, t_priority, bg_color=(254,242,242), text_color=(220,38,38))
        
        # Assignees
        x = 15 + sum(col_widths[:5])
        pdf.set_xy(x, start_y + 2)
        pdf.set_font('helvetica', '', 6)
        pdf.set_text_color(15, 23, 42)
        pdf.cell(col_widths[5], 4, safe_str(assignees))
        
        # SP
        x = 15 + sum(col_widths[:6])
        pdf.set_xy(x, start_y + 2)
        pdf.cell(col_widths[6], 4, safe_str(t_sp), align='C')
        
        pdf.set_y(start_y + 8)

    pdf.output(pdf_path)

if __name__ == '__main__':
    project_json = {
        "project": {
            "key": "REP-50B3F4",
            "name": "report",
            "description": "report service related tickets",
            "owner": "SoulSync",
            "period": "May 22, 2026 - Present",
            "generated_date": "28 May 2026",
            "total_members": 2
        },
        "summary": {
            "total_tickets": 3,
            "completed_tickets": 1,
            "completion_rate": 33,
            "critical_open_count": 1,
            "critical_open_keys": ["REP-50B3F4-1"],
            "story_points_burned": 0,
            "story_points_total": 2
        },
        "status_breakdown": [{"status": "BACKLOG", "count": 2}, {"status": "DONE", "count": 1}],
        "type_split": [{"type": "TICKETTYPE.TASK", "count": 3}],
        "assignees": [
            {"name": "Tester", "role": "MEMBER", "assigned_tickets": 1, "completed_tickets": 0, "story_points": 2},
            {"name": "SoulSync", "role": "ADMIN", "assigned_tickets": 1, "completed_tickets": 1, "story_points": 0}
        ],
        "releases": [],
        "tickets": [
            {
                "id": "REP-50B3F4-1",
                "title": "Add the count of domain",
                "type": "TICKETTYPE.TASK",
                "status": "BACKLOG",
                "priority": "TICKETPRIORITY.CRITICAL",
                "assignees": ["Tester"],
                "story_points": 2
            },
            {
                "id": "REP-50B3F4-2",
                "title": "test",
                "type": "TICKETTYPE.TASK",
                "status": "DONE",
                "priority": "TICKETPRIORITY.CRITICAL",
                "assignees": ["SoulSync"],
                "story_points": None
            },
            {
                "id": "REP-50B3F4-3",
                "title": "check",
                "type": "TICKETTYPE.TASK",
                "status": "BACKLOG",
                "priority": "TICKETPRIORITY.MEDIUM",
                "assignees": [],
                "story_points": None
            }
        ]
    }
    generate_pdf_report(project_json, 'test_redesign.pdf')
    print("Done")
