import os
import csv
import json
import itertools
from datetime import datetime
from flask import Flask, render_template, request, redirect, url_for, send_file

# وارد کردن ماژول‌های پروژه
from modules.segmenter import Segmenter
from modules.api_handler import APIHandler
from modules.data_manager import DataManager
from modules.visualizer import Visualizer

app = Flask(__name__)

# مقداردهی اولیه ماژول‌ها
segmenter = Segmenter()
api_handler = APIHandler()
data_manager = DataManager()
visualizer = Visualizer()


@app.route('/', methods=['GET'])
def index():
    """نمایش لیست پروژه‌های قبلی در داشبورد"""
    projects_dir = data_manager.base_projects_dir
    projects = []
    if os.path.exists(projects_dir):
        projects = [d for d in os.listdir(projects_dir) if os.path.isdir(os.path.join(projects_dir, d))]
        projects.sort(reverse=True)
    return render_template('index.html', projects=projects)


@app.route('/new_project', methods=['GET'])
def new_project():
    """فرم دریافت متن جدید"""
    return render_template('new_project.html')


@app.route('/process', methods=['POST'])
def process_text():
    """اجرای الگوریتم پایین به بالا و ساخت درخت با یک ریشه کلان (ROOT)"""
    text = request.form.get('text')
    target_count = int(request.form.get('target_segments', 7))

    if not text:
        return redirect(url_for('new_project'))

    project_name = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    project_path = data_manager.create_project_folder(project_name)

    # مرحله ۱: استخراج جملات خام اولیه
    sentences = segmenter.extract_sentences(text)

    tree_data_list = []
    current_level_items = []

    for i, s in enumerate(sentences):
        node_id = f"node_L0_{i}"
        current_level_items.append({"id": node_id, "text": s})
        tree_data_list.append({
            "level": 0,
            "segment_id": node_id,
            "parent_segment_id": "",
            "original_sentences": [s],
            "semantic_unit": s
        })

    level = 1
    global_node_counter = 1

    # مرحله ۲: سگمنت‌بندی بازگشتی تا رسیدن به تعداد هدف (مثلا 7 سگمنت)
    while len(current_level_items) > target_count:
        texts_to_segment = [item["text"] for item in current_level_items]

        # سگمنت‌بندی داینامیک
        grouped_segments_texts = segmenter.segment_items(texts_to_segment)

        # جلوگیری از پرش ناگهانی: اگر تعداد سگمنت‌ها کمتر از هدف شد، آن را وادار کن دقیقاً به اندازه هدف برش بزند
        if len(grouped_segments_texts) <= target_count:
            grouped_segments_texts = segmenter.segment_items(texts_to_segment, force_count=target_count)

        next_level_items = []
        pointer = 0

        for group in grouped_segments_texts:
            parent_node_id = f"node_L{level}_{global_node_counter}"
            global_node_counter += 1

            children_ids = []
            segment_content = []

            for _ in group:
                child = current_level_items[pointer]
                children_ids.append(child["id"])
                segment_content.append(child["text"])

                # ثبت آیدی پدر برای نودهای فرزند
                for entry in tree_data_list:
                    if entry["segment_id"] == child["id"]:
                        entry["parent_segment_id"] = parent_node_id
                pointer += 1

            # استخراج واحد معنایی
            semantic_unit = api_handler.get_semantic_unit(segment_content)

            next_level_items.append({"id": parent_node_id, "text": semantic_unit})
            tree_data_list.append({
                "level": level,
                "segment_id": parent_node_id,
                "parent_segment_id": "",
                "original_sentences": segment_content,
                "semantic_unit": semantic_unit
            })

        current_level_items = next_level_items
        level += 1

    # =========================================================================
    # مرحله ۳: ساخت ریشه نهایی (ROOT) برای کل متن
    # اتصال تمامی سگمنت‌های نهایی (مثلا 7 تا) به یک رأس کلی و گرفتن معنای کلان
    # =========================================================================
    if len(current_level_items) > 1:
        root_node_id = f"node_L{level}_ROOT"
        root_content = []

        for item in current_level_items:
            root_content.append(item["text"])

            for entry in tree_data_list:
                if entry["segment_id"] == item["id"]:
                    entry["parent_segment_id"] = root_node_id

        # ارسال کل 7 واحد معنایی به API برای دریافت غایت نهایی متن
        root_semantic_unit = api_handler.get_semantic_unit(root_content)

        tree_data_list.append({
            "level": level,
            "segment_id": root_node_id,
            "parent_segment_id": "",  # این نود پدر ندارد
            "original_sentences": root_content,
            "semantic_unit": root_semantic_unit
        })

    # ذخیره‌سازی داده‌های درخت و رسم آن
    data_manager.save_tree_data(project_path, tree_data_list)
    tree_html_path = os.path.join(project_path, "tree_visualization.html")
    visualizer.build_tree(tree_data_list, tree_html_path)

    return redirect(url_for('show_tree', project_name=project_name))


