namespace Synor.Sdk.Mining;

public enum DeviceType { Cpu, GpuNvidia, GpuAmd, Asic }
public enum DeviceStatus { Idle, Mining, Error, Offline }
public enum ConnectionStatus { Disconnected, Connecting, Connected, Reconnecting }
public enum TimePeriod { Hour, Day, Week, Month, All }
public enum SubmitStatus { Accepted, Rejected, Stale }

public record MiningConfig(
    string ApiKey,
    string Endpoint = "https://mining.synor.io/v1",
    TimeSpan? Timeout = null,
    int Retries = 3,
    bool Debug = false
) {
    public TimeSpan Timeout { get; init; } = Timeout ?? TimeSpan.FromSeconds(60);
}

public record PoolConfig(
    string Url,
    string User,
    string? Password = null,
    string? Algorithm = null,
    double? Difficulty = null
);

public record StratumConnection(
    string Id,
    string Pool,
    ConnectionStatus Status,
    string Algorithm,
    double Difficulty,
    long ConnectedAt,
    int AcceptedShares,
    int RejectedShares,
    int StaleShares,
    long? LastShareAt = null
);

public record PoolStats(
    string Url,
    int Workers,
    double Hashrate,
    double Difficulty,
    long LastBlock,
    int BlocksFound24h,
    double Luck
);

public record TemplateTransaction(
    string Txid,
    string Data,
    string Fee,
    int Weight
);

public record BlockTemplate(
    string Id,
    string PreviousBlockHash,
    string MerkleRoot,
    long Timestamp,
    string Bits,
    long Height,
    string CoinbaseValue,
    List<TemplateTransaction> Transactions,
    string Target,
    string Algorithm,
    string ExtraNonce
);

public record MinedWork(
    string TemplateId,
    string Nonce,
    string ExtraNonce,
    long Timestamp,
    string Hash
);

public record ShareInfo(
    string Hash,
    double Difficulty,
    long Timestamp,
    bool Accepted
);

public record SubmitResult(
    SubmitStatus Status,
    ShareInfo Share,
    bool BlockFound,
    string? Reason = null,
    string? BlockHash = null,
    string? Reward = null
);

public record Hashrate(
    double Current,
    double Average1h,
    double Average24h,
    double Peak,
    string Unit
);

public record ShareStats(
    int Accepted,
    int Rejected,
    int Stale,
    int Total,
    double AcceptRate
);

public record DeviceTemperature(
    double Current,
    double Max,
    bool Throttling
);

public record EarningsSnapshot(
    string Today,
    string Yesterday,
    string ThisWeek,
    string ThisMonth,
    string Total,
    string Currency
);

public record MiningStats(
    Hashrate Hashrate,
    ShareStats Shares,
    long Uptime,
    double Efficiency,
    EarningsSnapshot Earnings,
    double? PowerConsumption = null,
    DeviceTemperature? Temperature = null
);

public record EarningsBreakdown(
    long Date,
    string Amount,
    int Blocks,
    int Shares,
    double Hashrate
);

public record Earnings(
    TimePeriod Period,
    long StartDate,
    long EndDate,
    string Amount,
    int Blocks,
    int Shares,
    double AverageHashrate,
    string Currency,
    List<EarningsBreakdown> Breakdown
);

public record MiningDevice(
    string Id,
    string Name,
    DeviceType Type,
    DeviceStatus Status,
    double Hashrate,
    double Temperature,
    double FanSpeed,
    double PowerDraw,
    long MemoryUsed,
    long MemoryTotal,
    string? Driver = null,
    string? Firmware = null
);

public record DeviceConfig(
    bool Enabled,
    int? Intensity = null,
    int? PowerLimit = null,
    int? CoreClockOffset = null,
    int? MemoryClockOffset = null,
    int? FanSpeed = null
);

public record WorkerInfo(
    string Id,
    string Name,
    ConnectionStatus Status,
    Hashrate Hashrate,
    ShareStats Shares,
    List<MiningDevice> Devices,
    long LastSeen,
    long Uptime
);

public record MiningAlgorithm(
    string Name,
    string DisplayName,
    string HashUnit,
    string Profitability,
    double Difficulty,
    string BlockReward,
    int BlockTime
);

// Response wrappers
internal record DevicesResponse(List<MiningDevice>? Devices);
internal record WorkersResponse(List<WorkerInfo>? Workers);
internal record AlgorithmsResponse(List<MiningAlgorithm>? Algorithms);
internal record MiningStatusResponse(bool Mining);
internal record MiningHealthResponse(string Status);

public class MiningException : Exception
{
    public string? Code { get; }
    public int StatusCode { get; }

    public MiningException(string message, string? code = null, int statusCode = 0)
        : base(message)
    {
        Code = code;
        StatusCode = statusCode;
    }
}
