import io
import re
from reportlab.lib.pagesizes import landscape, A4
from reportlab.pdfgen import canvas
from reportlab.lib.units import cm
from reportlab.lib import colors

# Templates PDF : classic (emerald), modern (foncé), minimal (épuré)
PDF_TEMPLATES = {
    "classic": {
        "main": colors.HexColor("#047857"),
        "light": colors.HexColor("#d1fae5"),
        "title_size": 16,
        "block_title_bg": True,
    },
    "modern": {
        "main": colors.HexColor("#065f46"),
        "light": colors.HexColor("#a7f3d0"),
        "title_size": 18,
        "block_title_bg": True,
    },
    "minimal": {
        "main": colors.HexColor("#374151"),
        "light": colors.HexColor("#f3f4f6"),
        "title_size": 15,
        "block_title_bg": False,
    },
}

def _get_theme(template):
    if template not in PDF_TEMPLATES:
        template = "classic"
    return PDF_TEMPLATES[template]

def _wrap(text, max_width_cm, font_name="Helvetica", font_size=9, max_lines=25):
    """Découpe le texte en lignes tenant dans max_width_cm. font_size 6 => ~5.2 chars/cm."""
    if not (text and str(text).strip()):
        return []
    text = re.sub(r'\s+', ' ', str(text).strip())
    chars_per_cm = 5.2 if font_size <= 6 else 4.2
    max_chars = max(15, int(max_width_cm * chars_per_cm))
    lines = []
    for para in text.split("\n"):
        para = re.sub(r'\s+', ' ', para).strip()
        if not para:
            continue
        words = para.split()
        current = []
        length = 0
        for w in words:
            if length + len(w) + (1 if current else 0) <= max_chars:
                current.append(w)
                length += len(w) + (1 if current else 0)
            else:
                if current:
                    lines.append(" ".join(current))
                current = [w]
                length = len(w)
        if current:
            lines.append(" ".join(current))
    return lines[:max_lines]


def _wrap_bmc(text, width_cm, max_lines=60):
    """Wrap pour BMC (design app) : police 6, plus de lignes, pas de coupure de mots."""
    return _wrap(text, width_cm, font_size=6, max_lines=max_lines)

# Design Sénégal Academy (fond sombre, comme l'app)
BG_PAGE = colors.HexColor("#0f172a")       # slate-900
BG_BLOCK = colors.HexColor("#1e293b")      # slate-800
BG_BLOCK_ACCENT = colors.HexColor("#065f46")  # emerald-900 (bloc central)
BORDER_EMERALD = colors.HexColor("#047857")
TEXT_WHITE = colors.HexColor("#f8fafc")
TEXT_MUTED = colors.HexColor("#cbd5e1")
BADGE_EMERALD = colors.HexColor("#10b981")


def _draw_circle(p, cx, cy, r, fill_color, stroke_color=None):
    p.setFillColor(fill_color)
    if stroke_color:
        p.setStrokeColor(stroke_color)
        p.setLineWidth(0.5)
    p.circle(cx, cy, r)
    if stroke_color:
        p.setStrokeColor(colors.black)


def _draw_block(p, x, y, w, h, title, content, title_bg=None, use_title_bg=True, block_num=None, max_lines=None):
    """Dessine un bloc BMC : cadre, bandeau titre, contenu wrappé (tout le contenu, pas de coupure)."""
    p.setStrokeColor(BORDER_EMERALD)
    p.setLineWidth(0.6)
    p.setFillColor(BG_BLOCK)
    p.rect(x, y, w, h, fill=1, stroke=1)
    title_h = 0.65 * cm
    if use_title_bg and title_bg:
        p.setFillColor(BG_BLOCK_ACCENT)
        p.rect(x, y + h - title_h, w, title_h, fill=1, stroke=0)
    badge_x = x + 0.32 * cm
    badge_y = y + h - title_h / 2 - 0.05 * cm
    _draw_circle(p, badge_x, badge_y, 0.2 * cm, BADGE_EMERALD, BORDER_EMERALD)
    p.setFillColor(TEXT_WHITE)
    p.setFont("Helvetica-Bold", 8)
    if block_num is not None:
        p.drawCentredString(badge_x, badge_y - 0.08 * cm, str(block_num))
    p.setFont("Helvetica-Bold", 7)
    p.setFillColor(TEXT_WHITE)
    title_start = x + 0.85 * cm if block_num is not None else x + 0.2 * cm
    p.drawString(title_start, y + h - title_h + 0.2 * cm, title[:42])
    # Contenu : wrap selon la largeur du bloc, police 6, hauteur adaptée (autant de lignes qu'il tient)
    width_cm = (w - 0.5 * cm) / cm
    content_height = h - title_h - 0.25 * cm
    line_height_cm = 0.24
    max_lines_block = max(10, int(content_height / cm / line_height_cm))
    lines = _wrap_bmc(content or "—", width_cm, max_lines=max_lines_block)
    p.setFont("Helvetica", 6)
    p.setFillColor(TEXT_MUTED)
    content_y = y + h - title_h - 0.22 * cm
    for line in lines:
        if content_y <= y + 0.28 * cm:
            break
        # Afficher la ligne complète (déjà wrappée par _wrap_bmc, pas de troncature)
        p.drawString(x + 0.25 * cm, content_y, line)
        content_y -= line_height_cm * cm
    p.setFillColor(TEXT_WHITE)


