from pathlib import Path
import sys

from docx import Document
from docx.enum.section import WD_SECTION
from docx.enum.table import WD_CELL_VERTICAL_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Inches, Pt, RGBColor

SKILL_DIR = Path(r"C:\Users\User\.gapcode\plugins\cache\gapgpt\documents\26.722.10000\skills\documents")
sys.path.insert(0, str(SKILL_DIR / "scripts"))
from fa_docx import add_rtl_paragraph, set_font, set_rtl_paragraph, set_rtl_styles

ROOT = Path(__file__).resolve().parents[1]
OUT = ROOT / "docs" / "CRM_Project_Structure_1405-05-22.docx"

BLUE = "0277BD"
DARK_BLUE = "01579B"
LIGHT_BLUE = "E1F5FE"
GRAY = "607D8B"
LIGHT_GRAY = "F5F9FB"
RED = "C62828"


def shade(cell, fill):
    tc_pr = cell._tc.get_or_add_tcPr()
    shd = tc_pr.find(qn("w:shd"))
    if shd is None:
        shd = OxmlElement("w:shd")
        tc_pr.append(shd)
    shd.set(qn("w:fill"), fill)


def set_cell_margins(cell, top=100, start=120, bottom=100, end=120):
    tc = cell._tc
    tc_pr = tc.get_or_add_tcPr()
    tc_mar = tc_pr.first_child_found_in("w:tcMar")
    if tc_mar is None:
        tc_mar = OxmlElement("w:tcMar")
        tc_pr.append(tc_mar)
    for margin, value in (("top", top), ("start", start), ("bottom", bottom), ("end", end)):
        node = tc_mar.find(qn(f"w:{margin}"))
        if node is None:
            node = OxmlElement(f"w:{margin}")
            tc_mar.append(node)
        node.set(qn("w:w"), str(value))
        node.set(qn("w:type"), "dxa")


def set_table_widths(table, widths):
    table.autofit = False
    tbl_pr = table._tbl.tblPr
    tbl_w = tbl_pr.find(qn("w:tblW"))
    if tbl_w is None:
        tbl_w = OxmlElement("w:tblW")
        tbl_pr.append(tbl_w)
    tbl_w.set(qn("w:w"), str(sum(widths)))
    tbl_w.set(qn("w:type"), "dxa")
    grid = table._tbl.tblGrid
    for child in list(grid):
        grid.remove(child)
    for width in widths:
        col = OxmlElement("w:gridCol")
        col.set(qn("w:w"), str(width))
        grid.append(col)
    for row in table.rows:
        for cell, width in zip(row.cells, widths):
            tc_pr = cell._tc.get_or_add_tcPr()
            tc_w = tc_pr.find(qn("w:tcW"))
            if tc_w is None:
                tc_w = OxmlElement("w:tcW")
                tc_pr.append(tc_w)
            tc_w.set(qn("w:w"), str(width))
            tc_w.set(qn("w:type"), "dxa")
            set_cell_margins(cell)
            cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER


def mark_header_row(row):
    tr_pr = row._tr.get_or_add_trPr()
    tbl_header = tr_pr.find(qn("w:tblHeader"))
    if tbl_header is None:
        tbl_header = OxmlElement("w:tblHeader")
        tr_pr.append(tbl_header)
    tbl_header.set(qn("w:val"), "true")


def set_paragraph_spacing(paragraph, before=0, after=6, line=1.15):
    fmt = paragraph.paragraph_format
    fmt.space_before = Pt(before)
    fmt.space_after = Pt(after)
    fmt.line_spacing = line


def add_text(container, text, bold=False, color=None, size=10.5, align=WD_ALIGN_PARAGRAPH.RIGHT):
    p = container.add_paragraph()
    p.alignment = align
    run = p.add_run(text)
    run.bold = bold
    if color:
        run.font.color.rgb = RGBColor.from_string(color)
    set_font(run, "Vazirmatn", size)
    set_rtl_paragraph(p, font="Vazirmatn", size=size)
    set_paragraph_spacing(p)
    return p


