// ============================================================
// kline.entity.ts — TimescaleDB K 线 Hypertable 实体
// ============================================================
// 映射到 PostgreSQL klines 表（TimescaleDB hypertable）。
// 不继承 CommonBaseEntity — 使用 @timescaledb/typeorm 的
// @Hypertable / @TimeColumn 装饰器管理 TimescaleDB 特性。
//
// 关键 TimescaleDB 特性（由 @Hypertable 装饰器自动配置）：
//   - 自动按 time 列做时间分区（by_range）
//   - 列式压缩（compress），30 天后自动执行
//   - 通过 ContinuousAggregate 生成高周期 K 线视图
//
// 注意：@timescaledb/typeorm v0.0.1 为实验版本，
// 不支持空间分区（partitioning_column）。
// 若需要空间分区，可通过 db/init-db/ 下的 SQL 脚本手动添加。
// ============================================================

import { Hypertable, TimeColumn } from "@timescaledb/typeorm";
import {
    Entity,
    PrimaryColumn,
    Column,
    CreateDateColumn,
    UpdateDateColumn,
} from "typeorm";

import type { KlineInterval, PairType } from '../../types';

/**
 * 1 分钟 K 线 Hypertable
 *
 * 存储交易所推送的 OHLCV 数据。写入使用 UPSERT
 * （ON CONFLICT DO UPDATE），已存在的 K 线只更新
 * high/low/close/volume 增量。
 *
 * 高周期 K 线（5m+）通过 TimescaleDB 连续聚合视图
 * 从 1m 表自动生成，无需单独建表。
 */
@Hypertable({
    compression: {
        compress: true,
        compress_orderby: "time DESC",
        compress_segmentby: "exchange, symbol, type",
        policy: {
            schedule_interval: "30 days", // 30 天后自动压缩
        },
    },
})
@Entity("klines")
export class Kline {
    /**
     * 复合主键：交易所 + 交易对 + 周期 + 时间
     *
     * 设计原因：
     *   - 不同 symbol 在同一时刻有各自的 K 线，单列 time PK 会导致跨 symbol 冲突
     *   - 四列复合主键 = 业务唯一性语义，同时满足 TimescaleDB hypertable 要求
     *     （分区列 time 必须包含在主键中）
     *   - 不再需要额外的 @Index unique — 复合主键已保证唯一性
     */
    /** 交易所标识（binance / okx / bybit） */
    @PrimaryColumn("text")
    exchange!: string;

    /** 交易对符号（如 BTCUSDT） */
    @PrimaryColumn("text")
    symbol!: string;

    /** 交易对类型（如 spot） */
    @PrimaryColumn("text", { default: 'spot' })
    type!: PairType;

    /** K 线周期（1m） */
    @PrimaryColumn("text")
    interval!: KlineInterval;

    /** K 线开盘时间（UTC）— @timescaledb/typeorm 自动标记为时间分区列 */
    @TimeColumn()
    @PrimaryColumn("timestamptz")
    time!: Date;

    // ============================================================
    // OHLCV 价格数据（NUMERIC(20,8) 精度，与交易所对齐）
    // ============================================================

    /** 开盘价 */
    @Column("numeric", { precision: 20, scale: 8 })
    open!: number;

    /** 最高价 */
    @Column("numeric", { precision: 20, scale: 8 })
    high!: number;

    /** 最低价 */
    @Column("numeric", { precision: 20, scale: 8 })
    low!: number;

    /** 收盘价 */
    @Column("numeric", { precision: 20, scale: 8 })
    close!: number;

    /** 成交量（base 币种） */
    @Column("numeric", { precision: 20, scale: 8 })
    volume!: number;

    // ============================================================
    // 扩展字段（Binance 等交易所提供）
    // ============================================================

    /** 成交额（quote 币种） */
    @Column("numeric", { precision: 20, scale: 8, nullable: true })
    quote_volume?: number;

    /** 主动买入成交量（base 币种） */
    @Column("numeric", { precision: 20, scale: 8, nullable: true })
    taker_buy_base_vol?: number;

    /** 主动买入成交额（quote 币种） */
    @Column("numeric", { precision: 20, scale: 8, nullable: true })
    taker_buy_quote_vol?: number;

    /** 成交笔数 */
    @Column("integer", { nullable: true })
    trade_count?: number;

    /** K 线是否已关闭（true = 该周期 K 线不再变化） */
    @Column("boolean", { default: true })
    is_closed!: boolean;

    // ============================================================
    // 审计字段
    // ============================================================

    /** 记录首次写入时间 */
    @CreateDateColumn({ type: "timestamptz", name: "created_at" })
    createdAt!: Date;

    /** 记录最后更新时间 */
    @UpdateDateColumn({ type: "timestamptz", name: "updated_at" })
    updatedAt!: Date;
}
