from __future__ import annotations

import sqlite3
from calendar import monthrange
from datetime import datetime, timedelta
from typing import Any, Dict, List, Tuple


def period_bounds(period: str, ref_date: str) -> Tuple[str, str]:
    if period == "day":
        return ref_date, ref_date
    if period == "week":
        dt = datetime.strptime(ref_date, "%Y-%m-%d")
        start = (dt - timedelta(days=dt.weekday())).strftime("%Y-%m-%d")
        end = (dt + timedelta(days=6 - dt.weekday())).strftime("%Y-%m-%d")
        return start, end
    if period == "month":
        y, m = map(int, ref_date.split("-")[:2])
        last = monthrange(y, m)[1]
        return f"{ref_date[:7]}-01", f"{ref_date[:7]}-{last:02d}"
    raise ValueError(period)


def _card_use_revenue(conn: sqlite3.Connection, start: str, end: str) -> float:
    """次卡核销额 = card_use 对应服务 catalog 原价合计（PRD §9.1）。"""
    appt_rev = conn.execute(
        """SELECT COALESCE(SUM(cs.price), 0)
           FROM store_payments p
           JOIN store_appointments a ON a.id = p.appt_id
           JOIN catalog_services cs ON cs.name = a.service_name AND cs.status = 'active'
           WHERE p.type = 'card_use'
             AND substr(p.created_at, 1, 10) >= ? AND substr(p.created_at, 1, 10) <= ?""",
        (start, end),
    ).fetchone()[0]
    order_rev = conn.execute(
        """SELECT COALESCE(SUM(ol.line_amount), 0)
           FROM store_payments p
           JOIN store_order_lines ol ON ol.order_id = p.order_id AND ol.kind = 'service'
           WHERE p.type = 'card_use'
             AND substr(p.created_at, 1, 10) >= ? AND substr(p.created_at, 1, 10) <= ?""",
        (start, end),
    ).fetchone()[0]
    return round(float(appt_rev) + float(order_rev), 2)


def _repeat_rate(conn: sqlite3.Connection, start: str, end: str) -> float:
    """复购率：区间内到店 >=2 次的会员 / 到店会员总数。"""
    rows = conn.execute(
        """SELECT member_id, COUNT(*) AS cnt FROM (
             SELECT member_id FROM store_orders
             WHERE status='completed' AND member_id IS NOT NULL
               AND substr(updated_at,1,10) BETWEEN ? AND ?
             UNION ALL
             SELECT member_id FROM store_appointments
             WHERE status='completed' AND member_id IS NOT NULL
               AND substr(updated_at,1,10) BETWEEN ? AND ?
           ) GROUP BY member_id""",
        (start, end, start, end),
    ).fetchall()
    if not rows:
        return 0.0
    repeat = sum(1 for r in rows if int(r["cnt"]) >= 2)
    return round(repeat / len(rows), 4)


def compute_period_metrics(conn: sqlite3.Connection, start: str, end: str) -> Dict[str, Any]:
    pay_rows = conn.execute(
        """SELECT type, SUM(amount) AS total FROM store_payments
           WHERE substr(created_at, 1, 10) >= ? AND substr(created_at, 1, 10) <= ?
           AND type NOT LIKE 'refund_%'
           GROUP BY type""",
        (start, end),
    ).fetchall()
    by_type = {r["type"]: float(r["total"] or 0) for r in pay_rows}
    cash = by_type.get("cash", 0.0)
    consume = by_type.get("consume", 0.0)
    card_use = by_type.get("card_use", 0.0)

    order_rev = conn.execute(
        """SELECT COALESCE(SUM(total_amount), 0) FROM store_orders
           WHERE status = 'completed'
             AND substr(updated_at, 1, 10) >= ? AND substr(updated_at, 1, 10) <= ?""",
        (start, end),
    ).fetchone()[0]

    appt_rev = conn.execute(
        """SELECT COALESCE(SUM(p.amount), 0)
           FROM store_payments p
           JOIN store_appointments a ON a.id = p.appt_id
           WHERE a.status = 'completed'
             AND p.appt_id IS NOT NULL
             AND substr(p.created_at, 1, 10) >= ? AND substr(p.created_at, 1, 10) <= ?
             AND p.type NOT LIKE 'refund_%'""",
        (start, end),
    ).fetchone()[0]

    revenue = float(order_rev) + float(appt_rev)
    if revenue == 0:
        revenue = cash + consume + card_use

    txn_count = conn.execute(
        """SELECT COUNT(*) FROM (
             SELECT id FROM store_orders WHERE status='completed'
               AND substr(updated_at,1,10) BETWEEN ? AND ?
             UNION ALL
             SELECT id FROM store_appointments WHERE status='completed'
               AND substr(updated_at,1,10) BETWEEN ? AND ?
           )""",
        (start, end, start, end),
    ).fetchone()[0]

    visits = conn.execute(
        """SELECT COUNT(DISTINCT member_id) FROM (
             SELECT member_id FROM store_orders WHERE status='completed' AND member_id IS NOT NULL
               AND substr(updated_at,1,10) BETWEEN ? AND ?
             UNION
             SELECT member_id FROM store_appointments WHERE status='completed'
               AND substr(updated_at,1,10) BETWEEN ? AND ?
           )""",
        (start, end, start, end),
    ).fetchone()[0]

    perf_total = conn.execute(
        """SELECT COALESCE(SUM(amount), 0) FROM staff_performance
           WHERE ymd >= ? AND ymd <= ?""",
        (start, end),
    ).fetchone()[0]

    card_use_count = int(
        conn.execute(
            """SELECT COUNT(*) FROM store_payments
               WHERE type='card_use' AND substr(created_at,1,10) BETWEEN ? AND ?""",
            (start, end),
        ).fetchone()[0]
    )
    card_use_revenue = _card_use_revenue(conn, start, end)
    repeat_rate = _repeat_rate(conn, start, end)
    avg_ticket = round(revenue / txn_count, 2) if txn_count else 0.0

    return {
        "start": start,
        "end": end,
        "revenue": round(revenue, 2),
        "cash": round(cash, 2),
        "stored_value": round(consume, 2),
        "card_use_count": card_use_count,
        "card_use_revenue": card_use_revenue,
        "repeat_rate": repeat_rate,
        "payment_mix": {
            "cash": round(cash, 2),
            "consume": round(consume, 2),
            "card_use_count": card_use_count,
            "card_use_revenue": card_use_revenue,
        },
        "transactions": int(txn_count),
        "visits": int(visits),
        "avg_ticket": avg_ticket,
        "performance_total": round(float(perf_total), 2),
    }