def add_heading(doc, text, level=1):
    p = add_rtl_paragraph(doc, text, style=f"Heading {level}", font="Vazirmatn")
    p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    color = BLUE if level < 3 else DARK_BLUE
    for run in p.runs:
        run.font.color.rgb = RGBColor.from_string(color)
        run.bold = True
        set_font(run, "Vazirmatn", {1: 16, 2: 13, 3: 11.5}[level])
    set_paragraph_spacing(p, before={1: 16, 2: 11, 3: 7}[level], after={1: 7, 2: 5, 3: 3}[level])
    return p


def add_bullet(doc, text, level=0):
    p = doc.add_paragraph(style="List Bullet")
    p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    p.paragraph_format.left_indent = Inches(0.25 + level * 0.2)
    p.paragraph_format.right_indent = Inches(0.15)
    p.paragraph_format.first_line_indent = Inches(-0.15)
    run = p.add_run(text)
    set_font(run, "Vazirmatn", 10.5)
    set_rtl_paragraph(p, font="Vazirmatn", size=10.5)
    set_paragraph_spacing(p, after=3)
    return p


def add_numbered(doc, text):
    p = doc.add_paragraph(style="List Number")
    p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    p.paragraph_format.left_indent = Inches(0.35)
    p.paragraph_format.right_indent = Inches(0.15)
    p.paragraph_format.first_line_indent = Inches(-0.2)
    run = p.add_run(text)
    set_font(run, "Vazirmatn", 10.5)
    set_rtl_paragraph(p, font="Vazirmatn", size=10.5)
    set_paragraph_spacing(p, after=4)
    return p


def add_table(doc, headers, rows, widths):
    table = doc.add_table(rows=1, cols=len(headers))
    table.style = "Table Grid"
    set_table_widths(table, widths)
    mark_header_row(table.rows[0])
    header = table.rows[0].cells
    for idx, value in enumerate(headers):
        header[idx].text = ""
        shade(header[idx], BLUE)
        p = header[idx].paragraphs[0]
        p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
        run = p.add_run(value)
        run.bold = True
        run.font.color.rgb = RGBColor(255, 255, 255)
        set_font(run, "Vazirmatn", 9.5)
        set_rtl_paragraph(p, font="Vazirmatn", size=9.5)
    for row_idx, row in enumerate(rows):
        cells = table.add_row().cells
        for idx, value in enumerate(row):
            cells[idx].text = ""
            if row_idx % 2 == 0:
                shade(cells[idx], LIGHT_GRAY)
            p = cells[idx].paragraphs[0]
            p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
            run = p.add_run(str(value))
            set_font(run, "Vazirmatn", 9.2)
            set_rtl_paragraph(p, font="Vazirmatn", size=9.2)
            set_paragraph_spacing(p, after=2)
    for row in table.rows:
        for cell in row.cells:
            set_cell_margins(cell)
            cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
    return table


def configure_styles(doc):
    set_rtl_styles(doc, font="Vazirmatn")
    normal = doc.styles["Normal"]
    normal.font.name = "Vazirmatn"
    normal.font.size = Pt(10.5)
    normal.paragraph_format.space_after = Pt(6)
    normal.paragraph_format.line_spacing = 1.15
    for name, size, color in (("Heading 1", 16, BLUE), ("Heading 2", 13, BLUE), ("Heading 3", 11.5, DARK_BLUE)):
        style = doc.styles[name]
        style.font.name = "Vazirmatn"
        style.font.size = Pt(size)
        style.font.bold = True
        style.font.color.rgb = RGBColor.from_string(color)


