# -*- coding: utf-8 -*-
"""中台：日常管理（合规照）——可见范围 + 积分设置 + 两 TAB（药友/壹药网）提交审核（通过发分/驳回/super 删除扣回）。"""
import json
import csv
import io
import datetime

from flask import render_template, request, redirect, url_for, flash, abort, Response
from flask_login import login_required, current_user

from app.models import (DailyCompliance, DailyTab, DailyTabParticipant,
                        Staff, Store, Chain)
from app.extensions import db
from app.services import add_points, log_action, get_setting_int, set_setting
from app.admin import bp
from app.admin.views import _admin_only
from app.admin.admins import _super_only
from app.region_data import CHINA_REGION

def _ordered_tabs():
    """日常管理各 TAB，按 sort 倒序（KA连锁访店 300 排第一）。"""
    return DailyTab.query.order_by(DailyTab.sort.desc(), DailyTab.id).all()


def _tab_name(key):
    t = DailyTab.query.filter_by(key=key).first()
    return t.name if t else key


@bp.route("/daily", methods=["GET"])
@login_required
def daily():
    """日常管理主页面：两 TAB 合规照审核（仿门店运营审核页；设置在 /daily/settings）。"""
    _admin_only()
    status = request.args.get("status", "pending").strip()
    year = request.args.get("year", "").strip()
    month = request.args.get("month", "").strip()
    cust = request.args.get("cust", "").strip()            # 客户名称搜索
    province = request.args.get("province", "").strip()    # 客户省份
    city = request.args.get("city", "").strip()            # 客户城市
    sq = request.args.get("sq", "").strip()                # 店员姓名/手机
    visit_purpose = request.args.get("visit_purpose", "").strip()
    product_name = request.args.get("product_name", "").strip()
    tab_data = []
    for t in _ordered_tabs():
        q = (DailyCompliance.query.join(DailyCompliance.staff)
             .filter(DailyCompliance.tab_key == t.key, Staff.deleted == False))
        if status == "reviewed":
            q = q.filter(DailyCompliance.status.in_(("approved", "rejected")))
        elif status in ("pending", "approved", "rejected"):
            q = q.filter(DailyCompliance.status == status)
        if year and month:
            q = q.filter(DailyCompliance.period == "%s-%02d" % (int(year), int(month)))
        elif year:
            q = q.filter(DailyCompliance.period.like(year + "-%"))
        elif month:
            q = q.filter(DailyCompliance.period.like("__-%02d" % int(month)))
        if cust:
            # 一个搜索框同时覆盖 normal 的客户名称与 ka 的 KA连锁
            q = q.filter(db.or_(DailyCompliance.cust_name.contains(cust),
                                DailyCompliance.ka_chain.contains(cust)))
        if province:
            q = q.filter(DailyCompliance.cust_province == province)
        if city:
            q = q.filter(DailyCompliance.cust_city == city)
        if sq:
            q = q.filter(db.or_(Staff.name.contains(sq), Staff.phone.contains(sq)))
        if visit_purpose:
            q = q.filter(DailyCompliance.visit_purpose == visit_purpose)
        if product_name:
            q = q.filter(DailyCompliance.product_name == product_name)
        items = q.order_by(DailyCompliance.id.desc()).limit(200).all()
        tab_data.append({"key": t.key, "name": t.name,
                         "form_type": t.form_type or "normal",
                         "door": t.door_label or "门头照", "office": t.office_label or "办公区照",
                         "records": items})
    years = sorted({r[0][:4] for r in db.session.query(DailyCompliance.period).all()
                    if r[0] and len(r[0]) >= 4}, reverse=True)
    return render_template("admin/daily.html", tab_data=tab_data, status=status,
                           year=year, month=month, cust=cust, province=province, city=city, sq=sq,
                           visit_purpose=visit_purpose, product_name=product_name,
                           years=years, china_region=CHINA_REGION,
                           reward=get_setting_int("daily_reward", 100), active="daily")


_DAILY_STATUS = {"pending": "待审核", "approved": "已通过", "rejected": "已驳回"}


