from flask import Blueprint, render_template, redirect, url_for, flash, request, abort, send_file, jsonify
from flask_login import login_required, current_user

from app.extensions import db
from app.models.customer import Customer
from app.models.import_job import ImportJob
from app.services.permissions import require
from app.services.activity_logger import log_action
from app.services import customer_service, photo_storage, customer_import
from app.services.jalali import jalali_str_to_gregorian_date, to_jalali_str
from app.blueprints.customer_account.forms import CustomerForm
from config import CUSTOMER_RATINGS

bp = Blueprint("customer_account", __name__, url_prefix="/customers")


def _check_duplicate_phone(form, exclude_id=None):
    mobile = form.mobile_phone.data.strip() if form.mobile_phone.data else None
    landline = form.landline_phone.data.strip() if form.landline_phone.data else None
    if not mobile and not landline:
        return None

    query = Customer.query.filter(Customer.is_deleted.is_(False))
    if exclude_id:
        query = query.filter(Customer.id != exclude_id)

    existing = None
    matched_phone = None
    if mobile:
        existing = query.filter(Customer.mobile_phone == mobile).first()
        matched_phone = mobile
    if not existing and landline:
        existing = query.filter(Customer.landline_phone == landline).first()
        matched_phone = landline

    if existing:
        return {
            "existing_id": existing.id,
            "existing_name": f"{existing.first_name} {existing.last_name}",
            "phone": matched_phone,
        }
    return None


def _populate_customer(customer, form):
    customer.first_name = form.first_name.data.strip()
    customer.last_name = form.last_name.data.strip()
    customer.city = form.city.data.strip() if form.city.data else None
    customer.gender = form.gender.data
    customer.landline_phone = form.landline_phone.data.strip() if form.landline_phone.data else None
    customer.mobile_phone = form.mobile_phone.data.strip() if form.mobile_phone.data else None
    customer.customer_code = form.customer_code.data.strip() if form.customer_code.data else None
    customer.referrer_text = form.referrer_text.data.strip() if form.referrer_text.data else None
    customer.how_found = form.how_found.data.strip() if form.how_found.data else None
    customer.instagram_id = form.instagram_id.data.strip() if form.instagram_id.data else None
    customer.status = form.status.data
    customer.address = form.address.data.strip() if form.address.data else None
    customer.description = form.description.data.strip() if form.description.data else None
    if form.birth_date.data and form.birth_date.data.strip():
        try:
            customer.birth_date = jalali_str_to_gregorian_date(form.birth_date.data.strip())
        except Exception:
            customer.birth_date = None
    else:
        customer.birth_date = None


@bp.route("/new", methods=["GET", "POST"])
@login_required
@require("customer_account")
def new():
    form = CustomerForm()
    if request.method == "GET":
        form.customer_code.data = customer_service.next_customer_code()

    if form.validate_on_submit():
        if not form.mobile_phone.data and not form.landline_phone.data:
            pass  # شماره تماس در دسکتاپ الزامی نبود، اینجا هم اجباری نمی‌کنیم

        if request.form.get("confirm_duplicate") != "1":
            dup = _check_duplicate_phone(form)
            if dup:
                return render_template("customer_account/form.html", form=form, customer=None, duplicate_warning=dup)

        customer = Customer(created_by=current_user.id)
        _populate_customer(customer, form)
        if customer.customer_code:
            existing = Customer.query.filter_by(customer_code=customer.customer_code).first()
            if existing:
                flash("این کد مشتری قبلاً استفاده شده است", "error")
                return render_template("customer_account/form.html", form=form, customer=None)
        db.session.add(customer)
        db.session.flush()

        if form.photo.data:
            customer.photo_path = photo_storage.save_photo(form.photo.data, customer.id)

        db.session.commit()
        log_action(current_user, "create", "customer", customer.id,
                   {"name": f"{customer.first_name} {customer.last_name}"})
        flash(f"«{customer.first_name} {customer.last_name}» با موفقیت ثبت شد — می‌توانید مشتری بعدی را وارد کنید", "success")
        return redirect(url_for("customer_account.new"))

    return render_template("customer_account/form.html", form=form, customer=None)


