import json
import os

import pandas as pd
from flask import (
    Blueprint,
    current_app,
    flash,
    redirect,
    render_template,
    request,
    url_for,
)
from flask_login import current_user, login_required
from sqlalchemy import select
from werkzeug.utils import secure_filename

from web_application import db
from web_application.constants import (
    AI_TOOLS_DICT,
    ALLOWED_EXTENSIONS,
    CASE_TYPES,
    EXCEL_REPORTS,
    POSTS_PER_PAGE,
    UPLOAD_FOLDER,
)
from web_application.helpers.patoloji_helper import ai_engine
from web_application.models import AIAssessment, DrAssessment, Image, Patient
from web_application.site.main.forms import DrAssessmentForm

main = Blueprint(
    "main",
    __name__,
    template_folder="templates",
    static_folder="static",
)


# Image Upload Functions
if not os.path.exists(UPLOAD_FOLDER):
    os.makedirs(UPLOAD_FOLDER)


def allowed_files(filename):
    """It only checks files with permitted extensions."""
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS


def check_var_yok(text):
    if text == "var":
        return 1
    else:
        return 0


@main.route("/")
@main.route("/index")
@main.route("/home")
# @login_required
def home():
    if not current_user.is_authenticated:
        return redirect(url_for("user.login"))
    if current_user.get_role() == "guest":
        return redirect(url_for("main.guest_home"))
    page = request.args.get("page", 1, type=int)
    status = 0
    status = request.args.get(
        "status", 0, type=int
    )  # 0: all, 1: Pending, 2: AI Prediction, 3: Completed
    if status == 1:
        stmt = select(Patient).order_by(Patient.id.desc()).where(Patient.status == 1)
    elif status == 2:
        stmt = select(Patient).order_by(Patient.id.desc()).where(Patient.status == 2)
    elif status == 3:
        stmt = select(Patient).order_by(Patient.id.desc()).where(Patient.status == 3)
    else:
        stmt = select(Patient).order_by(Patient.id.desc())

    data = {
        "title": "Vakalar",
        "status": status,
        "patients": db.paginate(
            stmt,
            page=page,
            per_page=POSTS_PER_PAGE,
            error_out=False,  # Set to True to raise 404 on invalid page numbers
        ),
    }
    return render_template("main/home.html", **data)


@main.route("/guest")
@login_required
def guest_home():
    """Ana sayfa: Klasör yükleme formunu gösterir."""
    return render_template("main/home_guest.html")


@main.route("/create-patient")
@login_required
def patient_create():
    """Ana sayfa: Klasör yükleme formunu gösterir."""
    return render_template("main/patient_create.html")


@main.route("/upload", methods=["POST"])
def upload_files():
    """Performs the file upload process."""
    # 'file[]' ismindeki tüm dosyaları al (HTML'deki input'tan geliyor)
    uploaded_files = request.files.getlist("file[]")

    if not uploaded_files or (
        uploaded_files[0].filename == ""
        and uploaded_files[0].content_type == "application/octet-stream"
    ):
        flash("Lütfen yüklenecek bir klasör veya dosya seçin.", "error")
        return redirect(url_for("main.home"))

    for file in uploaded_files:
        # Eğer dosya boşsa (örneğin bazı tarayıcılarda boş girdiler gelebilir)
        # herhangi bir işlem yapmadan diğer dosyaya geçer.
        if file.filename == "" and file.content_type == "application/octet-stream":
            continue

        # sadece izin verilern dosya uzantılarını yükle
        if not allowed_files(file.filename):
            flash(
                f"'{file.filename}' dosyası izin verilmeyen bir uzantıda olduğu için yükleme yapılamadı.",
                "danger",
            )
            continue

        # Klasör yapısı bilgisini al (webkitRelativePath ile)
        # Bu bilgi, klasör yapısını korumak için kritik öneme sahiptir.
        # Eğer bu bilgi yoksa, sadece dosya adını kullanırız.
        relative_path = getattr(file, "webkitRelativePath", file.filename)

        # 1.  Path'i parçalara ayır
        # 'ana_klasor/alt_klasor/resim.jpg' -> ['ana_klasor', 'alt_klasor', 'resim.jpg']
        path_parts = relative_path.split("/")  # "/" yerine os.sep kullanılabilir

        # Klasör adını ve dosya adını güvenli hale getir
        if len(path_parts) > 1:
            # Dosya adı hariç klasör yolunu al (örneğin: 'ana_klasor/alt_klasor')
            # ben sadece 'alt_klasör' adını almak istiyorum bu yüzden path_parts[1:-1]
            sub_dir_parts = [secure_filename(p) for p in path_parts[1:-1]]
            # Yükleme klasörü içinde yeni klasör yolunu oluştur
            target_directory = os.path.join(UPLOAD_FOLDER, *sub_dir_parts)
            # Güvenli dosya adını al
            filename = secure_filename(path_parts[-1])
        else:
            # Klasör yapısı bilgisi yoksa
            target_directory = UPLOAD_FOLDER
            filename = secure_filename(file.filename)

        # 2. Klasör Yapısını Oluşturur (Eğer zaten yoksa)
        if not os.path.exists(target_directory):
            try:
                os.makedirs(target_directory)
            except Exception as e:
                flash(f"Klasör oluşturulamadı: {e}", "danger")
                continue

        # 3. Dosyayı yükle
        final_path = os.path.join(target_directory, filename)
        file.save(final_path)

        # 4. Parent Klasör Bilgisini Kaydet
        parent_folder = os.path.relpath(target_directory, UPLOAD_FOLDER)

        if parent_folder == ".":
            parent_folder = "Kök Dizin"  # Eğer dosya doğrudan yüklenmişse

        # Veri tabanında bu vakanın var olup olmadığını kontrol et
        stmt = select(Patient).where(Patient.case_dir == parent_folder)
        patient = db.session.execute(stmt).scalars().first()

        if patient is None:
            case_type = CASE_TYPES[parent_folder[0]]
            patient = Patient(
                user_id=current_user.id, case_type=case_type, case_dir=parent_folder
            )
            db.session.add(patient)
            db.session.commit()

        new_image = Image(filename=filename, patient_id=patient.id)
        db.session.add(new_image)
        db.session.commit()

    flash("Dosyalar yüklendi.", "success")
    return redirect(url_for("main.home"))


