import os
import shutil

from flask import Blueprint, render_template, redirect, url_for, flash, request, current_app
from flask_login import login_required, current_user

from app.extensions import db
from app.models import Patient, CaregiverLink, Document, IntakeEvent
from app.profiles.forms import ProfileForm, EmergencyInfoForm, AssignPendingDocumentForm
from app.profiles.helpers import get_caregiver_link, set_active_patient
from app.documents.routes import EXT_TO_MIME

profiles_bp = Blueprint(
    "profiles", __name__, url_prefix="/perfiles", template_folder="../templates/profiles"
)


@profiles_bp.before_request
def redirect_admins():
    if current_user.is_authenticated and current_user.is_admin():
        return redirect(url_for("admin.index"))
    return None


@profiles_bp.route("/")
@login_required
def list_profiles():
    pending_count = IntakeEvent.query.filter_by(
        user_id=current_user.id, status=IntakeEvent.STATUS_AMBIGUOUS_PATIENT
    ).count()
    return render_template(
        "profiles/list.html", patients=current_user.patients, pending_count=pending_count
    )


@profiles_bp.route("/nuevo", methods=["GET", "POST"])
@login_required
def new_profile():
    form = ProfileForm()
    if form.validate_on_submit():
        patient = Patient(
            created_by_user_id=current_user.id,
            full_name=form.full_name.data,
            birth_date=form.birth_date.data,
            national_id=form.national_id.data or None,
            phone=form.phone.data or None,
            country=form.country.data or None,
            city=form.city.data or None,
            emergency_token=Patient.generate_emergency_token(),
        )
        db.session.add(patient)
        db.session.flush()

        db.session.add(CaregiverLink(
            user_id=current_user.id, patient_id=patient.id,
            relationship_type=form.relationship_type.data, is_primary=True,
        ))
        db.session.commit()

        set_active_patient(patient.id)
        flash(f"Perfil de {patient.full_name} creado.", "success")
        return redirect(url_for("summary.view"))

    return render_template("profiles/new.html", form=form)


@profiles_bp.route("/<int:patient_id>/usar")
@login_required
def use_profile(patient_id):
    if not set_active_patient(patient_id):
        flash("No tienes acceso a ese perfil.", "danger")
        return redirect(url_for("profiles.list_profiles"))
    return redirect(url_for("summary.view"))


@profiles_bp.route("/pendientes")
@login_required
def pending_documents():
    events = IntakeEvent.query.filter_by(
        user_id=current_user.id, status=IntakeEvent.STATUS_AMBIGUOUS_PATIENT
    ).order_by(IntakeEvent.received_at.desc()).all()
    return render_template(
        "profiles/pending.html", events=events, patients=current_user.patients
    )


@profiles_bp.route("/pendientes/<int:event_id>/asignar", methods=["POST"])
@login_required
def assign_pending(event_id):
    event = db.session.get(IntakeEvent, event_id)
    if not event or event.user_id != current_user.id or event.status != IntakeEvent.STATUS_AMBIGUOUS_PATIENT:
        flash("Ese documento pendiente no existe o ya fue asignado.", "danger")
        return redirect(url_for("profiles.pending_documents"))

    form = AssignPendingDocumentForm()
    form.patient_id.choices = [(p.id, p.full_name) for p in current_user.patients]
    if not form.validate_on_submit() or not get_caregiver_link(form.patient_id.data):
        flash("Selecciona un perfil válido.", "danger")
        return redirect(url_for("profiles.pending_documents"))

    patient = db.session.get(Patient, form.patient_id.data)
    patient_folder = os.path.join(current_app.config["UPLOAD_FOLDER"], str(patient.id))
    os.makedirs(patient_folder, exist_ok=True)

    final_path = os.path.join(patient_folder, os.path.basename(event.pending_storage_path))
    shutil.move(event.pending_storage_path, final_path)

    ext = event.pending_original_filename.rsplit(".", 1)[-1].lower()
    document = Document(
        patient_id=patient.id,
        original_filename=event.pending_original_filename,
        storage_path=final_path,
        mime_type=EXT_TO_MIME.get(ext, "application/octet-stream"),
        status=Document.STATUS_PENDING,
        source_channel="email",
    )
    db.session.add(document)
    db.session.flush()

    event.status = IntakeEvent.STATUS_MATCHED
    event.patient_id = patient.id
    event.document_id = document.id
    event.pending_storage_path = None
    db.session.commit()

    flash(f"Documento asignado a {patient.full_name}.", "success")
    return redirect(url_for("profiles.pending_documents"))


@profiles_bp.route("/<int:patient_id>/emergencia", methods=["GET", "POST"])
@login_required
def emergency_settings(patient_id):
    link = get_caregiver_link(patient_id)
    if not link:
        flash("No tienes acceso a ese perfil.", "danger")
        return redirect(url_for("profiles.list_profiles"))

    patient = link.patient
    form = EmergencyInfoForm(obj=patient)
    if form.validate_on_submit():
        patient.emergency_contact_name = form.emergency_contact_name.data or None
        patient.emergency_contact_phone = form.emergency_contact_phone.data or None
        patient.blood_type = form.blood_type.data or None
        db.session.commit()
        flash("Información de emergencia actualizada.", "success")
        return redirect(url_for("profiles.emergency_settings", patient_id=patient.id))

    emergency_url = url_for("emergency.view", token=patient.emergency_token, _external=True)
    return render_template(
        "profiles/emergency_settings.html", form=form, patient=patient, emergency_url=emergency_url
    )


@profiles_bp.route("/<int:patient_id>/emergencia/regenerar", methods=["POST"])
@login_required
def regenerate_emergency_token(patient_id):
    link = get_caregiver_link(patient_id)
    if not link:
        flash("No tienes acceso a ese perfil.", "danger")
        return redirect(url_for("profiles.list_profiles"))

    link.patient.emergency_token = Patient.generate_emergency_token()
    db.session.commit()
    flash("Se generó un nuevo enlace de emergencia. El anterior ya no funciona.", "success")
    return redirect(url_for("profiles.emergency_settings", patient_id=patient_id))
