from requests import get
import time
import os
import pandas as pd
import tqdm
from datetime import datetime, timedelta

teamId = 19
ip = "http://band.hxzhxy.cn"
param = {
    "username": "xtl",
    "password": "xia123456",
    "client_id": "client",
    "grant_type": "password",
    "client_secret": "123456",
}

data = get(url=f"{ip}/oauth/token", params=param).json()
token = data["access_token"]
header = {
    "content-type": "application/json",
    "authorization": f"Bearer {token}",
}

url = f"{ip}/pay/trads/findPayTtadsNews"
output_dir = r"e:\project\python\工具\智慧校园\本部\消费数据\24-26消费信息"

FIELD_MAP = {
    "gradeName": "年级名称",
    "termName": "交易地点",
    "teamId": "团队ID",
    "stuId": "学生ID",
    "areaName": "设备区域名称",
    "bagName": "交易账户",
    "userNumb": "学号/工号",
    "dealCount": "交易流水号/笔次",
    "className": "班级名称",
    "remark": "备注/充值类型",
    "cardCode": "物理卡号",
    "dealType": "消费方式",
    "cardValue": "余额",
    "userXm": "姓名",
    "cardNo": "卡号",
    "createDate": "入库时间",
    "dealValue": "交易金额",
    "recordType": "记录类型",
    "id": "记录ID",
    "recordId": "终端原始记录ID",
    "userId": "用户唯一ID",
    "dealTime": "交易时间"
}

OUTPUT_COLUMNS = list(FIELD_MAP.values())


def day_range(start_date, end_date):
    current = start_date
    while current <= end_date:
        yield current
        current += timedelta(days=1)


def month_range(start_date, end_date):
    current = datetime(start_date.year, start_date.month, 1)
    end_month = datetime(end_date.year, end_date.month, 1)
    while current <= end_month:
        yield current
        if current.month == 12:
            current = datetime(current.year + 1, 1, 1)
        else:
            current = datetime(current.year, current.month + 1, 1)


def to_timestamp_ms(dt):
    return int(dt.timestamp() * 1000)


def fetch_day_records(day_dt):
    day_start = datetime(day_dt.year, day_dt.month, day_dt.day, 0, 0, 0)
    day_end = datetime(day_dt.year, day_dt.month, day_dt.day, 23, 59, 59)

    begin_time = to_timestamp_ms(day_start)
    end_time = to_timestamp_ms(day_end)

    page_number = 0
    page_size = 100
    day_records = []

    while True:
        params = {
            "teamId": teamId,
            "pageNumber": page_number,
            "pageSize": page_size,
            "screen": 1,
            "beginTime": begin_time,
            "endTime": end_time,
            "name": "",
            "recordType": 1,
            "termName": "",
            "type": 1,
            "classId": "",
            "gradeId": ""
        }

        resp = get(url=url, params=params, headers=header, timeout=60)
        resp.raise_for_status()
        result = resp.json()

        if not result.get("success"):
            raise Exception(f"接口返回失败: {result}")

        data = result.get("data") or {}
        content = data.get("content") or []
        total_pages = data.get("totalPages", 0)
        total_elements = data.get("totalElements", 0)

        day_records.extend(content)

        print(
            f"{day_dt.strftime('%Y-%m-%d')} 第 {page_number + 1}/{max(total_pages, 1)} 页，"
            f"当前页 {len(content)} 条，当天累计 {len(day_records)} 条，总计 {total_elements} 条"
        )

        page_number += 1
        if page_number >= total_pages or total_pages == 0:
            break

        time.sleep(0.1)

    return day_records


def parse_date(date_str):
    return datetime.strptime(date_str, "%Y-%m-%d")


def convert_records_to_df(records):
    rows = []
    for record in records:
        row = {}
        for en_key, cn_key in FIELD_MAP.items():
            row[cn_key] = record.get(en_key)
        rows.append(row)
    if not rows:
        return pd.DataFrame(columns=OUTPUT_COLUMNS)
    return pd.DataFrame(rows, columns=OUTPUT_COLUMNS)


def get_month_start_end(month_dt, start_date, end_date):
    month_start = datetime(month_dt.year, month_dt.month, 1)
    if month_dt.month == 12:
        next_month = datetime(month_dt.year + 1, 1, 1)
    else:
        next_month = datetime(month_dt.year, month_dt.month + 1, 1)
    month_end = next_month - timedelta(days=1)

    if month_start < start_date:
        month_start = start_date
    if month_end > end_date:
        month_end = end_date

    return month_start, month_end


def save_month_excel(month_dt, records):
    df = convert_records_to_df(records)
    file_name = f"{month_dt.strftime('%Y%m')}_学生消费记录.xlsx"
    file_path = os.path.join(output_dir, file_name)
    df.to_excel(file_path, index=False)
    return file_path, len(df)


def main():
    print("开始拉取数据...")
    start_date_str = os.getenv("START_DATE", "2024-01-01")
    end_date_str = os.getenv("END_DATE", "2026-05-19")

    start_date = parse_date(start_date_str)
    end_date = parse_date(end_date_str)

    all_month_list = list(month_range(start_date, end_date))
    total_records = 0
    success_months = 0

    with tqdm.tqdm(all_month_list, desc="按月拉取消费记录") as month_pbar:
        for month_dt in month_pbar:
            try:
                month_start, month_end = get_month_start_end(month_dt, start_date, end_date)
                month_records = []
                month_days = list(day_range(month_start, month_end))

                for day_dt in month_days:
                    day_records = fetch_day_records(day_dt)
                    month_records.extend(day_records)
                    time.sleep(0.2)

                file_path, count = save_month_excel(month_dt, month_records)
                total_records += count
                success_months += 1
                month_pbar.set_postfix({
                    "month": month_dt.strftime("%Y-%m"),
                    "count": count,
                    "total": total_records
                })
                print(f"已输出: {file_path}")
            except Exception as e:
                print(f"{month_dt.strftime('%Y-%m')} 拉取失败: {e}")

    print("\n完成")
    print(f"成功月份: {success_months}")
    print(f"总记录数: {total_records}")
    print(f"输出目录: {output_dir}")


if __name__ == "__main__":
    main()
