using System;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
using FootwearTest.Models;
using Microsoft.Extensions.Logging;

namespace FootwearTest.Services;

public sealed class ModbusTcpDeviceClient : IDeviceClient
{
    private readonly DeviceSettings _settings;
    private readonly ILogger<ModbusTcpDeviceClient> _logger;
    private TcpClient? _tcpClient;
    private bool _lastReadFailed;

    public ModbusTcpDeviceClient(DeviceSettings settings, ILogger<ModbusTcpDeviceClient> logger)
    {
        _settings = settings;
        _logger = logger;
        LastSnapshot = DeviceSnapshot.Initial with { AlarmText = "Modbus 点表未配置，当前仅验证连接" };
    }

    public bool IsConnected => _tcpClient?.Connected == true;
    public string ConnectionText => IsConnected ? $"Modbus TCP {_settings.Host}:{_settings.Port} 已连接" : "Modbus TCP 未连接";
    public DeviceSnapshot LastSnapshot { get; private set; }
    public event EventHandler<DeviceSnapshot>? SnapshotUpdated;

    public async Task ConnectAsync(CancellationToken cancellationToken = default)
    {
        _logger.LogInformation("Connecting Modbus TCP device. Host={Host}, Port={Port}", _settings.Host, _settings.Port);

        try
        {
            _tcpClient?.Dispose();
            _tcpClient = new TcpClient();
            await _tcpClient.ConnectAsync(_settings.Host, _settings.Port, cancellationToken);
            LastSnapshot = LastSnapshot with { Timestamp = DateTime.Now, AlarmText = "等待配置真实 Modbus 寄存器点表" };
            SnapshotUpdated?.Invoke(this, LastSnapshot);
            _logger.LogInformation("Modbus TCP device connected. Host={Host}, Port={Port}", _settings.Host, _settings.Port);
        }
        catch (Exception ex)
        {
            _tcpClient?.Dispose();
            _tcpClient = null;
            _logger.LogError(ex, "Modbus TCP connection failed. Host={Host}, Port={Port}", _settings.Host, _settings.Port);
            throw;
        }
    }

    public Task DisconnectAsync(CancellationToken cancellationToken = default)
    {
        if (IsConnected)
        {
            _logger.LogInformation("Disconnecting Modbus TCP device. Host={Host}, Port={Port}", _settings.Host, _settings.Port);
        }

        _tcpClient?.Dispose();
        _tcpClient = null;
        return Task.CompletedTask;
    }

    public Task<DeviceSnapshot> ReadSnapshotAsync(CancellationToken cancellationToken = default)
    {
        LastSnapshot = LastSnapshot with { Timestamp = DateTime.Now };
        SnapshotUpdated?.Invoke(this, LastSnapshot);
        if (_lastReadFailed)
        {
            _logger.LogInformation("Modbus snapshot read recovered. Timestamp={Timestamp}", LastSnapshot.Timestamp);
            _lastReadFailed = false;
        }

        return Task.FromResult(LastSnapshot);
    }

    public Task SetOutputsAsync(bool pumpRunning, bool fanRunning, bool heaterRunning, CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "Writing output state to Modbus device placeholder. Pump={PumpRunning}, Fan={FanRunning}, Heater={HeaterRunning}",
            pumpRunning,
            fanRunning,
            heaterRunning);

        LastSnapshot = LastSnapshot with
        {
            Timestamp = DateTime.Now,
            PumpRunning = pumpRunning,
            FanRunning = fanRunning,
            HeaterRunning = heaterRunning
        };
        SnapshotUpdated?.Invoke(this, LastSnapshot);
        return Task.CompletedTask;
    }
}
