#!/usr/bin/env python3
"""Genera contrato de arrendamiento de montacargas en DOCX."""

from datetime import datetime, timedelta
from docx import Document
from docx.shared import Pt, Inches, Cm, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.enum.table import WD_TABLE_ALIGNMENT
from docx.oxml.ns import qn
import os

BLANK = "________________________________________"
SHORT_BLANK = "____________________"
TINY_BLANK = "__________"

def set_cell_border(cell, **kwargs):
    """Set cell borders."""
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()
    tcBorders = tcPr.find(qn('w:tcBorders'))
    if tcBorders is None:
        tcBorders = __import__('docx.oxml', fromlist=['OxmlElement']).OxmlElement('w:tcBorders')
        tcPr.append(tcBorders)

def add_paragraph(doc, text, bold=False, size=11, alignment=WD_ALIGN_PARAGRAPH.JUSTIFY,
                  space_after=Pt(6), space_before=Pt(0), font_name='Arial'):
    p = doc.add_paragraph()
    p.alignment = alignment
    p.paragraph_format.space_after = space_after
    p.paragraph_format.space_before = space_before
    run = p.add_run(text)
    run.bold = bold
    run.font.size = Pt(size)
    run.font.name = font_name
    return p

def add_mixed_paragraph(doc, parts, alignment=WD_ALIGN_PARAGRAPH.JUSTIFY,
                        space_after=Pt(6), size=11):
    """Add paragraph with mixed bold/normal runs. parts = [(text, bold), ...]"""
    p = doc.add_paragraph()
    p.alignment = alignment
    p.paragraph_format.space_after = space_after
    for text, bold in parts:
        run = p.add_run(text)
        run.bold = bold
        run.font.size = Pt(size)
        run.font.name = 'Arial'
    return p

def generate_payment_dates(start_date, count=10, interval_days=5):
    dates = []
    for i in range(count):
        dates.append(start_date + timedelta(days=i * interval_days))
    return dates

def format_date_es(dt):
    meses = {1:'enero',2:'febrero',3:'marzo',4:'abril',5:'mayo',6:'junio',
             7:'julio',8:'agosto',9:'septiembre',10:'octubre',11:'noviembre',12:'diciembre'}
    return f"{dt.day} de {meses[dt.month]} de {dt.year}"