def _draw_block_legacy(p, x, y, w, h, title, content, title_bg=None, use_title_bg=True, block_num=None):
    """Ancien style (fond blanc) pour templates modern/minimal."""
    p.setStrokeColor(colors.black)
    p.setLineWidth(0.8)
    p.rect(x, y, w, h)
    title_h = 0.6 * cm
    if use_title_bg and title_bg:
        p.setFillColor(title_bg)
        p.rect(x, y + h - title_h, w, title_h)
    p.setFillColor(colors.black)
    p.setFont("Helvetica-Bold", 9)
    p.drawString(x + 0.15 * cm, y + h - title_h + 0.2 * cm, title[:40])
    lines = _wrap(content or "—", (w - 0.4 * cm) / cm)
    p.setFont("Helvetica", 8)
    content_y = y + h - title_h - 0.35 * cm
    for line in lines:
        if content_y <= y + 0.3 * cm:
            break
        p.drawString(x + 0.2 * cm, content_y, line[:80])
        content_y -= 0.35 * cm
    p.setFillColor(colors.black)

def generate_bmc_pdf_file(bmc_data, template="classic"):
    """
    Génère le PDF du Business Model Canvas (A4 paysage), 9 blocs numérotés.
    template classic = design app (fond sombre, blocs 1-9, icônes). modern/minimal = style clair.
    """
    use_app_design = template == "classic"
    theme = _get_theme(template)
    use_bg = theme.get("block_title_bg", True)
    title_bg = theme["light"] if use_bg else None

    buffer = io.BytesIO()
    p = canvas.Canvas(buffer, pagesize=landscape(A4))
    width, height = landscape(A4)
    margin = 0.8 * cm
    y_start = height - 2.2 * cm
    block_h = 5.2 * cm
    col_w = (width - 2 * margin) / 5
    half_h = block_h / 2

    # Fond page (design app)
    if use_app_design:
        p.setFillColor(BG_PAGE)
        p.rect(0, 0, width, height, fill=1, stroke=0)

    # En-tête
    if use_app_design:
        p.setFont("Helvetica-Bold", 18)
        p.setFillColor(TEXT_WHITE)
        p.drawString(margin, height - 1.5 * cm, "BUSINESS MODEL CANVAS")
        p.setFont("Helvetica", 10)
        p.setFillColor(TEXT_MUTED)
        name = getattr(bmc_data.entrepreneur, "first_name", "") or getattr(bmc_data.entrepreneur, "email", "")
        p.drawString(width - margin - 8 * cm, height - 1.5 * cm, f"Document — {name}")
        p.setFillColor(TEXT_WHITE)
    else:
        p.setFont("Helvetica-Bold", theme.get("title_size", 16))
        p.setFillColor(theme["main"])
        p.drawString(margin, height - 1.5 * cm, "BUSINESS MODEL CANVAS")
        p.setFont("Helvetica", 10)
        p.setFillColor(colors.grey)
        name = getattr(bmc_data.entrepreneur, "first_name", "") or getattr(bmc_data.entrepreneur, "email", "")
        p.drawString(width - margin - 8 * cm, height - 1.5 * cm, f"Document — {name}")
        p.setFillColor(colors.black)

    y_top = y_start - block_h
    draw_blk = _draw_block if use_app_design else _draw_block_legacy
    def _opt(n): return (title_bg, use_bg) if not use_app_design else (None, True)
    def _num(n): return n if use_app_design else None

    draw_blk(p, margin, y_top, col_w, block_h, "Partenaires Clés", getattr(bmc_data, "key_partners", None), title_bg=_opt(1)[0], use_title_bg=_opt(1)[1], block_num=_num(1))
    draw_blk(p, margin + col_w, y_start - half_h, col_w, half_h, "Activités Clés", getattr(bmc_data, "key_activities", None), title_bg=_opt(2)[0], use_title_bg=_opt(2)[1], block_num=_num(2))
    draw_blk(p, margin + col_w, y_top, col_w, half_h, "Ressources Clés", getattr(bmc_data, "key_resources", None), title_bg=_opt(3)[0], use_title_bg=_opt(3)[1], block_num=_num(3))
    draw_blk(p, margin + 2 * col_w, y_top, col_w, block_h, "Proposition de Valeur", getattr(bmc_data, "value_proposition", None), title_bg=_opt(4)[0], use_title_bg=_opt(4)[1], block_num=_num(4))
    draw_blk(p, margin + 3 * col_w, y_start - half_h, col_w, half_h, "Relation Client", getattr(bmc_data, "customer_relationships", None), title_bg=_opt(5)[0], use_title_bg=_opt(5)[1], block_num=_num(5))
    draw_blk(p, margin + 3 * col_w, y_top, col_w, half_h, "Canaux", getattr(bmc_data, "channels", None), title_bg=_opt(6)[0], use_title_bg=_opt(6)[1], block_num=_num(6))
    draw_blk(p, margin + 4 * col_w, y_top, col_w, block_h, "Segments Clients", getattr(bmc_data, "customer_segments", None), title_bg=_opt(7)[0], use_title_bg=_opt(7)[1], block_num=_num(7))

    bottom_h = 4.5 * cm
    y_bottom = y_top - bottom_h
    cost_w = (width - 2 * margin) / 2 - 0.2 * cm
    draw_blk(p, margin, y_bottom, cost_w, bottom_h, "Structure de Coûts", getattr(bmc_data, "cost_structure", None), title_bg=_opt(8)[0], use_title_bg=_opt(8)[1], block_num=_num(8))
    draw_blk(p, margin + cost_w + 0.2 * cm, y_bottom, cost_w, bottom_h, "Flux de Revenus", getattr(bmc_data, "revenue_streams", None), title_bg=_opt(9)[0], use_title_bg=_opt(9)[1], block_num=_num(9))

    # Pied de page
    p.setFont("Helvetica", 8)
    if use_app_design:
        p.setFillColor(TEXT_MUTED)
    else:
        p.setFillColor(colors.grey)
    p.drawString(margin, margin - 0.3 * cm, "Sénégal Academy — Business Model Canvas")
    p.drawRightString(width - margin, margin - 0.3 * cm, "1/1")
    p.setFillColor(colors.black)

    p.showPage()
    p.save()
    buffer.seek(0)
    return buffer

