#!/usr/bin/env python3
"""
Demo: Table Pagination

This example demonstrates table pagination when content exceeds page height:
- Large table that spans multiple pages
- Automatic row-level pagination (entire rows move to next page)
- Continuation markers ("continued on next page", "continued from previous page")
- Headers repeated on each page

The pagination system:
1. Renders rows sequentially until page height limit reached
2. Moves entire row to next page if it doesn't fit
3. Repeats header row on continuation pages
4. Adds visual markers to show table continues
"""

from pyWebLayout.concrete.page import Page
from pyWebLayout.concrete.table import TableRenderer, TableStyle
from pyWebLayout.style.page_style import PageStyle
from pyWebLayout.style import Font
from pyWebLayout.abstract.block import Table, TableRow, TableCell, Paragraph
from pyWebLayout.abstract.inline import Word
from PIL import Image, ImageDraw


def create_large_table():
    """Create a table with many rows that will require pagination."""
    table = Table()
    table.caption = "Employee Directory (Paginated)"

    font = Font(font_size=11)

    # Header
    header_row = TableRow()
    for text in ["ID", "Name", "Department", "Email", "Phone"]:
        cell = TableCell(is_header=True)
        para = Paragraph(font)
        para.add_word(Word(text, font))
        cell.add_block(para)
        header_row.add_cell(cell)
    table.add_row(header_row, section="header")

    # Many body rows (will span multiple pages)
    departments = ["Engineering", "Sales", "Marketing", "HR", "Finance", "Operations", "Support"]

    for i in range(60):
        row = TableRow()

        # ID
        cell = TableCell()
        para = Paragraph(font)
        para.add_word(Word(f"EMP{i+1001}", font))
        cell.add_block(para)
        row.add_cell(cell)

        # Name
        cell = TableCell()
        para = Paragraph(font)
        names = ["Alice Johnson", "Bob Smith", "Charlie Brown", "Diana Lee",
                 "Eve Wilson", "Frank Miller", "Grace Davis", "Henry Taylor"]
        para.add_word(Word(names[i % len(names)], font))
        cell.add_block(para)
        row.add_cell(cell)

        # Department
        cell = TableCell()
        para = Paragraph(font)
        para.add_word(Word(departments[i % len(departments)], font))
        cell.add_block(para)
        row.add_cell(cell)

        # Email
        cell = TableCell()
        para = Paragraph(font)
        email = f"{names[i % len(names)].lower().replace(' ', '.')}@company.com"
        para.add_word(Word(email, font))
        cell.add_block(para)
        row.add_cell(cell)

        # Phone
        cell = TableCell()
        para = Paragraph(font)
        para.add_word(Word(f"+1-555-{(i*17)%1000:04d}", font))
        cell.add_block(para)
        row.add_cell(cell)

        table.add_row(row, section="body")

    return table


