from flask import Blueprint, render_template, redirect, url_for, flash, request, abort
from flask_login import login_required, current_user
from sqlalchemy import func, and_

from app.extensions import db
from app.models.call import Call
from app.models.customer import Customer
from app.models.user import User
from app.models.tag import CallTag
from app.services.permissions import require
from app.services.activity_logger import log_action
from app.services import customer_service, tag_service
from app.services.jalali import jalali_str_to_gregorian_date, to_jalali_str
from app.blueprints.calls.forms import CallLogForm

bp = Blueprint("calls", __name__, url_prefix="/calls")


@bp.route("/")
@login_required
@require("calls")
def index():
    search = request.args.get("q", "").strip()
    salesperson_id = request.args.get("salesperson_id", type=int)
    answered_raw = request.args.get("answered")
    answered = {"1": True, "0": False}.get(answered_raw)
    date_from_raw = request.args.get("date_from", "").strip()
    date_to_raw = request.args.get("date_to", "").strip()

    # تماس‌ها الان یه لیست کامل مشتری‌هاست (حتی بدون تماس)، با اطلاعات آخرین تماسشون کنارش
    latest_dates = (
        db.session.query(Call.customer_id.label("customer_id"), func.max(Call.call_date).label("max_date"))
        .group_by(Call.customer_id)
        .subquery()
    )
    latest_call = (
        db.session.query(
            Call.customer_id.label("customer_id"),
            Call.id.label("call_id"),
            Call.call_date.label("call_date"),
            Call.salesperson_id.label("salesperson_id"),
            Call.answered.label("answered"),
            Call.result_text.label("result_text"),
        )
        .join(latest_dates, and_(
            Call.customer_id == latest_dates.c.customer_id,
            Call.call_date == latest_dates.c.max_date,
        ))
        .subquery()
    )

    query = (
        db.session.query(Customer, latest_call.c.call_id, latest_call.c.call_date,
                          latest_call.c.salesperson_id, latest_call.c.answered, latest_call.c.result_text)
        .outerjoin(latest_call, latest_call.c.customer_id == Customer.id)
        .filter(Customer.is_deleted.is_(False))
    )
    if search:
        like = f"%{search}%"
        query = query.filter(db.or_(Customer.first_name.ilike(like), Customer.last_name.ilike(like),
                                     Customer.mobile_phone.ilike(like)))
    if salesperson_id:
        query = query.filter(latest_call.c.salesperson_id == salesperson_id)
    if answered is not None:
        query = query.filter(latest_call.c.answered.is_(answered))
    try:
        if date_from_raw:
            query = query.filter(latest_call.c.call_date >= jalali_str_to_gregorian_date(date_from_raw))
        if date_to_raw:
            query = query.filter(latest_call.c.call_date <= jalali_str_to_gregorian_date(date_to_raw))
    except Exception:
        pass

    rows = query.order_by(latest_call.c.call_date.desc().nulls_last(), Customer.first_name).limit(1000).all()
    salespeople = User.query.order_by(User.full_name).all()
    salespeople_by_id = {u.id: u.full_name for u in salespeople}

    if search:
        log_action(current_user, "search", "call", details={"query": search})

    return render_template(
        "calls/index.html", rows=rows, salespeople=salespeople, salespeople_by_id=salespeople_by_id,
        q=search, selected_salesperson=salesperson_id, selected_answered=answered_raw,
        date_from=date_from_raw, date_to=date_to_raw,
    )


@bp.route("/new", methods=["GET", "POST"])
@login_required
@require("calls")
def new():
    customer_id = request.args.get("customer_id", type=int) or request.form.get("customer_id", type=int)
    customer = db.session.get(Customer, customer_id) if customer_id else None

    form = CallLogForm()
    search_results = []
    if not customer and request.method == "GET" and request.args.get("search"):
        search_results = customer_service.search_by_name(request.args.get("search"))

    if form.validate_on_submit():
        target_customer = db.session.get(Customer, form.customer_id.data)
        if not target_customer:
            flash("لطفاً یک مشتری برای این تماس انتخاب کنید", "error")
        else:
            call = Call(
                customer_id=target_customer.id,
                salesperson_id=current_user.id,
                answered=(form.answered.data == "1"),
                result_text=form.result_text.data.strip() if form.result_text.data else None,
            )
            db.session.add(call)
            db.session.flush()
            for tag_id in request.form.getlist("tag_ids"):
                db.session.add(CallTag(call_id=call.id, tag_id=int(tag_id)))
            db.session.commit()
            log_action(current_user, "create", "call", call.id, {"customer_id": target_customer.id})
            flash("تماس با موفقیت ثبت شد", "success")
            return redirect(url_for("customer_profile.show", customer_id=target_customer.id))

    return render_template(
        "calls/new.html", form=form, customer=customer,
        search_results=search_results, all_tag_groups=tag_service.all_tags_grouped(),
    )


@bp.route("/<int:call_id>")
@login_required
@require("calls")
def detail(call_id):
    call = db.session.get(Call, call_id) or abort(404)
    call_tags = (
        db.session.query(CallTag)
        .filter(CallTag.call_id == call_id)
        .all()
    )
    tag_names = [ct.tag.name for ct in call_tags]
    return render_template(
        "calls/detail.html", call=call, tag_names=tag_names,
    )