def _wrap_pitch(text, max_width_cm=16):
    """Retourne une liste de lignes pour affichage PDF pitch."""
    if not (text and str(text).strip()):
        return []
    text = re.sub(r'\s+', ' ', str(text).strip())
    max_chars = max(40, int(max_width_cm * 4.2))
    lines = []
    for para in text.split("\n"):
        para = re.sub(r'\s+', ' ', para).strip()
        if not para:
            continue
        words = para.split()
        current, length = [], 0
        for w in words:
            if length + len(w) + (1 if current else 0) <= max_chars:
                current.append(w)
                length += len(w) + (1 if current else 0)
            else:
                if current:
                    lines.append(" ".join(current))
                current, length = [w], len(w)
        if current:
            lines.append(" ".join(current))
    return lines[:40]


def generate_pitch_pdf_file(pitch_data, template="classic"):
    """
    Génère le PDF du Pitch Deck (PItchcomplet.md) : 13 pages.
    template classic = design app (fond sombre, texte blanc). modern/minimal = style clair.
    """
    theme = _get_theme(template)
    use_app_design = template == "classic"
    title_size = 22 if template == "modern" else 20 if template == "classic" else 18

    buffer = io.BytesIO()
    width, height = landscape(A4)
    p = canvas.Canvas(buffer, pagesize=landscape(A4))
    margin = 1.5 * cm
    y_top = height - margin
    line_height = 0.5 * cm

    def _slide_bg():
        if use_app_design:
            p.setFillColor(BG_PAGE)
            p.rect(0, 0, width, height, fill=1, stroke=0)

    def _slide_title(title, subtitle=None):
        if use_app_design:
            p.setFont("Helvetica-Bold", title_size)
            p.setFillColor(TEXT_WHITE)
            p.drawCentredString(width / 2, y_top - 0.8 * cm, title[:80])
            if subtitle:
                p.setFont("Helvetica", 11)
                p.setFillColor(TEXT_MUTED)
                p.drawCentredString(width / 2, y_top - 1.4 * cm, subtitle[:100])
            p.setFillColor(TEXT_WHITE)
        else:
            p.setFont("Helvetica-Bold", title_size)
            p.setFillColor(theme["main"])
            p.drawCentredString(width / 2, y_top - 0.8 * cm, title[:80])
            if subtitle:
                p.setFont("Helvetica", 11)
                p.setFillColor(colors.grey)
                p.drawCentredString(width / 2, y_top - 1.4 * cm, subtitle[:100])
            p.setFillColor(colors.black)

    def _slide_content(content, x=margin, w=(width - 2 * margin)):
        if content is None or (isinstance(content, str) and not content.strip()):
            return
        lines = _wrap_pitch(str(content), w / cm)
        p.setFont("Helvetica", 11)
        p.setFillColor(TEXT_MUTED if use_app_design else colors.black)
        y = y_top - 2.2 * cm
        for line in lines:
            if y < margin + line_height:
                break
            p.drawString(x, y, line[:120])
            y -= line_height
        if use_app_design:
            p.setFillColor(TEXT_WHITE)

    # Page 1 : Titre et promoteur
    _slide_bg()
    _slide_title(getattr(pitch_data, "project_name", "") or "Pitch Deck", "Présentation")
    _slide_content(getattr(pitch_data, "promoter_presentation", "") or getattr(pitch_data, "tagline", ""))
    p.setFont("Helvetica", 8)
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 2 : Description du projet
    _slide_bg()
    _slide_title("Description du projet")
    _slide_content(getattr(pitch_data, "project_description", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 3 : Problème
    _slide_bg()
    _slide_title("Quel problème votre projet cherche-t-il à résoudre ?")
    _slide_content(getattr(pitch_data, "problem", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    _slide_bg()
    _slide_title("Quelle solution innovante ou valeur ajoutée votre projet propose-t-il ?")
    _slide_content(getattr(pitch_data, "solution", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    _slide_bg()
    _slide_title("Les clients potentiels")
    _slide_content(getattr(pitch_data, "market_potential", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    _slide_bg()
    _slide_title("Modèle économique")
    _slide_content(getattr(pitch_data, "business_model", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    _slide_bg()
    _slide_title("Vos réalisations (en écrit)")
    _slide_content(getattr(pitch_data, "achievements_text", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    _slide_bg()
    _slide_title("Vos réalisations (en image)")
    try:
        images_attr = getattr(pitch_data, "images", None)
        images = list(images_attr.all()[:6]) if images_attr is not None else []
    except Exception:
        images = []
    y = y_top - 2 * cm
    p.setFont("Helvetica", 10)
    p.setFillColor(TEXT_MUTED if use_app_design else colors.black)
    for img in images:
        cap = getattr(img, "caption", None) or "Image de réalisation"
        p.drawString(margin, y, str(cap)[:80])
        y -= line_height
    if not images:
        p.drawString(margin, y_top - 2.5 * cm, "— Aucune image ajoutée —")
    p.setFont("Helvetica", 8)
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 9 : Prochaines étapes
    _slide_bg()
    _slide_title("Vos prochaines étapes")
    _slide_content(getattr(pitch_data, "roadmap", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 10 : Vos besoins
    _slide_bg()
    _slide_title("Vos besoins")
    _slide_content(getattr(pitch_data, "needs", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 11 : Vision 5 ans
    _slide_bg()
    _slide_title("Votre vision d'ici 5 ans")
    _slide_content(getattr(pitch_data, "vision_5_years", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 12 : Dernier mot
    _slide_bg()
    _slide_title("Un dernier mot pour convaincre le jury ou l'audience ?")
    _slide_content(getattr(pitch_data, "final_pitch", ""))
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    # Page 13 : Remerciements
    _slide_bg()
    p.setFont("Helvetica-Bold", 22)
    p.setFillColor(BADGE_EMERALD if use_app_design else theme["main"])
    p.drawCentredString(width / 2, height / 2, "Merci de votre aimable attention")
    p.setFont("Helvetica", 12)
    p.setFillColor(TEXT_MUTED if use_app_design else colors.grey)
    p.drawCentredString(width / 2, height / 2 - 1.2 * cm, "Invitation aux questions du jury")
    p.setFont("Helvetica", 8)
    p.drawString(margin, margin, "Sénégal Academy — Pitch Deck")
    p.showPage()

    p.save()
    buffer.seek(0)
    return buffer