def render_table_with_pagination(table, page_size, max_pages=3):
    """
    Render a table across multiple pages.

    Args:
        table: The table to render
        page_size: Tuple of (width, height) for each page
        max_pages: Maximum number of pages to render

    Returns:
        List of PIL Images (one per page)
    """
    pages = []

    page_style = PageStyle(
        border_width=1,
        padding=(20, 20, 20, 20),
        background_color=(255, 255, 255)
    )

    table_style = TableStyle(
        border_width=1,
        border_color=(100, 100, 100),
        cell_padding=(6, 8, 6, 8),
        header_bg_color=(220, 230, 240),
        cell_bg_color=(255, 255, 255),
        alternate_row_color=(248, 248, 248)
    )

    # Get all rows
    all_rows = list(table.all_rows())
    header_rows = [row for section, row in all_rows if section == "header"]
    body_rows = [row for section, row in all_rows if section == "body"]

    # Calculate header height once
    temp_page = Page(size=page_size, style=page_style)
    temp_canvas = temp_page._create_canvas()
    temp_draw = ImageDraw.Draw(temp_canvas)

    # Create temporary table with just header to measure
    header_table = Table()
    header_table.caption = table.caption
    for header_row in header_rows:
        header_table.add_row(header_row, section="header")

    header_renderer = TableRenderer(
        header_table,
        origin=(20, 20),
        available_width=page_size[0] - 40,
        draw=temp_draw,
        style=table_style,
        canvas=temp_canvas
    )
    header_height = header_renderer.height

    # Available height for body rows
    available_body_height = page_size[1] - 60 - header_height  # margins + header

    # Paginate body rows
    current_page_rows = []
    current_height = 0
    page_num = 0

    for i, body_row in enumerate(body_rows):
        if page_num >= max_pages:
            break

        # Estimate row height (simplified - actual would measure each row)
        # For this demo, assume ~30px per row
        row_height = 35

        if current_height + row_height > available_body_height and current_page_rows:
            # Render current page
            page_canvas = render_page(
                table,
                header_rows,
                current_page_rows,
                page_size,
                page_style,
                table_style,
                page_num,
                is_last=False
            )
            pages.append(page_canvas)

            # Start new page
            page_num += 1
            current_page_rows = []
            current_height = 0

        current_page_rows.append(body_row)
        current_height += row_height

    # Render final page
    if current_page_rows and page_num < max_pages:
        page_canvas = render_page(
            table,
            header_rows,
            current_page_rows,
            page_size,
            page_style,
            table_style,
            page_num,
            is_last=(i == len(body_rows) - 1)
        )
        pages.append(page_canvas)

    return pages


def render_page(table, header_rows, body_rows, page_size, page_style, table_style, page_num, is_last):
    """Render a single page with header and body rows."""
    page = Page(size=page_size, style=page_style)
    canvas = page._create_canvas()
    page._canvas = canvas
    page._draw = ImageDraw.Draw(canvas)

    # Create table for this page
    page_table = Table()
    if page_num == 0:
        page_table.caption = table.caption
    else:
        page_table.caption = f"{table.caption} (continued)"

    # Add header rows
    for header_row in header_rows:
        page_table.add_row(header_row, section="header")

    # Add body rows for this page
    for body_row in body_rows:
        page_table.add_row(body_row, section="body")

    # Render table
    renderer = TableRenderer(
        page_table,
        origin=(20, 20),
        available_width=page_size[0] - 40,
        draw=page._draw,
        style=table_style,
        canvas=canvas
    )
    renderer.render()

    # Add continuation marker at bottom
    if not is_last:
        font = Font(font_size=10)
        y_pos = page_size[1] - 30
        page._draw.text(
            (page_size[0] // 2 - 100, y_pos),
            "(continued on next page)",
            fill=(100, 100, 100),
            font=font.font
        )

    # Add page number
    page._draw.text(
        (page_size[0] // 2 - 20, page_size[1] - 15),
        f"Page {page_num + 1}",
        fill=(150, 150, 150),
        font=Font(font_size=9).font
    )

    return canvas


def main():
    # Create large table
    table = create_large_table()

    # Render with pagination (3 pages max for demo)
    page_size = (900, 700)
    pages = render_table_with_pagination(table, page_size, max_pages=3)

    # Combine pages side-by-side for visualization
    total_width = page_size[0] * len(pages) + (len(pages) - 1) * 20  # 20px spacing
    combined = Image.new('RGB', (total_width, page_size[1]), (240, 240, 240))

    x_offset = 0
    for i, page_canvas in enumerate(pages):
        combined.paste(page_canvas, (x_offset, 0))
        x_offset += page_size[0] + 20

    # Save
    output_path = "docs/images/example_13_table_pagination.png"
    combined.save(output_path)

    print(f"✓ Table pagination demo created!")
    print(f"  Output: {output_path}")
    print(f"  Pages rendered: {len(pages)}")
    print(f"  Image size: {combined.size}")
    print(f"\nDemonstrates:")
    print(f"  - Large table (60 rows) paginated across {len(pages)} pages")
    print(f"  - Header repeated on each page")
    print(f"  - Continuation markers")
    print(f"  - Page numbers")


if __name__ == "__main__":
    main()