@app.route('/tree/<project_name>')
def show_tree(project_name):
    """نمایش صفحه وب حاوی درخت سلسله‌مراتبی"""
    return render_template('tree_view.html', project_name=project_name)


@app.route('/tree_iframe/<project_name>')
def tree_iframe(project_name):
    """سرو کردن فایل HTML درخت برای نمایش در iframe"""
    project_path = os.path.join(data_manager.base_projects_dir, project_name)
    tree_html_path = os.path.join(project_path, "tree_visualization.html")
    return send_file(tree_html_path)


@app.route('/graph/<project_name>/<node_id>')
def generate_and_show_graph(project_name, node_id):
    """ساخت گراف On-Demand در زمان کلیک روی نود (حتی نود ROOT)"""
    project_path = os.path.join(data_manager.base_projects_dir, project_name)
    graph_dir = os.path.join(project_path, f"{node_id}_graph")
    graph_html_path = os.path.join(graph_dir, "graph.html")

    # اگر از قبل ساخته شده بود، مجدداً پردازش نکن
    if os.path.exists(graph_html_path):
        return render_template('graph_view.html', project_name=project_name, node_id=node_id)

    # خواندن جملات نود از CSV
    node_sentences = []
    tree_csv = os.path.join(project_path, "tree_data.csv")
    with open(tree_csv, mode='r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        for row in reader:
            if row["segment_id"] == node_id:
                node_sentences = json.loads(row["original_sentences"])
                break

    if not node_sentences:
        return "خطا: دیتای نود یافت نشد.", 404

    # ۱. استخراج گزاره‌ها از API
    raw_props = api_handler.extract_propositions(node_sentences)
    propositions = [
        {"proposition_id": i + 1, "sentence": " ".join(node_sentences), "proposition_text": p}
        for i, p in enumerate(raw_props)
    ]

    # ۲. بررسی تمام روابط دو به دو بین گزاره‌ها
    relations = []
    scores = []
    rel_id_counter = 1

    for p1, p2 in itertools.combinations(propositions, 2):
        rel_desc = api_handler.check_relation(p1["proposition_text"], p2["proposition_text"])

        if rel_desc and "ارتباط وجود ندارد" not in rel_desc:
            score = api_handler.score_relation(rel_desc)
            if score > 0:
                relations.append({
                    "relation_id": rel_id_counter,
                    "source_proposition_id": p1["proposition_id"],
                    "target_proposition_id": p2["proposition_id"],
                    "relation_type": rel_desc
                })
                scores.append({
                    "relation_id": rel_id_counter,
                    "score": score
                })
                rel_id_counter += 1

    # ۳. ذخیره و رسم گراف
    data_manager.save_graph_data(project_path, node_id, propositions, relations, scores)
    visualizer.build_graph(propositions, relations, scores, graph_html_path)

    return render_template('graph_view.html', project_name=project_name, node_id=node_id)


@app.route('/graph_iframe/<project_name>/<node_id>')
def graph_iframe(project_name, node_id):
    """سرو کردن فایل HTML گراف برای نمایش در iframe"""
    project_path = os.path.join(data_manager.base_projects_dir, project_name)
    graph_html_path = os.path.join(project_path, f"{node_id}_graph", "graph.html")
    return send_file(graph_html_path)


if __name__ == '__main__':
    for folder in ["projects", "templates", "static"]:
        if not os.path.exists(folder):
            os.makedirs(folder)
    app.run(debug=True, port=5000)