namespace Application.Abstractions.Crypto;

public interface IUpbitClient
{
    // Candle (캔들)
    Task<IReadOnlyList<UpbitCandle>> GetSecondCandlesAsync(string market, int count, CancellationToken ct = default);
    Task<IReadOnlyList<UpbitCandle>> GetMinuteCandlesAsync(string market, int unit, int count, CancellationToken ct = default);
    Task<IReadOnlyList<UpbitCandle>> GetDayCandlesAsync(string market, int count, CancellationToken ct = default);
    Task<IReadOnlyList<UpbitCandle>> GetWeekCandlesAsync(string market, int count, CancellationToken ct = default);
    Task<IReadOnlyList<UpbitCandle>> GetMonthCandlesAsync(string market, int count, CancellationToken ct = default);
    Task<IReadOnlyList<UpbitCandle>> GetYearCandlesAsync(string market, int count, CancellationToken ct = default);

    // Market (마켓 목록)
    Task<IReadOnlyList<UpbitMarket>> GetMarketsAsync(CancellationToken ct = default);

    // Ticker (현재가 상세)
    Task<IReadOnlyList<UpbitTickerDetail>> GetTickersAsync(string[] markets, CancellationToken ct = default);

    // Trade (최근 체결 내역)
    Task<IReadOnlyList<UpbitTrade>> GetTradesAsync(string market, int count, CancellationToken ct = default);

    // Orderbook (호가 정보)
    Task<IReadOnlyList<UpbitOrderbook>> GetOrderbookAsync(string[] markets, CancellationToken ct = default);
}

/// <summary>
/// WebSocket 현재가(Ticker) — SIMPLE 포맷
/// https://docs.upbit.com/kr/reference/websocket-ticker
/// </summary>
public sealed record UpbitTicker(
    string Market,                  // 페어(거래쌍)의 코드 (ty: ticker)
    decimal OpeningPrice,           // 시가
    decimal HighPrice,              // 고가
    decimal LowPrice,               // 저가
    decimal TradePrice,             // 현재가
    decimal PrevClosingPrice,       // 전일 종가
    string Change,                  // 전일 대비 (EVEN: 보합, RISE: 상승, FALL: 하락)
    decimal ChangePrice,            // 전일 대비 값
    decimal SignedChangePrice,      // 전일 대비 값 (부호 포함)
    decimal ChangeRate,             // 전일 대비 등락율
    decimal SignedChangeRate,       // 전일 대비 등락율 (부호 포함)
    decimal TradeVolume,            // 가장 최근 거래량
    decimal AccTradeVolume,         // 누적 거래량 (UTC 0시 기준)
    decimal AccTradeVolume24h,      // 24시간 누적 거래량
    decimal AccTradePrice,          // 누적 거래대금 (UTC 0시 기준)
    decimal AccTradePrice24h,       // 24시간 누적 거래대금
    string TradeDate,               // 최근 거래 일자 (UTC, yyyyMMdd)
    string TradeTime,               // 최근 거래 시각 (UTC, HHmmss)
    long TradeTimestamp,            // 체결 타임스탬프 (ms)
    string AskBid,                  // 매수/매도 구분 (ASK: 매도, BID: 매수)
    decimal AccAskVolume,           // 누적 매도량
    decimal AccBidVolume,           // 누적 매수량
    decimal Highest52WeekPrice,     // 52주 신고가
    string Highest52WeekDate,       // 52주 신고가 달성일 (yyyy-MM-dd)
    decimal Lowest52WeekPrice,      // 52주 신저가
    string Lowest52WeekDate,        // 52주 신저가 달성일 (yyyy-MM-dd)
    string MarketState,             // 거래 상태 (PREVIEW, ACTIVE, DELISTED)
    string? DelistingDate,          // 상장폐지일
    string MarketWarning,           // 유의 종목 여부 (NONE, CAUTION)
    long Timestamp,                 // 타임스탬프 (ms)
    string StreamType               // 스트림 타입 (SNAPSHOT, REALTIME)
);

/// <summary>
/// REST/WebSocket 캔들 — 공통 + 타입별 선택 필드
/// https://docs.upbit.com/kr/reference/list-candles-seconds
/// https://docs.upbit.com/kr/reference/list-candles-minutes
/// https://docs.upbit.com/kr/reference/list-candles-days
/// https://docs.upbit.com/kr/reference/list-candles-weeks
/// https://docs.upbit.com/kr/reference/list-candles-months
/// https://docs.upbit.com/kr/reference/list-candles-years
/// </summary>
public sealed record UpbitCandle(
    string Market,                   // 페어(거래쌍)의 코드
    string CandleDateTimeUtc,        // 캔들 기준 시각 (UTC)
    string CandleDateTimeKst,        // 캔들 기준 시각 (KST)
    decimal OpeningPrice,            // 시가
    decimal HighPrice,               // 고가
    decimal LowPrice,                // 저가
    decimal TradePrice,              // 종가 (현재가)
    long Timestamp,                  // 마지막 틱이 저장된 시각 (ms)
    decimal CandleAccTradePrice,     // 누적 거래 금액
    decimal CandleAccTradeVolume,    // 누적 거래량

    // 분(Minutes) 캔들 전용
    int? Unit,                       // 캔들 집계 시간 단위 (분: 1, 3, 5, 10, 15, 30, 60, 240)

    // 일(Days) 캔들 전용
    decimal? PrevClosingPrice,       // 전일 종가 (UTC 0시 기준)
    decimal? ChangePrice,            // 전일 종가 대비 가격 변화
    decimal? ChangeRate,             // 전일 종가 대비 가격 변화율
    decimal? ConvertedTradePrice,    // 종가 환산 화폐 단위로 환산된 가격 (요청 시)

    // 주(Weeks), 월(Months), 연(Years) 캔들 전용
    string? FirstDayOfPeriod         // 캔들 집계 시작일자 (yyyy-MM-dd)
);