def configure_page(doc):
    section = doc.sections[0]
    section.page_width = Inches(8.5)
    section.page_height = Inches(11)
    section.top_margin = Inches(0.75)
    section.bottom_margin = Inches(0.75)
    section.left_margin = Inches(0.85)
    section.right_margin = Inches(0.85)
    section.header_distance = Inches(0.35)
    section.footer_distance = Inches(0.35)

    header = section.header
    hp = header.paragraphs[0]
    hp.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    hr = hp.add_run("مستند ساختار پروژه CRM آتش فراز")
    hr.font.color.rgb = RGBColor.from_string(GRAY)
    set_font(hr, "Vazirmatn", 8.5)
    set_rtl_paragraph(hp, font="Vazirmatn", size=8.5)

    footer = section.footer
    fp = footer.paragraphs[0]
    fp.alignment = WD_ALIGN_PARAGRAPH.CENTER
    fr = fp.add_run("نسخه بررسی داخلی - ۲۲ مرداد ۱۴۰۵")
    fr.font.color.rgb = RGBColor.from_string(GRAY)
    set_font(fr, "Vazirmatn", 8)
    set_rtl_paragraph(fp, font="Vazirmatn", size=8)


def build():
    doc = Document()
    configure_styles(doc)
    configure_page(doc)

    title = doc.add_paragraph()
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
    run = title.add_run("سند ساختار پروژه CRM آتش فراز")
    run.bold = True
    run.font.color.rgb = RGBColor.from_string(DARK_BLUE)
    set_font(run, "Vazirmatn", 23)
    set_rtl_paragraph(title, font="Vazirmatn", size=23)
    set_paragraph_spacing(title, after=4)

    subtitle = doc.add_paragraph()
    subtitle.alignment = WD_ALIGN_PARAGRAPH.CENTER
    sr = subtitle.add_run("وضعیت پروژه تا تاریخ ۲۲ مرداد ۱۴۰۵")
    sr.font.color.rgb = RGBColor.from_string(GRAY)
    set_font(sr, "Vazirmatn", 11)
    set_rtl_paragraph(subtitle, font="Vazirmatn", size=11)
    set_paragraph_spacing(subtitle, after=16)

    callout = doc.add_table(rows=1, cols=1)
    callout.style = "Table Grid"
    set_table_widths(callout, [9360])
    mark_header_row(callout.rows[0])
    cell = callout.cell(0, 0)
    shade(cell, LIGHT_BLUE)
    cell.text = ""
    p = cell.paragraphs[0]
    p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
    r = p.add_run("هدف سند: ارائه یک نقشه قابل چاپ از معماری فعلی، مسیر فایل‌ها، جداول، نقش‌ها، جریان‌های کاری و نقاط پیشنهادی برای ادامه توسعه.")
    r.bold = True
    r.font.color.rgb = RGBColor.from_string(DARK_BLUE)
    set_font(r, "Vazirmatn", 10.5)
    set_rtl_paragraph(p, font="Vazirmatn", size=10.5)
    set_cell_margins(cell, top=180, bottom=180)

    add_heading(doc, "۱. خلاصه وضعیت فعلی", 1)
    add_text(doc, "تا این مرحله، یک پنل مستقل و موبایل‌محور برای بازاریاب‌ها روی همان ساختار اصلی مشتریان CRM ساخته شده است. داده مشتریان در جدول اصلی customers ذخیره می‌شود و جدول موازی برای مشتریان ایجاد نشده است.")
    for text in [
        "ورود مستقل بازاریاب با session جداگانه.",
        "نمایش مشتریان اختصاص‌یافته به هر بازاریاب.",
        "ثبت مشتری پایه با شماره موبایل اجباری.",
        "انتخاب استان و شهر وابسته با AJAX.",
        "ثبت پیگیری از پروفایل مشتری.",
        "نمایش پیگیری‌های در انتظار و امکان انجام/تأیید آن‌ها.",
        "عدم امکان لغو پیگیری توسط بازاریاب.",
        "ثبت فعالیت و لاگ عملیات.",
        "نمایش تاریخ‌های کاربرپسند به شمسی و ذخیره تاریخ‌ها در دیتابیس به میلادی.",
    ]:
        add_bullet(doc, text)

    add_heading(doc, "۲. مسیرهای اصلی پروژه", 1)
    add_table(doc, ["بخش", "مسیر", "وظیفه"], [
        ("پنل اصلی مشتریان", "modules/customers/", "ثبت، ویرایش، لیست، پروفایل و پیگیری‌های مدیریتی"),
        ("پنل بازاریاب", "marketer/", "ورود، داشبورد، مشتریان من، پروفایل و پیگیری‌های اختصاصی"),
        ("ظاهر پنل بازاریاب", "assets/css/marketer-panel.css", "تم آبی، ریسپانسیو، IranSans و فرم‌ها"),
        ("رفتار AJAX پنل", "assets/js/marketer-panel.js", "ارسال فرم‌ها بدون refresh و نمایش پیام‌ها"),
        ("مهاجرت‌های CRM", "ADMIN/sql/005_crm_customer_lifecycle.sql", "وضعیت چرخه عمر، فعالیت‌ها و پیگیری‌ها"),
        ("دسترسی پنل", "ADMIN/sql/007_marketer_panel.sql", "permissionهای ورود و عملیات پنل بازاریاب"),
    ], [1900, 3300, 4160])

    add_heading(doc, "۳. فایل‌های پنل بازاریاب", 1)
    add_table(doc, ["فایل", "نقش فعلی"], [
        ("marketer/_bootstrap.php", "session، احراز دسترسی، CSRF، توابع تاریخ، برچسب‌ها و layout مشترک"),
        ("marketer/login.php", "ورود مستقل بازاریاب و اعتبارسنجی فارسی"),
        ("marketer/logout.php", "خروج و پاک‌سازی session"),
        ("marketer/index.php", "داشبورد و شمارنده پیگیری‌های باز"),
        ("marketer/customers.php", "لیست مشتریان اختصاص‌یافته و جست‌وجو"),
        ("marketer/customer.php", "پروفایل مشتری، ثبت پیگیری و مشاهده فعالیت‌ها"),
        ("marketer/customer_create.php", "ثبت مشتری پایه با استان، شهر، زون و کدپستی"),
        ("marketer/customer_process.php", "اعتبارسنجی و درج مشتری در customers"),
        ("marketer/cities.php", "API داخلی دریافت شهرهای یک استان"),
        ("marketer/followups.php", "لیست پیگیری‌های باز و دکمه انجام شد"),
        ("marketer/followup_process.php", "ثبت، انجام و لاگ پیگیری‌ها"),
    ], [3600, 5760])

    add_heading(doc, "۴. جداول اصلی دیتابیس", 1)
    add_table(doc, ["جدول", "کاربرد", "نکته مهم"], [
        ("customers", "اطلاعات اصلی مشتری", "شماره موبایل یکتا؛ visitor_id مالک فعلی مشتری است"),
        ("customer_assignments", "تاریخچه تخصیص بازاریاب", "برای جلوگیری از ثبت تکراری و نگهداری سابقه"),
        ("customer_statuses", "وضعیت CRM", "سرنخ، بالقوه، واقعی، inactive و lost"),
        ("customer_status_history", "سابقه تغییر وضعیت", "دلیل تغییر و کاربر تغییر‌دهنده ذخیره می‌شود"),
        ("customer_activities", "فعالیت‌های انجام‌شده", "تماس، بازدید، happy call، پیام و خرید"),
        ("follow_ups", "وظایف و پیگیری‌ها", "pending، done و cancelled؛ بازاریاب فقط done می‌کند"),
        ("logs", "لاگ عمومی سیستم", "ثبت ورود، ایجاد مشتری، ثبت/انجام پیگیری و تلاش‌های غیرمجاز"),
        ("users / roles / permissions", "کاربران و سطح دسترسی", "پنل بازاریاب بر اساس role visitor و permissionهای marketer است"),
    ], [2300, 3500, 3560])

    add_heading(doc, "۵. وضعیت چرخه عمر مشتری", 1)
    add_table(doc, ["وضعیت", "معنی کسب‌وکاری", "رفتار فعلی"], [
        ("lead / سرنخ", "اطلاعات اولیه قبل از ارزیابی", "قابل توسعه در مسیرهای آینده"),
        ("potential / بالقوه", "بازدید شده ولی هنوز خرید نکرده", "وضعیت پیش‌فرض ثبت از پنل بازاریاب"),
        ("customer / واقعی", "خرید انجام داده", "برای اتصال به سفارش و خرید آماده توسعه"),
        ("inactive / کم‌فعال", "در بازه‌ای خرید یا تعامل نداشته", "فعلاً دستی؛ اتوماسیون سه‌ماهه بعداً"),
        ("lost / از دست رفته", "عدم تمایل، لید اشتباه یا توقف قطعی", "با دلیل و سابقه تغییر وضعیت نگهداری می‌شود"),
    ], [1900, 3650, 3810])

    add_heading(doc, "۶. جریان کاری بازاریاب", 1)
    for text in [
        "بازاریاب وارد /marketer/login.php می‌شود.",
        "در داشبورد، مشتریان خودش و پیگیری‌های باز را می‌بیند.",
        "در بازدید حضوری، مشتری جدید را با موبایل اجباری ثبت می‌کند.",
        "استان انتخاب می‌شود و شهرهای همان استان با AJAX بارگذاری می‌شوند.",
        "مشتری به‌صورت خودکار به همان بازاریاب اختصاص داده می‌شود.",
        "بازاریاب برای مشتری از صفحه پروفایل پیگیری ثبت می‌کند.",
        "پیگیری در لیست بازاریاب نمایش داده می‌شود.",
        "بازاریاب فقط می‌تواند وظیفه را انجام‌شده کند؛ لغو در اختیار پنل مدیریتی است.",
        "با انجام پیگیری، follow_ups به done می‌رود، customer_activities ثبت می‌شود و next_follow_up_at به‌روزرسانی می‌گردد.",
    ]:
        add_numbered(doc, text)

    add_heading(doc, "۷. دسترسی‌های پنل بازاریاب", 1)
    add_table(doc, ["Permission", "کاربرد"], [
        ("marketer.panel.login", "اجازه ورود به پنل"),
        ("marketer.panel.access", "اجازه استفاده از داشبورد"),
        ("marketer.customers.view", "مشاهده مشتریان خود"),
        ("marketer.customers.create", "ثبت مشتری جدید"),
        ("marketer.followups.view", "مشاهده پیگیری‌های اختصاص‌یافته"),
        ("marketer.followups.manage", "ثبت پیگیری و انجام پیگیری"),
    ], [3500, 5860])
    add_text(doc, "قاعده مالکیت: بازاریاب فقط مشتریانی را می‌بیند و مدیریت می‌کند که visitor_id آن‌ها برابر شناسه خودش باشد. تغییر مالک مشتری باید از پنل مدیریتی انجام شود.", bold=True, color=DARK_BLUE)

    add_heading(doc, "۸. تاریخ‌ها و تقویم", 1)
    for text in [
        "نمایش تاریخ برای کاربر: شمسی با to_shamsi و to_shamsi_full.",
        "ذخیره تاریخ در دیتابیس: میلادی با to_miladi.",
        "فیلد تاریخ پیگیری: datepicker شمسی اصلی پروژه با فرمت YYYY/MM/DD HH:mm.",
        "parser سمت سرور ارقام فارسی، عربی، جداکننده | و تاریخ/ساعت را پشتیبانی می‌کند.",
    ]:
        add_bullet(doc, text)

    add_heading(doc, "۹. لاگ و حسابرسی", 1)
    add_text(doc, "برای عملیات مهم از setlog استفاده شده است. نمونه رخدادهای فعلی:")
    for text in [
        "ورود موفق یا ناموفق بازاریاب.",
        "ثبت مشتری جدید از پنل بازاریاب.",
        "ثبت پیگیری.",
        "انجام پیگیری.",
        "تلاش بازاریاب برای لغو پیگیری.",
    ]:
        add_bullet(doc, text)

    add_heading(doc, "۱۰. نکات فنی و محدودیت‌های فعلی", 1)
    for text in [
        "فعلاً ثبت مشتری پایه انجام می‌شود و فیلدهای تکمیلی فرم اصلی هنوز وارد پنل بازاریاب نشده‌اند.",
        "اتصال کامل به سفارش و تبدیل خودکار مشتری واقعی در مرحله بعد انجام می‌شود.",
        "inactive شدن خودکار بعد از سه ماه هنوز پیاده‌سازی نشده است.",
        "تغییر وضعیت CRM و تغییر بازاریاب باید از پنل مدیریتی کنترل شود.",
        "پنل بازاریاب ریسپانسیو است و برای استفاده موبایل طراحی شده است.",
    ]:
        add_bullet(doc, text)

    add_heading(doc, "۱۱. پیشنهاد اولویت ادامه پروژه", 1)
    for text in [
        "تکمیل فرم ثبت مشتری با فیلدهای تکمیلی مورد نیاز کسب‌وکار.",
        "تکمیل صفحه پروفایل مشتری بازاریاب با خلاصه وضعیت، آخرین فعالیت و پیگیری بعدی.",
        "تعریف فرآیند مشخص تغییر وضعیت از بالقوه به واقعی بعد از ثبت سفارش.",
        "اتصال ماژول سفارش به first_purchase_at و lifecycle_status_id.",
        "ساخت گزارش مدیریتی برای عملکرد بازاریاب‌ها و نرخ تبدیل.",
        "پیاده‌سازی inactive خودکار با job زمان‌بندی‌شده.",
        "تکمیل permissionهای جزئی‌تر برای مشاهده و ویرایش بخش‌های مختلف.",
    ]:
        add_numbered(doc, text)

    add_heading(doc, "۱۲. چک‌لیست بررسی و تصمیم‌گیری", 1)
    checklist = [
        "آیا وضعیت پیش‌فرض مشتری ثبت‌شده باید potential باشد؟",
        "آیا بازاریاب دفتر مجاز به انجام پیگیری مشتری بازاریاب میدانی هست؟",
        "آیا ثبت پیگیری جدید فقط از پروفایل مشتری کافی است؟",
        "چه فیلدهایی از فرم اصلی مشتری باید در پنل موبایل اجباری باشند؟",
        "چه رویدادی مشتری را از potential به customer تبدیل می‌کند؟",
        "دلیل lost شدن مشتری در چه سطحی ثبت و چه کسانی قابل مشاهده باشد؟",
        "آیا گزارش روزانه و هفتگی برای بازاریاب‌ها لازم است؟",
    ]
    for text in checklist:
        p = add_bullet(doc, "□ " + text)
        p.paragraph_format.space_after = Pt(6)

    add_heading(doc, "۱۳. جمع‌بندی", 1)
    add_text(doc, "ساختار فعلی برای شروع CRM مناسب است: مشتری در یک جدول مرکزی نگهداری می‌شود، مالکیت با visitor_id کنترل می‌شود، فعالیت و پیگیری از یکدیگر جدا هستند، و لاگ حسابرسی برای عملیات مهم وجود دارد. توسعه‌های بعدی بهتر است روی سفارش، گزارش عملکرد، اتوماسیون inactive و تکمیل فرم مشتری متمرکز شوند.")

    doc.core_properties.title = "سند ساختار پروژه CRM آتش فراز"
    doc.core_properties.subject = "ساختار پنل بازاریاب و CRM"
    doc.core_properties.author = "Atash Faraz"
    doc.save(OUT)
    print(OUT)


if __name__ == "__main__":
    build()