def main():
    doc = Document()

    # Page margins
    for section in doc.sections:
        section.top_margin = Cm(2.5)
        section.bottom_margin = Cm(2.5)
        section.left_margin = Cm(2.5)
        section.right_margin = Cm(2.5)

    # ── TITLE ──
    add_paragraph(doc, "CONTRATO DE ARRENDAMIENTO DE EQUIPO",
                  bold=True, size=14, alignment=WD_ALIGN_PARAGRAPH.CENTER,
                  space_after=Pt(4))
    add_paragraph(doc, "(Montacargas)",
                  bold=False, size=11, alignment=WD_ALIGN_PARAGRAPH.CENTER,
                  space_after=Pt(18))

    # ── PROEMIO ──
    add_paragraph(doc,
        f"Contrato de arrendamiento de equipo que celebran, por una parte, "
        f"el C. {BLANK}, con domicilio en {BLANK}, "
        f"identificado con {SHORT_BLANK} número {SHORT_BLANK}, "
        f"con CURP {SHORT_BLANK}, "
        f"a quien en lo sucesivo se le denominará \"EL ARRENDADOR\"; "
        f"y por la otra parte, PROYECTOS BODE SA DE CV, representada en este acto por "
        f"el Ing. Luis Alberto Borbolla Bueno, con domicilio fiscal en "
        f"{BLANK}, "
        f"a quien en lo sucesivo se le denominará \"EL ARRENDATARIO\"; "
        f"al tenor de las siguientes:",
        size=11, space_after=Pt(12))

    # ── DECLARACIONES ──
    add_paragraph(doc, "DECLARACIONES", bold=True, size=12,
                  alignment=WD_ALIGN_PARAGRAPH.CENTER, space_after=Pt(8))

    add_mixed_paragraph(doc, [
        ("I. ", True), ("EL ARRENDADOR declara:", True)
    ], space_after=Pt(4))
    add_paragraph(doc,
        "a) Ser legítimo propietario de dos (2) montacargas con capacidad de 5,000 lbs "
        "(2.27 toneladas métricas) cada uno, descritos en la Cláusula Primera del presente contrato.",
        space_after=Pt(2))
    add_paragraph(doc,
        "b) Que los equipos se encuentran en buen estado de funcionamiento y libres de cualquier "
        "gravamen o impedimento legal para su arrendamiento.",
        space_after=Pt(2))
    add_paragraph(doc,
        "c) Que tiene plena capacidad jurídica para celebrar el presente contrato.",
        space_after=Pt(8))

    add_mixed_paragraph(doc, [
        ("II. ", True), ("EL ARRENDATARIO declara:", True)
    ], space_after=Pt(4))
    add_paragraph(doc,
        "a) Ser una sociedad legalmente constituida conforme a las leyes mexicanas.",
        space_after=Pt(2))
    add_paragraph(doc,
        "b) Que requiere el uso temporal de los equipos descritos para actividades de "
        "manejo de materiales en planta industrial.",
        space_after=Pt(2))
    add_paragraph(doc,
        "c) Que conoce las condiciones generales del equipo y las acepta.",
        space_after=Pt(12))

    add_paragraph(doc, "CLÁUSULAS", bold=True, size=12,
                  alignment=WD_ALIGN_PARAGRAPH.CENTER, space_after=Pt(10))

    # ── CLÁUSULA I: OBJETO ──
    add_paragraph(doc, "PRIMERA. — OBJETO DEL CONTRATO.", bold=True, size=11,
                  space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDADOR otorga en arrendamiento a EL ARRENDATARIO los siguientes equipos:",
        space_after=Pt(6))

    # Equipment table
    table = doc.add_table(rows=3, cols=5)
    table.alignment = WD_TABLE_ALIGNMENT.CENTER
    table.style = 'Table Grid'
    headers = ['Equipo', 'Marca / Modelo', 'No. de Serie', 'Capacidad', 'Horómetro (hrs)']
    for i, h in enumerate(headers):
        cell = table.rows[0].cells[i]
        cell.text = h
        for p in cell.paragraphs:
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER
            for run in p.runs:
                run.bold = True
                run.font.size = Pt(9)
                run.font.name = 'Arial'

    for row_idx in range(1, 3):
        table.rows[row_idx].cells[0].text = f"Montacargas {row_idx}"
        table.rows[row_idx].cells[3].text = "5,000 lbs\n(2.27 ton)"
        for col_idx in [1, 2, 4]:
            table.rows[row_idx].cells[col_idx].text = ""
        for col_idx in range(5):
            for p in table.rows[row_idx].cells[col_idx].paragraphs:
                p.alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in p.runs:
                    run.font.size = Pt(9)
                    run.font.name = 'Arial'

    doc.add_paragraph()  # spacer

    add_paragraph(doc,
        "EL ARRENDATARIO declara recibir los equipos en buen estado de funcionamiento, "
        "conforme al Acta de Entrega que ambas partes firmarán en la fecha de entrega efectiva.",
        space_after=Pt(10))

    # ── CLÁUSULA II: VIGENCIA ──
    add_paragraph(doc, "SEGUNDA. — VIGENCIA.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "El presente contrato tendrá una duración de cincuenta (50) días naturales, "
        "contados a partir de la fecha de entrega efectiva de los equipos. "
        "Al concluir el plazo, EL ARRENDATARIO devolverá los equipos sin necesidad "
        "de requerimiento judicial o extrajudicial previo.",
        space_after=Pt(10))

    # ── CLÁUSULA III: PRECIO ──
    add_paragraph(doc, "TERCERA. — PRECIO.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDATARIO se obliga a pagar a EL ARRENDADOR la cantidad de $30,000.00 "
        "(Treinta mil pesos 00/100 M.N.) mensuales por cada montacargas, equivalente a "
        "$1,000.00 (Mil pesos 00/100 M.N.) por día natural.",
        space_after=Pt(4))
    add_paragraph(doc,
        "El monto total del arrendamiento por los dos (2) equipos durante cincuenta (50) días "
        "asciende a $100,000.00 (Cien mil pesos 00/100 M.N.).",
        space_after=Pt(4))
    add_paragraph(doc,
        "Los montos señalados son cantidades netas. El presente contrato no genera "
        "obligaciones fiscales de facturación entre las partes.",
        space_after=Pt(10))

    # ── CLÁUSULA IV: FORMA DE PAGO ──
    add_paragraph(doc, "CUARTA. — FORMA DE PAGO.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "Las partes acuerdan el siguiente calendario de pagos diferidos. "
        "Los pagos se realizarán mediante transferencia electrónica a la cuenta bancaria "
        f"de EL ARRENDADOR: Banco {SHORT_BLANK}, CLABE {BLANK}.",
        space_after=Pt(6))

    # Payment schedule table
    start = datetime(2026, 5, 29)
    dates = generate_payment_dates(start, count=10, interval_days=5)

    pay_table = doc.add_table(rows=12, cols=3)
    pay_table.alignment = WD_TABLE_ALIGNMENT.CENTER
    pay_table.style = 'Table Grid'

    pay_headers = ['No. de Pago', 'Fecha', 'Monto (MXN)']
    for i, h in enumerate(pay_headers):
        cell = pay_table.rows[0].cells[i]
        cell.text = h
        for p in cell.paragraphs:
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER
            for run in p.runs:
                run.bold = True
                run.font.size = Pt(9)
                run.font.name = 'Arial'

    for idx, dt in enumerate(dates):
        row = pay_table.rows[idx + 1]
        row.cells[0].text = str(idx + 1)
        row.cells[1].text = format_date_es(dt)
        row.cells[2].text = "$10,000.00"
        for col_idx in range(3):
            for p in row.cells[col_idx].paragraphs:
                p.alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in p.runs:
                    run.font.size = Pt(9)
                    run.font.name = 'Arial'

    # Total row
    total_row = pay_table.rows[11]
    total_row.cells[0].text = ""
    total_row.cells[1].text = "TOTAL"
    total_row.cells[2].text = "$100,000.00"
    for col_idx in range(3):
        for p in total_row.cells[col_idx].paragraphs:
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER
            for run in p.runs:
                run.bold = True
                run.font.size = Pt(9)
                run.font.name = 'Arial'

    doc.add_paragraph()  # spacer

    add_paragraph(doc,
        "En caso de retraso en cualquier pago, EL ARRENDATARIO contará con un período "
        "de gracia de tres (3) días naturales. Transcurrido dicho período sin que se "
        "haya efectuado el pago, EL ARRENDADOR podrá solicitar la devolución de los equipos.",
        space_after=Pt(10))

    # ── CLÁUSULA V: ENTREGA Y DEVOLUCIÓN ──
    add_paragraph(doc, "QUINTA. — ENTREGA Y DEVOLUCIÓN.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        f"Los equipos serán entregados en el domicilio: {BLANK}, "
        "en la fecha acordada por ambas partes.",
        space_after=Pt(4))
    add_paragraph(doc,
        "Al momento de la entrega, ambas partes firmarán un Acta de Entrega que incluirá: "
        "estado general de cada equipo, lectura del horómetro, niveles de fluidos, "
        "y registro fotográfico.",
        space_after=Pt(4))
    add_paragraph(doc,
        "Al finalizar el contrato, EL ARRENDATARIO devolverá los equipos en las mismas "
        "condiciones en que los recibió, descontando el desgaste natural proporcional "
        "a las horas de uso registradas en el horómetro. Se levantará un Acta de Devolución "
        "con los mismos elementos del Acta de Entrega.",
        space_after=Pt(10))

    # ── CLÁUSULA VI: USO Y MANTENIMIENTO ──
    add_paragraph(doc, "SEXTA. — USO Y MANTENIMIENTO.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "Los equipos se destinarán exclusivamente para manejo de materiales "
        "en planta industrial. Queda prohibido subarrendar o ceder los derechos "
        "del presente contrato a terceros sin autorización escrita de EL ARRENDADOR.",
        space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDATARIO será responsable del mantenimiento operativo diario "
        "(combustible, gas LP, limpieza, lubricación básica). "
        "EL ARRENDADOR cubrirá las reparaciones mayores derivadas del desgaste "
        "natural por uso ordinario.",
        space_after=Pt(10))

    # ── CLÁUSULA VII: RESPONSABILIDAD ──
    add_paragraph(doc, "SÉPTIMA. — RESPONSABILIDAD.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDATARIO será responsable de los daños causados a los equipos por "
        "negligencia, operación incorrecta o uso fuera de las especificaciones técnicas. "
        "La responsabilidad máxima de EL ARRENDATARIO por daños al equipo estará limitada "
        "al valor justo de mercado del equipo al momento del siniestro.",
        space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDADOR será responsable por defectos ocultos o fallas mecánicas "
        "derivadas del desgaste natural previo a la entrega.",
        space_after=Pt(4))
    add_paragraph(doc,
        "Ninguna de las partes será responsable por incumplimiento derivado de "
        "caso fortuito o fuerza mayor debidamente acreditados.",
        space_after=Pt(10))

    # ── CLÁUSULA VIII: RESCISIÓN ──
    add_paragraph(doc, "OCTAVA. — RESCISIÓN.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDATARIO podrá dar por terminado el presente contrato con un aviso "
        "por escrito de al menos cinco (5) días naturales de anticipación.",
        space_after=Pt(4))
    add_paragraph(doc,
        "EL ARRENDADOR podrá dar por terminado el presente contrato con un aviso "
        "por escrito de al menos quince (15) días naturales de anticipación. "
        "EL ARRENDADOR no podrá rescindir el contrato durante operaciones activas de "
        "maniobra sin el consentimiento mutuo de ambas partes.",
        space_after=Pt(4))
    add_paragraph(doc,
        "En caso de terminación anticipada, EL ARRENDADOR reembolsará a EL ARRENDATARIO "
        "la parte proporcional de los días no utilizados, calculada a razón de $1,000.00 "
        "M.N. por día por equipo.",
        space_after=Pt(10))

    # ── CLÁUSULA IX: JURISDICCIÓN ──
    add_paragraph(doc, "NOVENA. — JURISDICCIÓN.", bold=True, size=11, space_after=Pt(4))
    add_paragraph(doc,
        "Para la interpretación y cumplimiento del presente contrato, las partes se someten "
        "a la jurisdicción de los Tribunales competentes de la ciudad de Monterrey, "
        "Nuevo León, renunciando expresamente a cualquier otro fuero que pudiera "
        "corresponderles por razón de su domicilio presente o futuro.",
        space_after=Pt(14))

    # ── FIRMAS ──
    add_paragraph(doc,
        "Leído que fue el presente contrato por ambas partes y enteradas de su contenido "
        "y alcance legal, lo firman por duplicado en la ciudad de Monterrey, Nuevo León, "
        f"a los ______ días del mes de ______________ de 2026.",
        space_after=Pt(24))

    # Signature table (no borders)
    sig_table = doc.add_table(rows=4, cols=2)
    sig_table.alignment = WD_TABLE_ALIGNMENT.CENTER

    # Remove borders
    for row in sig_table.rows:
        for cell in row.cells:
            tc = cell._tc
            tcPr = tc.get_or_add_tcPr()
            tcBorders = __import__('lxml.etree', fromlist=['SubElement'])
            from docx.oxml import OxmlElement
            borders = OxmlElement('w:tcBorders')
            for border_name in ['top', 'left', 'bottom', 'right']:
                border = OxmlElement(f'w:{border_name}')
                border.set(qn('w:val'), 'none')
                border.set(qn('w:sz'), '0')
                borders.append(border)
            tcPr.append(borders)

    # Row 0: spacer
    # Row 1: signature lines
    sig_table.rows[1].cells[0].text = "________________________________"
    sig_table.rows[1].cells[1].text = "________________________________"
    # Row 2: names
    sig_table.rows[2].cells[0].text = f"EL ARRENDADOR\nC. {SHORT_BLANK}"
    sig_table.rows[2].cells[1].text = "EL ARRENDATARIO\nIng. Luis Alberto Borbolla Bueno\nPROYECTOS BODE SA DE CV"

    for row in sig_table.rows:
        for cell in row.cells:
            for p in cell.paragraphs:
                p.alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in p.runs:
                    run.font.size = Pt(10)
                    run.font.name = 'Arial'

    doc.add_paragraph()  # spacer
    add_paragraph(doc, "TESTIGOS", bold=True, size=11,
                  alignment=WD_ALIGN_PARAGRAPH.CENTER, space_after=Pt(20))

    # Witness table
    wit_table = doc.add_table(rows=3, cols=2)
    wit_table.alignment = WD_TABLE_ALIGNMENT.CENTER

    for row in wit_table.rows:
        for cell in row.cells:
            tc = cell._tc
            tcPr = tc.get_or_add_tcPr()
            from docx.oxml import OxmlElement
            borders = OxmlElement('w:tcBorders')
            for border_name in ['top', 'left', 'bottom', 'right']:
                border = OxmlElement(f'w:{border_name}')
                border.set(qn('w:val'), 'none')
                border.set(qn('w:sz'), '0')
                borders.append(border)
            tcPr.append(borders)

    wit_table.rows[1].cells[0].text = "________________________________"
    wit_table.rows[1].cells[1].text = "________________________________"
    wit_table.rows[2].cells[0].text = f"TESTIGO 1\nNombre: {SHORT_BLANK}\nID: {SHORT_BLANK}"
    wit_table.rows[2].cells[1].text = f"TESTIGO 2\nNombre: {SHORT_BLANK}\nID: {SHORT_BLANK}"

    for row in wit_table.rows:
        for cell in row.cells:
            for p in cell.paragraphs:
                p.alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in p.runs:
                    run.font.size = Pt(10)
                    run.font.name = 'Arial'

    # Save
    out_dir = os.path.dirname(os.path.abspath(__file__))
    out_path = os.path.join(out_dir, "CONTRATO_ARRENDAMIENTO_MONTACARGAS.docx")
    doc.save(out_path)
    print(f"Contrato generado: {out_path}")
    return out_path

if __name__ == "__main__":
    main()