/// <summary>
/// 마켓 목록
/// https://docs.upbit.com/kr/reference/list-trading-pairs
/// </summary>
public sealed record UpbitMarket(
    string Market,                   // 페어(거래쌍)의 코드
    string KoreanName,               // 가상자산 한글명
    string EnglishName,              // 가상자산 영문명
    UpbitMarketEvent MarketEvent     // 종목 유의/경보 정보
);

/// <summary>마켓 이벤트 정보 (유의 종목)</summary>
public sealed record UpbitMarketEvent(
    bool Warning,                    // 유의 종목 여부
    UpbitMarketCaution Caution       // 주의 종목 상세
);

/// <summary>마켓 주의 종목 상세</summary>
public sealed record UpbitMarketCaution(
    bool PriceFluctuations,               // 가격 급등락 경보
    bool TradingVolumeSoaring,            // 거래량 급증 경보
    bool DepositAmountSoaring,            // 입금량 급증 경보
    bool GlobalPriceDifferences,          // 국내외 가격 차이 경보
    bool ConcentrationOfSmallAccounts     // 소수 계정 집중 거래 경보
);

/// <summary>
/// REST 현재가(Ticker) 상세
/// https://docs.upbit.com/kr/reference/list-tickers
/// </summary>
public sealed record UpbitTickerDetail(
    string Market,                   // 페어(거래쌍)의 코드
    string TradeDate,                // 최근 거래 일자 (UTC, yyyyMMdd)
    string TradeTime,                // 최근 거래 시각 (UTC, HHmmss)
    string TradeDateKst,             // 최근 거래 일자 (KST, yyyyMMdd)
    string TradeTimeKst,             // 최근 거래 시각 (KST, HHmmss)
    long TradeTimestamp,             // 체결 타임스탬프 (ms)
    decimal OpeningPrice,            // 시가
    decimal HighPrice,               // 고가
    decimal LowPrice,                // 저가
    decimal TradePrice,              // 현재가
    decimal PrevClosingPrice,        // 전일 종가
    string Change,                   // 전일 대비 (EVEN, RISE, FALL)
    decimal ChangePrice,             // 전일 대비 값
    decimal ChangeRate,              // 전일 대비 등락율
    decimal SignedChangePrice,       // 전일 대비 값 (부호 포함)
    decimal SignedChangeRate,        // 전일 대비 등락율 (부호 포함)
    decimal TradeVolume,             // 가장 최근 거래량
    decimal AccTradePrice,           // 누적 거래대금 (UTC 0시 기준)
    decimal AccTradePrice24h,        // 24시간 누적 거래대금
    decimal AccTradeVolume,          // 누적 거래량 (UTC 0시 기준)
    decimal AccTradeVolume24h,       // 24시간 누적 거래량
    decimal Highest52WeekPrice,      // 52주 신고가
    string Highest52WeekDate,        // 52주 신고가 달성일 (yyyy-MM-dd)
    decimal Lowest52WeekPrice,       // 52주 신저가
    string Lowest52WeekDate,         // 52주 신저가 달성일 (yyyy-MM-dd)
    long Timestamp                   // 타임스탬프 (ms)
);

/// <summary>
/// REST 최근 체결 내역
/// https://docs.upbit.com/kr/reference/recent-trades-history
/// </summary>
public sealed record UpbitTrade(
    string Market,                   // 페어(거래쌍)의 코드
    string TradeDateUtc,             // 체결 일자 (UTC)
    string TradeTimeUtc,             // 체결 시각 (UTC)
    long Timestamp,                  // 타임스탬프 (ms)
    decimal TradePrice,              // 체결 가격
    decimal TradeVolume,             // 체결량
    decimal PrevClosingPrice,        // 전일 종가
    decimal ChangePrice,             // 전일 대비 값
    string AskBid,                   // 매수/매도 구분 (ASK: 매도, BID: 매수)
    long SequentialId                // 체결 번호 (Unique)
);

/// <summary>
/// REST 호가 정보
/// https://docs.upbit.com/kr/reference/list-orderbooks
/// </summary>
public sealed record UpbitOrderbook(
    string Market,                   // 페어(거래쌍)의 코드
    decimal TotalAskSize,            // 호가 매도 총 잔량
    decimal TotalBidSize,            // 호가 매수 총 잔량
    IReadOnlyList<UpbitOrderbookUnit> OrderbookUnits, // 호가 리스트
    long Timestamp,                  // 타임스탬프 (ms)
    decimal Level                    // 호가 모아보기 단위
);

/// <summary>호가 단위</summary>
public sealed record UpbitOrderbookUnit(
    decimal AskPrice,                // 매도호가
    decimal BidPrice,                // 매수호가
    decimal AskSize,                 // 매도 잔량
    decimal BidSize                  // 매수 잔량
);