# -*- coding: utf-8 -*-
"""中台：发票管理（查看/下载店员上传的高铁电子发票，支持单个+批量下载并标记已下载）。"""
import os
import io
import zipfile
import datetime

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

from app.models import Invoice, Staff, Store, Chain
from app.extensions import db
from app.admin import bp
from app.admin.views import _admin_only
from app.admin.admins import _super_only
from app.services import log_action
from app.region_data import CHINA_REGION


def _invoice_path(inv):
    """file_url('/uploads/invoice/xxx') → UPLOAD_DIR 下的实际文件路径。"""
    url = inv.file_url or ""
    prefix = "/uploads/"
    rel = url[len(prefix):] if url.startswith(prefix) else url.lstrip("/")
    return os.path.join(current_app.config["UPLOAD_DIR"], rel)


@bp.route("/invoices")
@login_required
def invoices():
    _admin_only()
    q = (request.args.get("q") or "").strip()
    year = request.args.get("year", "").strip()
    month = request.args.get("month", "").strip()
    chain = request.args.get("chain", "").strip()
    province = request.args.get("province", "").strip()
    city = request.args.get("city", "").strip()
    query = Invoice.query.join(Invoice.staff).filter(Staff.deleted == False)
    if q:
        query = query.filter(db.or_(Staff.name.contains(q), Staff.phone.contains(q)))
    if year and month:
        start = datetime.date(int(year), int(month), 1)
        end = datetime.date(int(year) + 1, 1, 1) if int(month) == 12 else datetime.date(int(year), int(month) + 1, 1)
        query = query.filter(Invoice.created_at >= start, Invoice.created_at < end)
    elif year:
        query = query.filter(Invoice.created_at >= datetime.date(int(year), 1, 1),
                             Invoice.created_at < datetime.date(int(year) + 1, 1, 1))
    elif month:
        query = query.filter(db.extract('month', Invoice.created_at) == int(month))
    if chain:
        query = query.join(Store, Staff.store_id == Store.id).filter(Store.chain_id == int(chain))
    if province:
        query = query.filter(Staff.province == province)
    if city:
        query = query.filter(Staff.city == city)
    invoices = query.order_by(Invoice.id.desc()).limit(300).all()
    chains = Chain.query.order_by(Chain.name).all()
    years = sorted({str(s[0].year) for s in
                    Invoice.query.with_entities(Invoice.created_at).all() if s[0]}, reverse=True)
    return render_template("admin/invoice_list.html", invoices=invoices, q=q,
                           year=year, month=month, chain=chain, province=province, city=city,
                           chains=chains, years=years, china_region=CHINA_REGION, active="invoices")


@bp.route("/invoices/<int:id>/download")
@login_required
def invoice_download(id):
    """下载单张发票，并标记为已下载。"""
    _admin_only()
    inv = Invoice.query.get_or_404(id)
    path = _invoice_path(inv)
    if not os.path.isfile(path):
        return "发票文件不存在", 404
    inv.downloaded = True
    inv.downloaded_at = datetime.datetime.now()
    inv.downloaded_by = current_user.id
    db.session.commit()
    return send_file(path, as_attachment=True,
                     download_name=inv.filename or os.path.basename(path))


@bp.route("/invoices/download", methods=["POST"])
@login_required
def invoice_download_batch():
    """批量下载选中的发票（内存打 zip），并全部标记已下载。"""
    _admin_only()
    ids = [int(i) for i in request.form.getlist("ids") if i.isdigit()]
    if not ids:
        return "未选择发票", 400
    invs = Invoice.query.filter(Invoice.id.in_(ids)).all()
    if not invs:
        return "未找到发票", 404
    buf = io.BytesIO()
    now = datetime.datetime.now()
    used = {}
    with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
        for inv in invs:
            path = _invoice_path(inv)
            if not os.path.isfile(path):
                continue
            staff_name = inv.staff.name if inv.staff else "staff%d" % inv.staff_id
            base = inv.filename or os.path.basename(path)
            arc = "%s_%s" % (staff_name, base)
            if arc in used:
                used[arc] += 1
                name, ext = os.path.splitext(arc)
                arc = "%s_%d%s" % (name, used[arc], ext)
            else:
                used[arc] = 1
            zi = zipfile.ZipInfo(arc)
            zi.flag_bits |= 0x800          # UTF-8 文件名标志，避免中文乱码
            zi.compress_type = zipfile.ZIP_DEFLATED
            with open(path, "rb") as f:
                zf.writestr(zi, f.read())
            inv.downloaded = True
            inv.downloaded_at = now
            inv.downloaded_by = current_user.id
    db.session.commit()
    buf.seek(0)
    return send_file(buf, mimetype="application/zip", as_attachment=True,
                     download_name="invoices_%s.zip" % now.strftime("%Y%m%d_%H%M%S"))


@bp.route("/invoices/<int:id>/delete", methods=["POST"])
@login_required
def invoice_delete(id):
    """删除单张发票（仅超级管理员）。一并删除磁盘文件。"""
    _super_only()
    inv = Invoice.query.get_or_404(id)
    path = _invoice_path(inv)
    try:
        if os.path.isfile(path):
            os.remove(path)
    except OSError:
        pass
    summary = "删除发票：%s" % (inv.filename or inv.id)
    db.session.delete(inv)
    log_action("delete_invoice", target_type="invoice", target_id=id,
               summary=summary, commit=False)
    db.session.commit()
    flash("已删除发票", "success")
    return redirect(url_for("admin.invoices"))


@bp.route("/invoices/batch-delete", methods=["POST"])
@login_required
def invoice_delete_batch():
    """批量删除选中的发票（仅超级管理员）。一并删除磁盘文件。"""
    _super_only()
    ids = [int(i) for i in request.form.getlist("ids") if i.isdigit()]
    if not ids:
        flash("未选择发票", "danger")
        return redirect(url_for("admin.invoices"))
    invs = Invoice.query.filter(Invoice.id.in_(ids)).all()
    n = len(invs)
    for inv in invs:
        path = _invoice_path(inv)
        try:
            if os.path.isfile(path):
                os.remove(path)
        except OSError:
            pass
        db.session.delete(inv)
    log_action("delete_invoice_batch", target_type="invoice",
               summary="批量删除发票 %d 条" % n, commit=False)
    db.session.commit()
    flash("已删除 %d 条发票" % n, "success")
    return redirect(url_for("admin.invoices"))
