"""Portrait PDF export action"""

import io
import os
from datetime import datetime

import arabic_reshaper
from bidi.algorithm import get_display
from django.http import HttpResponse
from django.utils.text import capfirst
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.platypus import Paragraph, Table

from .utils import (
    get_active_settings, hex_to_rgb, setup_font, get_logo_path,
    create_table_style, create_header_style, calculate_column_widths,
    draw_model_name, draw_exported_at,
    draw_page_number, draw_logo
)


def reshape_to_arabic(columns, font_name, font_size, queryset, max_chars_per_line, pdf_settings=None):
    """Process and reshape Arabic text if present"""
    # Create header style with larger font and bold for column headers
    header_style = create_header_style(pdf_settings, font_name, is_header=True)
    body_style = create_header_style(pdf_settings, font_name, is_header=False)

    # Process column headers - capitalize and format
    headers = []
    for column in columns:
        # Get verbose name if available, otherwise capitalize the field name
        if hasattr(queryset.model, column):
            field = queryset.model._meta.get_field(column)
            header = capfirst(field.verbose_name) if hasattr(field, 'verbose_name') else capfirst(column)
        else:
            header = capfirst(column.replace('_', ' '))
        headers.append(Paragraph(str(header), header_style))

    data = [headers]

    for obj in queryset:
        row = []
        for column in columns:
            value = str(getattr(obj, column))
            if isinstance(value, str):
                value = arabic_reshaper.reshape(value)
                value = get_display(value)
                if len(value) > max_chars_per_line:
                    lines = [value[i:i + max_chars_per_line] for i in range(0, len(value), max_chars_per_line)]
                    value = "<br/>".join(lines)
            row.append(Paragraph(str(value), body_style))
        data.append(row)
    return data


def export_to_pdf_portrait(modeladmin, request, queryset, pagesize=A4):
    """Export data to PDF in portrait orientation"""
    # Get active settings
    pdf_settings = get_active_settings()

    # Create the response object with content type as PDF
    response = HttpResponse(content_type='application/pdf')
    response[
        'Content-Disposition'] = f'attachment; filename="{modeladmin.model.__name__}_export_{datetime.now().strftime("%Y-%m-%d_%H-%M-%S")}.pdf"'
    buffer = io.BytesIO()

    # Initialize canvas with portrait orientation
    p = canvas.Canvas(buffer, pagesize=pagesize)
    canvas_width, canvas_height = pagesize

    # Use settings or defaults - optimized for portrait
    ROWS_PER_PAGE = pdf_settings.items_per_page if pdf_settings else 20  # More rows in portrait due to less width
    max_chars_per_line = pdf_settings.max_chars_per_line if pdf_settings else 40  # Less chars per line in portrait
    page_margin = (pdf_settings.page_margin_mm if pdf_settings else 15) * mm

    # Setup font and colors
    font_name = setup_font(pdf_settings)
    logo_file = get_logo_path(pdf_settings)
    header_bg_color = hex_to_rgb(pdf_settings.header_background_color) if pdf_settings else colors.lightgrey
    grid_color = hex_to_rgb(pdf_settings.grid_line_color) if pdf_settings else colors.black

    # Create table style optimized for portrait
    table_style = create_table_style(pdf_settings, font_name, header_bg_color, grid_color)

    # Calculate available space for table
    table_width = canvas_width - (2 * page_margin)
    table_height = canvas_height - (3 * page_margin)  # Leave space for header and footer

    # Prepare data
    valid_fields = [field for field in modeladmin.list_display if hasattr(modeladmin.model, field)]
    data = reshape_to_arabic(valid_fields, font_name,
                             pdf_settings.body_font_size if pdf_settings else 7,
                             queryset, max_chars_per_line, pdf_settings)

    # Calculate column widths and pages
    col_widths = calculate_column_widths(data, table_width, font_name,
                                         pdf_settings.body_font_size if pdf_settings else 7)
    total_rows = len(data) - 1
    total_pages = int((total_rows + ROWS_PER_PAGE - 1) / ROWS_PER_PAGE)

    # Define margins - optimized for portrait
    header_margin = page_margin + (10 * mm)  # Space for title
    table_top_margin = header_margin + (8 * mm)  # Start table below header
    footer_margin = page_margin + (5 * mm)

    # Draw pages
    for page in range(total_pages):
        if not pdf_settings or pdf_settings.show_header:
            draw_model_name(p, modeladmin, font_name,
                            pdf_settings.header_font_size if pdf_settings else 12,
                            canvas_width, canvas_height, header_margin)

        # Draw the table with adjusted positioning - centered
        start_row = page * ROWS_PER_PAGE
        end_row = min((page + 1) * ROWS_PER_PAGE, len(data))
        page_data = data[0:1] + data[start_row + 1:end_row]  # Include header row

        table = Table(page_data, colWidths=col_widths, style=table_style)
        table.wrapOn(p, table_width, table_height)
        table_x = (canvas_width - table_width) / 2  # Center the table
        table_y = canvas_height - table_top_margin - table._height
        table.drawOn(p, table_x, table_y)

        # Draw footer elements
        if not pdf_settings or pdf_settings.show_export_time:
            draw_exported_at(p, font_name,
                             pdf_settings.body_font_size if pdf_settings else 7,
                             canvas_width, footer_margin)

        if not pdf_settings or pdf_settings.show_page_numbers:
            draw_page_number(p, page, total_pages, font_name,
                             pdf_settings.body_font_size if pdf_settings else 7,
                             canvas_width, footer_margin)

        if (not pdf_settings or pdf_settings.show_logo) and os.path.exists(logo_file):
            draw_logo(p, logo_file, canvas_width, canvas_height)

        p.showPage()

    p.save()
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response