@main.route("/patient/<int:patient_id>/detail")
@login_required
def patient_detail(patient_id):
    stmt = select(Patient).where(Patient.id == patient_id)
    patient = db.session.execute(stmt).scalars().first()
    if patient:
        data = {
            "title": f"Vaka {patient.case_dir}",
            "patient": patient,
            "images": patient.get_images(),
        }
        return render_template("main/patient_detail.html", **data)
    else:
        flash("Vaka bulunamadı.", "danger")
        return redirect(url_for("main.home"))


@main.route("/patient/<int:patient_id>/wait-for-ai-prediction")
@login_required
def patient_wait_for_ai_prediction(patient_id):
    data = {
        "title": f"Vaka {patient_id} için yapay zeka tahmini bekleniyor...",
        "patient_id": patient_id,
    }
    return render_template("main/patient_wait_for_ai_prediction.html", **data)


@main.route("/patient/ai/evaluation", methods=["POST"])
@login_required
def patient_ai_evaluation():
    if request.method == "GET":
        return {"message": "Bu endpoint sadece POST isteklerini kabul eder."}
    else:
        requested_data = json.loads(request.data)
        patient_id = int(requested_data["patient_id"])
        provider = requested_data["provider"]

        stmt = select(Patient).where(Patient.id == patient_id)
        patient = db.session.execute(stmt).scalars().first()
        images = [
            os.path.join(
                current_app.root_path,
                "static",
                "uploads",
                "diagnosis_images",
                patient.case_dir,
                image.filename,
            )
            for image in patient.get_images()
        ][:9]
        if len(images) < 9:
            return {
                "Hata": "Yeterli sayıda görüntü bulunamadı. En az 9 görüntü gereklidir."
            }
        else:
            print("checkpoint 1")

            received_data = ai_engine(provider=provider, image_paths=images)

            llm_name = AI_TOOLS_DICT[received_data["llm"]]

            ai_assessment = AIAssessment(patient_id=patient_id, ai_name=llm_name)
            ai_assessment.pnx_exists = check_var_yok(received_data["pnx"]["var_yok"])
            ai_assessment.pnx_loc = received_data["pnx"]["lokasyon"]
            ai_assessment.hmx_exists = check_var_yok(received_data["hmx"]["var_yok"])
            ai_assessment.hmx_loc = received_data["hmx"]["lokasyon"]
            ai_assessment.akk_exists = check_var_yok(received_data["akk"]["var_yok"])
            ai_assessment.akk_loc = received_data["akk"]["lokasyon"]
            ai_assessment.kot_exists = check_var_yok(received_data["kot"]["var_yok"])
            ai_assessment.kot_loc = received_data["kot"]["lokasyon"]

            db.session.add(ai_assessment)
            patient.status = 2
            db.session.commit()

            return {"message": "AI değerlendirmesi tamamlandı."}


@main.route("/patient/dr/evaluation", methods=["POST"])
@login_required
def patient_dr_evaluation():
    if request.method == "GET":
        return {"message": "Bu endpoint sadece POST isteklerini kabul eder."}
    else:
        requested_data = json.loads(request.data)
        patient_id = int(requested_data["patient_id"])
        field_name = requested_data["field_name"]
        new_value = requested_data["value"]
        patient = (
            db.session.execute(select(Patient).where(Patient.id == patient_id))
            .scalars()
            .first()
        )
        dr_assessment = (
            db.session.execute(
                select(DrAssessment).where(
                    DrAssessment.patient_id == patient_id,
                    DrAssessment.user_id == current_user.id,
                )
            )
            .scalars()
            .first()
        )
        if dr_assessment is None:
            dr_assessment = DrAssessment(
                patient_id=patient.id,
                user_id=current_user.id,
            )
            db.session.add(dr_assessment)

        if hasattr(dr_assessment, field_name):
            setattr(dr_assessment, field_name, new_value)

            # # 2. Commit changes
            db.session.commit()
        else:
            print(f"Error: {field_name}")

    return {"message": "OK."}