@bp.route("/<int:customer_id>/edit", methods=["GET", "POST"])
@login_required
@require("customer_account")
def edit(customer_id):
    customer = db.session.get(Customer, customer_id) or abort(404)
    form = CustomerForm(obj=customer)
    if request.method == "GET" and customer.birth_date:
        form.birth_date.data = to_jalali_str(customer.birth_date)

    if form.validate_on_submit():
        if request.form.get("confirm_duplicate") != "1":
            dup = _check_duplicate_phone(form, exclude_id=customer.id)
            if dup:
                return render_template("customer_account/form.html", form=form, customer=customer, duplicate_warning=dup)

        _populate_customer(customer, form)
        if form.photo.data:
            customer.photo_path = photo_storage.save_photo(form.photo.data, customer.id)
        db.session.commit()
        log_action(current_user, "update", "customer", customer.id,
                   {"name": f"{customer.first_name} {customer.last_name}"})
        flash("اطلاعات مشتری با موفقیت ذخیره شد", "success")
        return redirect(url_for("customer_profile.show", customer_id=customer.id))

    return render_template("customer_account/form.html", form=form, customer=customer)


@bp.route("/remove", methods=["GET"])
@login_required
@require("customer_account")
def remove():
    search = request.args.get("q", "").strip()
    city = request.args.get("city") or None
    status = request.args.get("status") or None
    rating = request.args.get("rating") or None
    sort = request.args.get("sort", "joined_desc")

    results = customer_service.list_customers(
        search=search, city=city, status=status, rating=rating, sort=sort
    )
    cities = customer_service.distinct_cities()

    return render_template(
        "customer_account/remove.html",
        results=results, cities=cities,
        statuses=customer_service.STATUS_CHOICES, ratings=CUSTOMER_RATINGS,
        sorts=customer_service.SORT_OPTIONS,
        q=search, selected_city=city, selected_status=status,
        selected_rating=rating, selected_sort=sort,
    )


@bp.route("/<int:customer_id>/delete", methods=["POST"])
@login_required
@require("customer_account")
def delete(customer_id):
    customer = db.session.get(Customer, customer_id) or abort(404)
    name = f"{customer.first_name} {customer.last_name}"
    customer.is_deleted = True  # حذف نرم — طبق تصمیم کاربر برای نسخه آنلاین چندکاربره
    db.session.commit()
    log_action(current_user, "delete", "customer", customer.id, {"name": name})
    flash(f"«{name}» حذف شد", "success")
    return redirect(url_for("customer_account.remove"))


@bp.route("/import")
@login_required
@require("customer_account")
def import_page():
    return render_template("customer_account/import.html")


@bp.route("/import/template")
@login_required
@require("customer_account")
def import_template():
    buffer = customer_import.build_template_excel()
    return send_file(
        buffer, mimetype="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        as_attachment=True, download_name="قالب-وارد-کردن-مشتریان.xlsx",
    )


@bp.route("/import/check", methods=["POST"])
@login_required
@require("customer_account")
def import_check():
    file = request.files.get("file")
    if not file or not file.filename:
        return jsonify({"error": "فایلی انتخاب نشده است"}), 400
    if not file.filename.lower().endswith(".xlsx"):
        return jsonify({"error": "فقط فایل اکسل (xlsx.) پذیرفته می‌شود"}), 400

    file_bytes = file.read()
    token = customer_import.save_pending_import(file_bytes)
    conflicts = customer_import.find_duplicate_conflicts(file_bytes)
    return jsonify({"token": token, "conflicts": conflicts})


@bp.route("/import/start", methods=["POST"])
@login_required
@require("customer_account")
def import_start():
    data = request.get_json(silent=True) or {}
    token = data.get("token")
    skip_rows = set(data.get("skip_rows") or [])
    if not token:
        return jsonify({"error": "نشست آپلود پیدا نشد — لطفاً دوباره فایل را انتخاب کنید"}), 400

    file_bytes = customer_import.load_pending_import(token)
    if file_bytes is None:
        return jsonify({"error": "فایل موقت پیدا نشد — لطفاً دوباره فایل را انتخاب کنید"}), 400

    job_id = customer_import.start_import_job(file_bytes, current_user.id, skip_rows=skip_rows)
    customer_import.delete_pending_import(token)
    return jsonify({"job_id": job_id})


@bp.route("/import/status/<int:job_id>")
@login_required
@require("customer_account")
def import_status(job_id):
    job = db.session.get(ImportJob, job_id) or abort(404)
    return jsonify({
        "status": job.status,
        "total": job.total_rows,
        "processed": job.processed_rows,
        "created": job.created_count,
        "skipped": job.skipped_count,
        "errors": job.errors or [],
        "error_message": job.error_message,
    })
