from datetime import date, datetime, timedelta
from flask import Blueprint, flash, make_response, redirect, render_template, request, url_for
from flask_login import current_user, login_required
from sqlalchemy import func
from app_new.extensions import db
from app_new.core.models.user import Staff
from app_new.core.models.prevention import PreventionWorkLog, StaffAuthorization, RiskAssessment, PreventionAction, SafetyRegisterEntry
from app_new.core.services.planning_service import PlanningService

prevention_bp = Blueprint("prevention", __name__)
def _date(value): return datetime.strptime(value, "%Y-%m-%d").date() if value else None

@prevention_bp.route("/")
@login_required
def index():
    monday = date.today() - timedelta(days=date.today().weekday())
    minutes = db.session.query(func.coalesce(func.sum(PreventionWorkLog.duration_minutes), 0)).filter(PreventionWorkLog.user_id == current_user.id, PreventionWorkLog.work_date >= monday).scalar()
    available_minutes = 0
    for offset in range(7):
        hours = PlanningService.get_working_hours(monday + timedelta(days=offset), current_user.id)
        if hours:
            available_minutes += int((datetime.combine(date.min, hours[1]) - datetime.combine(date.min, hours[0])).total_seconds() / 60)
            if hours[2] and hours[3]:
                available_minutes -= int((datetime.combine(date.min, hours[3]) - datetime.combine(date.min, hours[2])).total_seconds() / 60)
    target = round(available_minutes * 0.10)
    logs = PreventionWorkLog.query.filter_by(user_id=current_user.id).order_by(PreventionWorkLog.work_date.desc()).limit(20).all()
    return render_template("prevention/index.html", staff=Staff.query.filter_by(is_active=True).order_by(Staff.last_name).all(), logs=logs, risks=RiskAssessment.query.filter_by(is_active=True).all(), actions=PreventionAction.query.order_by(PreventionAction.due_date).all(), entries=SafetyRegisterEntry.query.order_by(SafetyRegisterEntry.entry_date.desc()).limit(20).all(), minutes=minutes, target=target, available_minutes=available_minutes)

@prevention_bp.post("/staff")
@login_required
def add_staff():
    db.session.add(Staff(first_name=request.form.get("first_name", "").strip(), last_name=request.form.get("last_name", "").strip(), function=request.form.get("function")))
    db.session.commit(); flash("Agent ajouté.", "success"); return redirect(url_for("prevention.index"))

@prevention_bp.post("/time")
@login_required
def add_time():
    db.session.add(PreventionWorkLog(user_id=current_user.id, work_date=_date(request.form.get("work_date")) or date.today(), duration_minutes=max(1, request.form.get("duration_minutes", type=int) or 1), activity=request.form.get("activity", "").strip(), notes=request.form.get("notes")))
    db.session.commit(); flash("Temps de prévention enregistré.", "success"); return redirect(url_for("prevention.index"))

@prevention_bp.post("/authorization")
@login_required
def add_authorization():
    db.session.add(StaffAuthorization(staff_id=request.form.get("staff_id", type=int), name=request.form.get("name", "").strip(), issued_on=_date(request.form.get("issued_on")), expires_on=_date(request.form.get("expires_on")), issuer=request.form.get("issuer")))
    db.session.commit(); flash("Habilitation enregistrée.", "success"); return redirect(url_for("prevention.index"))

@prevention_bp.post("/risk")
@login_required
def add_risk():
    severity = request.form.get("severity", type=int) or 1
    probability = request.form.get("probability", type=int) or 1
    work_unit = request.form.get("work_unit", "").strip()
    hazard = request.form.get("hazard", "").strip()
    if not work_unit or not hazard or severity not in range(1, 5) or probability not in range(1, 5):
        flash("Unité, danger et cotations de 1 à 4 sont obligatoires.", "danger")
        return redirect(url_for("prevention.index"))
    db.session.add(RiskAssessment(work_unit=work_unit, hazard=hazard, exposed_people=request.form.get("exposed_people"), severity=severity, probability=probability, control_measures=request.form.get("control_measures"), reviewed_on=date.today()))
    db.session.commit(); flash("Risque ajouté au DUERP.", "success"); return redirect(url_for("prevention.index"))

@prevention_bp.post("/action")
@login_required
def add_action():
    db.session.add(PreventionAction(title=request.form.get("title", "").strip(), source_type=request.form.get("source_type", "observation"), risk_id=request.form.get("risk_id", type=int), priority=request.form.get("priority", "normale"), owner=request.form.get("owner"), due_date=_date(request.form.get("due_date"))))
    db.session.commit(); flash("Action créée.", "success"); return redirect(url_for("prevention.index"))

@prevention_bp.post("/action/<int:id>/status")
@login_required
def update_action_status(id):
    action = PreventionAction.query.get_or_404(id)
    allowed = {"a_faire", "validee", "planifiee", "en_cours", "verifiee", "cloturee", "refusee"}
    status = request.form.get("status")
    if status not in allowed:
        flash("Statut de prévention invalide.", "danger")
    else:
        action.status = status
        db.session.commit()
        flash("Action de prévention mise à jour.", "success")
    return redirect(url_for("prevention.index"))

@prevention_bp.post("/register")
@login_required
def add_register():
    db.session.add(SafetyRegisterEntry(entry_date=_date(request.form.get("entry_date")) or date.today(), entry_type=request.form.get("entry_type", "observation"), title=request.form.get("title", "").strip(), details=request.form.get("details"), location=request.form.get("location"), created_by_id=current_user.id))
    db.session.commit(); flash("Entrée ajoutée au registre.", "success"); return redirect(url_for("prevention.index"))


@prevention_bp.get('/duerp.csv')
@login_required
def export_duerp():
    """Exporte le registre DUERP exploitable dans un tableur."""
    import csv
    import io
    output = io.StringIO()
    writer = csv.writer(output, delimiter=';')
    writer.writerow(['Unité de travail', 'Danger', 'Personnes exposées', 'Gravité', 'Probabilité', 'Criticité', 'Mesures existantes', 'Dernière revue'])
    for risk in RiskAssessment.query.order_by(RiskAssessment.work_unit, RiskAssessment.hazard).all():
        writer.writerow([risk.work_unit, risk.hazard, risk.exposed_people or '', risk.severity,
                         risk.probability, (risk.severity or 0) * (risk.probability or 0),
                         risk.control_measures or '', risk.reviewed_on.isoformat() if risk.reviewed_on else ''])
    response = make_response('\ufeff' + output.getvalue())
    response.headers['Content-Type'] = 'text/csv; charset=utf-8'
    response.headers['Content-Disposition'] = 'attachment; filename=duerp.csv'
    return response