def staff_ranking(conn: sqlite3.Connection, month: str) -> List[Dict[str, Any]]:
    y1, m1 = map(int, month.split("-"))
    start = f"{month}-01"
    last = monthrange(y1, m1)[1]
    end = f"{month}-{last:02d}"
    rows = conn.execute(
        """
        SELECT s.id, s.name,
               COALESCE(SUM(p.amount), 0) AS revenue
        FROM staff_staff s
        LEFT JOIN staff_performance p ON p.staff_id = s.id AND p.ymd >= ? AND p.ymd <= ?
        WHERE s.status = 'active'
        GROUP BY s.id
        ORDER BY revenue DESC
        """,
        (start, end),
    ).fetchall()
    return [
        {"rank": i + 1, "staff_id": r["id"], "name": r["name"], "revenue": float(r["revenue"])}
        for i, r in enumerate(rows)
    ]


def report_by_service(conn: sqlite3.Connection, month: str) -> List[Dict[str, Any]]:
    y1, m1 = map(int, month.split("-"))
    start = f"{month}-01"
    last = monthrange(y1, m1)[1]
    end = f"{month}-{last:02d}"
    rows = conn.execute(
        """SELECT service_name AS name, COUNT(*) AS count, COALESCE(SUM(rev), 0) AS revenue
           FROM (
             SELECT a.service_name, cs.price AS rev
             FROM store_appointments a
             JOIN catalog_services cs ON cs.name = a.service_name
             WHERE a.status = 'completed'
               AND substr(a.updated_at, 1, 10) BETWEEN ? AND ?
             UNION ALL
             SELECT ol.ref_name AS service_name, ol.line_amount AS rev
             FROM store_order_lines ol
             JOIN store_orders o ON o.id = ol.order_id
             WHERE ol.kind = 'service' AND o.status = 'completed'
               AND substr(o.updated_at, 1, 10) BETWEEN ? AND ?
           ) GROUP BY service_name ORDER BY revenue DESC""",
        (start, end, start, end),
    ).fetchall()
    return [
        {"service": r["name"], "count": int(r["count"]), "revenue": round(float(r["revenue"]), 2)}
        for r in rows
    ]


def format_report_md(metrics: Dict[str, Any], *, title: str, show_repeat: bool = False) -> str:
    lines = [
        f"# {title}",
        "",
        f"区间：{metrics['start']} ~ {metrics['end']}",
        f"营收 ¥{metrics['revenue']}",
        f"现金实收 ¥{metrics['cash']} | 储值核销 ¥{metrics['stored_value']} | 次卡核销 ¥{metrics['card_use_revenue']}",
        f"到店 {metrics['visits']} 人 | 客单 ¥{metrics['avg_ticket']}",
        f"成交笔数 {metrics['transactions']} | 业绩额 ¥{metrics['performance_total']}",
    ]
    if show_repeat:
        pct = round(float(metrics.get("repeat_rate", 0)) * 100, 1)
        lines.append(f"复购率 {pct}%")
    return "\n".join(lines)