@bp.route("/daily/<string:tab>/export")
@login_required
def daily_export(tab):
    """导出某 TAB 的全部日常管理记录为 CSV（含所有字段 + 两张照片的完整 URL）。"""
    _admin_only()
    t = DailyTab.query.filter_by(key=tab).first()
    if not t:
        abort(404)
    rows = (DailyCompliance.query.join(DailyCompliance.staff)
            .filter(DailyCompliance.tab_key == tab, Staff.deleted == False)
            .order_by(DailyCompliance.id.desc()).limit(5000).all())
    reviewer_ids = set(r.reviewer_id for r in rows if r.reviewer_id)
    reviewers = {s.id: s.name for s in Staff.query.filter(Staff.id.in_(reviewer_ids)).all()} if reviewer_ids else {}
    host = request.host_url.rstrip("/")
    out = io.StringIO()
    out.write("﻿")   # UTF-8 BOM，Excel 打开中文不乱码
    w = csv.writer(out)
    w.writerow(["ID", "TAB", "客户名称", "KA连锁", "省份", "城市", "拜访目的", "产品",
                "沟通量/活动描述", "已陈列产品", "周期", "状态", "积分", "店员姓名", "手机号",
                "门店", "连锁", t.door_label or "照片1", t.office_label or "照片2",
                "提交时间", "审核人", "审核时间", "驳回理由"])
    for r in rows:
        w.writerow([r.id, t.name, r.cust_name or "", r.ka_chain or "", r.cust_province or "",
                    r.cust_city or "", r.visit_purpose or "", r.product_name or "",
                    r.visit_content or "", r.displayed_products or "", r.period or "",
                    _DAILY_STATUS.get(r.status, r.status), r.points_earned,
                    r.staff.name if r.staff else "", r.staff.phone if r.staff else "",
                    r.staff.store.name if (r.staff and r.staff.store) else "",
                    r.staff.store.chain.name if (r.staff and r.staff.store and r.staff.store.chain) else "",
                    host + (r.door_img or ""), host + (r.office_img or ""),
                    r.created_at.strftime("%Y-%m-%d %H:%M") if r.created_at else "",
                    reviewers.get(r.reviewer_id, ""),
                    r.reviewed_at.strftime("%Y-%m-%d %H:%M") if r.reviewed_at else "",
                    r.reject_reason or ""])
    filename = "daily_%s_%s.csv" % (tab, datetime.date.today())
    return Response(out.getvalue(), mimetype="text/csv",
                    headers={"Content-Disposition": "attachment; filename=%s" % filename})


@bp.route("/daily/settings", methods=["GET", "POST"])
@login_required
def daily_settings():
    """日常管理设置：审核积分（后台可配）+ 各 TAB 可见范围（每 TAB 独立 全员/连锁/指定人员，
    抄文件下载分类可见范围模式）。图标是否对店员可见 = 至少一个 TAB 可见（见 api _daily_icon_visible）。"""
    _admin_only()
    if request.method == "POST":
        # 仅保存审核积分（每 TAB 可见范围走 /daily/tab/<id> 单独提交）
        reward = request.form.get("reward", 100, type=int)
        if reward < 0:
            reward = 0
        set_setting("daily_reward", reward)
        log_action("daily_reward", target_type="setting", target_id=0,
                   summary="日常管理：审核奖励 %d 分" % reward)
        flash("已保存审核积分", "success")
        return redirect(url_for("admin.daily_settings"))
    chains = Chain.query.order_by(Chain.name).all()
    tab_data = []
    for t in _ordered_tabs():
        tab_data.append({
            "tab": t,
            "sel_chains": set(json.loads(t.allowed_chains) if t.allowed_chains else []),
            "sel_staff": set(p.staff_id for p in
                             DailyTabParticipant.query.filter_by(tab_id=t.id).all()),
        })
    staff_list = Staff.query.filter(
        Staff.role == "staff", Staff.deleted.is_(False), Staff.status == "active"
    ).order_by(Staff.id.desc()).limit(500).all()
    chain_counts = {}
    for c in chains:
        chain_counts[c.id] = Staff.query.join(Staff.store).filter(
            Staff.role == "staff", Staff.deleted.is_(False), Staff.status == "active",
            Store.chain_id == c.id).count()
    return render_template("admin/daily_settings.html", tab_data=tab_data, chains=chains,
                           staff_list=staff_list, chain_counts=chain_counts,
                           reward=get_setting_int("daily_reward", 100),
                           china_region=CHINA_REGION, active="daily")


