using System;

namespace Hc900Crawler.Core.Application.Services;

/// <summary>
/// 전체 파이프라인에서 KST 기준 시간을 단일 제공.
/// 테스트 시 고정 시간 주입 가능 (IClock).
/// </summary>
public interface IClock
{
    DateTimeOffset UtcNow { get; }
}

/// <summary>
/// 시스템 클록 - 실제 서버 시간 사용
/// </summary>
public class SystemClock : IClock
{
    public DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
}

/// <summary>
/// 테스트용 고정 시계
/// </summary>
public class FixedClock(DateTimeOffset fixedUtc) : IClock
{
    public DateTimeOffset UtcNow => fixedUtc;
}

/// <summary>
/// KST 시간대 변환기
/// 모든 "지금", "오늘"의 기준을 한 곳에서 제공합니다.
/// </summary>
public class KstClock(IClock clock)
{
    public static readonly TimeZoneInfo Kst =
        TimeZoneInfo.FindSystemTimeZoneById(
            OperatingSystem.IsWindows()
                ? "Korea Standard Time"   // Windows
                : "Asia/Seoul");          // Linux (Ubuntu)

    // ── 기준 시각 ────────────────────────────────────────────────
    /// <summary>KST 현재 시각</summary>
    public DateTimeOffset KstNow
        => TimeZoneInfo.ConvertTime(clock.UtcNow, Kst);

    /// <summary>KST 오늘 00:00:00 → UTC</summary>
    public DateTimeOffset TodayKstStartUtc
        => ToUtc(KstNow.Date);

    /// <summary>KST 어제 00:00:00 → UTC</summary>
    public DateTimeOffset YesterdayKstStartUtc
        => ToUtc(KstNow.Date.AddDays(-1));

    // ── 변환 유틸 ────────────────────────────────────────────────
    /// <summary>KST DateTime → UTC DateTimeOffset</summary>
    public DateTimeOffset ToUtc(DateTime kstDateTime)
    {
        // Kind가 Unspecified면 KST로 간주
        var unspecified = DateTime.SpecifyKind(kstDateTime, DateTimeKind.Unspecified);
        return TimeZoneInfo.ConvertTimeToUtc(unspecified, Kst);
    }

    /// <summary>UTC DateTimeOffset → KST DateTime</summary>
    public DateTime ToKst(DateTimeOffset utc)
        => TimeZoneInfo.ConvertTime(utc, Kst).DateTime;

    /// <summary>PostgreSQL TIMESTAMPTZ 리터럴 생성 (항상 UTC+0 명시)</summary>
    public string ToSqlLiteral(DateTime kstDateTime)
    {
        var utc = ToUtc(kstDateTime);
        return $"'{utc:yyyy-MM-dd HH:mm:ss}+00'";
    }

    /// <summary>상대 INTERVAL은 변환 불필요 — NOW()는 DB 서버 UTC 기준</summary>
    public static string ToIntervalCondition(string col, string interval)
        => $"{col} >= NOW() - INTERVAL '{interval}'";
}