@main.route("/export")
@login_required
def export():
    target_directory = os.path.join(EXCEL_REPORTS)
    if not os.path.exists(target_directory):
        os.makedirs(target_directory)

    patients = (
        db.session.query(
            Patient.case_type,
            Patient.case_dir,
            AIAssessment.ai_name,
            AIAssessment.pnx_exists,
            AIAssessment.pnx_loc,
            AIAssessment.hmx_exists,
            AIAssessment.hmx_loc,
            AIAssessment.akk_exists,
            AIAssessment.akk_loc,
            AIAssessment.kot_exists,
            AIAssessment.kot_loc,
            DrAssessment.gemini_pnx,
            DrAssessment.gemini_hmx,
            DrAssessment.gemini_akk,
            DrAssessment.gemini_kot,
            DrAssessment.openai_pnx,
            DrAssessment.openai_hmx,
            DrAssessment.openai_akk,
            DrAssessment.openai_kot,
            DrAssessment.claude_pnx,
            DrAssessment.claude_hmx,
            DrAssessment.claude_akk,
            DrAssessment.claude_kot,
            DrAssessment.grok_pnx,
            DrAssessment.grok_hmx,
            DrAssessment.grok_akk,
            DrAssessment.grok_kot,
            DrAssessment.user_id,
        )
        .join(AIAssessment, AIAssessment.patient_id == Patient.id)
        .join(DrAssessment, DrAssessment.patient_id == Patient.id)
        .order_by(AIAssessment.id.asc())
        .all()
    )

    data = export_to_excel(patients)
    df = pd.DataFrame(data)

    # df = df.rename(columns=COLUMN_NAMES)

    file_name = "diagnosis_report.xlsx"
    file_path = os.path.join(target_directory, file_name)
    df.to_excel(file_path, index=False)

    data = {
        "title": "Rapor İndir",
        "is_created": 1 if len(patients) > 0 else 0,
    }

    return render_template("main/export.html", **data)


def export_to_excel(patients):
    data = {
        "case_type": [],
        "case_dir": [],
        "ai_name": [],
        "pnx_exists": [],
        "pnx_loc": [],
        "hmx_exists": [],
        "hmx_loc": [],
        "akk_exists": [],
        "akk_loc": [],
        "kot_exists": [],
        "kot_loc": [],
        "gemini_pnx": [],
        "gemini_hmx": [],
        "gemini_akk": [],
        "gemini_kot": [],
        "openai_pnx": [],
        "openai_hmx": [],
        "openai_akk": [],
        "openai_kot": [],
        "claude_pnx": [],
        "claude_hmx": [],
        "claude_akk": [],
        "claude_kot": [],
        "grok_pnx": [],
        "grok_hmx": [],
        "grok_akk": [],
        "grok_kot": [],
        "user_id": [],
    }

    for patient in patients:
        data["case_type"].append(patient.case_type)
        data["case_dir"].append(patient.case_dir)
        data["ai_name"].append(patient.ai_name)
        data["pnx_exists"].append(patient.pnx_exists)
        data["pnx_loc"].append(patient.pnx_loc)
        data["hmx_exists"].append(patient.hmx_exists)
        data["hmx_loc"].append(patient.hmx_loc)
        data["akk_exists"].append(patient.akk_exists)
        data["akk_loc"].append(patient.akk_loc)
        data["kot_exists"].append(patient.kot_exists)
        data["kot_loc"].append(patient.kot_loc)
        data["gemini_pnx"].append(patient.gemini_pnx)
        data["gemini_hmx"].append(patient.gemini_hmx)
        data["gemini_akk"].append(patient.gemini_akk)
        data["gemini_kot"].append(patient.gemini_kot)
        data["openai_pnx"].append(patient.openai_pnx)
        data["openai_hmx"].append(patient.openai_hmx)
        data["openai_akk"].append(patient.openai_akk)
        data["openai_kot"].append(patient.openai_kot)
        data["claude_pnx"].append(patient.claude_pnx)
        data["claude_hmx"].append(patient.claude_hmx)
        data["claude_akk"].append(patient.claude_akk)
        data["claude_kot"].append(patient.claude_kot)
        data["grok_pnx"].append(patient.grok_pnx)
        data["grok_hmx"].append(patient.grok_hmx)
        data["grok_akk"].append(patient.grok_akk)
        data["grok_kot"].append(patient.grok_kot)
        data["user_id"].append(patient.user_id)

    return data