@bp.route("/daily/tab/<int:id>", methods=["POST"])
@login_required
def daily_tab_scope(id):
    """保存某 TAB 的可见范围（抄文件下载分类范围模式：scope_mode + chains + participant 全量替换）。"""
    _admin_only()
    t = DailyTab.query.get_or_404(id)
    t.scope_mode = request.form.get("scope_mode", "all")
    t.allowed_chains = (json.dumps([int(c) for c in request.form.getlist("chains")])
                        if t.scope_mode == "chain" else None)
    DailyTabParticipant.query.filter_by(tab_id=t.id).delete()
    if t.scope_mode == "staff":
        for sid in request.form.getlist("staff_ids"):
            db.session.add(DailyTabParticipant(tab_id=t.id, staff_id=int(sid)))
    db.session.commit()
    log_action("daily_tab_scope", target_type="daily_tab", target_id=t.id,
               summary="日常管理「%s」可见范围：%s" % (t.name, t.scope_mode))
    flash("已保存「%s」可见范围" % t.name, "success")
    return redirect(url_for("admin.daily_settings") + "#tab-%d" % t.id)


@bp.route("/daily/<int:id>/approve", methods=["POST"])
@login_required
def daily_approve(id):
    _admin_only()
    # 行锁串行化并发审核，防双击/并发重复发分
    rec = db.session.query(DailyCompliance).filter(DailyCompliance.id == id).with_for_update().first()
    if not rec:
        abort(404)
    if rec.status != "pending":
        flash("该提交已处理", "danger")
        return redirect(url_for("admin.daily"))
    reward = get_setting_int("daily_reward", 100)
    rec.status = "approved"
    rec.reviewer_id = current_user.id
    rec.reviewed_at = datetime.datetime.now()
    rec.points_earned = reward
    ok = add_points(rec.staff, reward, "daily", ref_id=rec.id,
                    remark="日常管理合规照奖励（%s/%s）" % (_tab_name(rec.tab_key), rec.period), commit=False)
    if not ok:
        db.session.rollback()
        flash("发分失败，请重试", "danger")
        return redirect(url_for("admin.daily"))
    log_action("daily_approve", target_type="daily_compliance", target_id=id,
               summary="通过 %s 的日常管理(%s)，发分 %d" % (
                   rec.staff.name if rec.staff else "?", _tab_name(rec.tab_key), reward), commit=False)
    db.session.commit()
    flash("已通过，发放积分 %d" % reward, "success")
    return redirect(url_for("admin.daily"))


@bp.route("/daily/<int:id>/reject", methods=["POST"])
@login_required
def daily_reject(id):
    _admin_only()
    rec = DailyCompliance.query.get_or_404(id)
    if rec.status != "pending":
        return redirect(url_for("admin.daily"))
    rec.status = "rejected"
    rec.reviewer_id = current_user.id
    rec.reviewed_at = datetime.datetime.now()
    rec.reject_reason = request.form.get("reason", "").strip()
    log_action("daily_reject", target_type="daily_compliance", target_id=id,
               summary="驳回 %s 的日常管理(%s)" % (
                   rec.staff.name if rec.staff else "?", _tab_name(rec.tab_key)), commit=False)
    db.session.commit()
    flash("已驳回", "success")
    return redirect(url_for("admin.daily"))


@bp.route("/daily/<int:id>/delete", methods=["POST"])
@login_required
def daily_delete(id):
    """删除日常管理合规照（仅超级管理员）。仅 approved 扣回已发积分。"""
    _super_only()
    rec = DailyCompliance.query.get_or_404(id)
    staff = rec.staff
    pts = rec.points_earned or 0
    deduct = pts if rec.status == "approved" else 0
    if deduct > 0 and staff:
        ok = add_points(staff, -deduct, "daily", ref_id=rec.id,
                        remark="删除日常管理合规照 #%d 扣回" % rec.id, commit=False)
        if not ok:
            db.session.rollback()
            flash("无法删除：%s 积分余额不足，无法扣回 %d" % (staff.name, deduct), "danger")
            return redirect(url_for("admin.daily"))
    summary = "删除日常管理 #%d（%s，状态 %s，扣回 %d）" % (
        id, staff.name if staff else "？", rec.status, deduct)
    db.session.delete(rec)
    log_action("delete_daily", target_type="daily_compliance", target_id=id,
               summary=summary, commit=False)
    db.session.commit()
    flash("已删除，扣回 %d 积分" % deduct, "success")
    return redirect(url_for("admin.daily"))
