using System;
using System.Collections.ObjectModel;
using System.Text.Json;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Input;
using FootwearTest.Models;
using FootwearTest.Services;
using Microsoft.Extensions.Logging;

namespace FootwearTest.ViewModels;

public partial class MethodBViewModel : ViewModelBase
{
    private readonly IDeviceClient _deviceClient;
    private readonly DeviceSettings _settings;
    private readonly TestFormulaService _formulaService;
    private readonly TestRunRepository _repository;
    private readonly ILogger<MethodBViewModel> _logger;

    public MethodBViewModel(
        IDeviceClient deviceClient,
        DeviceSettings settings,
        TestFormulaService formulaService,
        TestRunRepository repository,
        ILogger<MethodBViewModel> logger)
    {
        _deviceClient = deviceClient;
        _settings = settings;
        _formulaService = formulaService;
        _repository = repository;
        _logger = logger;
        RunMoistureCommand = new AsyncRelayCommand(RunMoistureAsync);
        RunWarmthCommand = new AsyncRelayCommand(RunWarmthAsync);
    }

    public ObservableCollection<string> ProcedureLog { get; } = [];
    public IAsyncRelayCommand RunMoistureCommand { get; }
    public IAsyncRelayCommand RunWarmthCommand { get; }

    private string _sampleDescription = "满帮鞋同号两只";
    private string _statusText = "待机";
    private string _moistureResultText = "尚未计算";
    private string _warmthResultText = "尚未计算";
    private string _moistureDetailText = "m180、T180*、XT180* 完成后显示。";
    private string _warmthDetailText = "Q、R 完成后显示。";
    private double _m11 = 6.00;
    private double _m12 = 7.10;
    private double _m21 = 14.00;
    private double _m22 = 16.40;
    private double _m31 = 410.00;
    private double _m32 = 413.20;
    private double _m41 = 18.00;
    private double _m42 = 19.00;
    private double _m51 = 100.00;
    private double _m52 = 84.70;
    private double _m61 = 100.00;
    private double _m62 = 99.80;
    private double _m71 = 100.00;
    private double _m72 = 99.78;
    private double _warmthEnergyKilojoules = 48.2;
    private double _warmthSeconds = 10800;

    public string SampleDescription { get => _sampleDescription; set => SetProperty(ref _sampleDescription, value); }
    public string StatusText { get => _statusText; set => SetProperty(ref _statusText, value); }
    public string MoistureResultText { get => _moistureResultText; set => SetProperty(ref _moistureResultText, value); }
    public string WarmthResultText { get => _warmthResultText; set => SetProperty(ref _warmthResultText, value); }
    public string MoistureDetailText { get => _moistureDetailText; set => SetProperty(ref _moistureDetailText, value); }
    public string WarmthDetailText { get => _warmthDetailText; set => SetProperty(ref _warmthDetailText, value); }
    public double M11 { get => _m11; set => SetProperty(ref _m11, value); }
    public double M12 { get => _m12; set => SetProperty(ref _m12, value); }
    public double M21 { get => _m21; set => SetProperty(ref _m21, value); }
    public double M22 { get => _m22; set => SetProperty(ref _m22, value); }
    public double M31 { get => _m31; set => SetProperty(ref _m31, value); }
    public double M32 { get => _m32; set => SetProperty(ref _m32, value); }
    public double M41 { get => _m41; set => SetProperty(ref _m41, value); }
    public double M42 { get => _m42; set => SetProperty(ref _m42, value); }
    public double M51 { get => _m51; set => SetProperty(ref _m51, value); }
    public double M52 { get => _m52; set => SetProperty(ref _m52, value); }
    public double M61 { get => _m61; set => SetProperty(ref _m61, value); }
    public double M62 { get => _m62; set => SetProperty(ref _m62, value); }
    public double M71 { get => _m71; set => SetProperty(ref _m71, value); }
    public double M72 { get => _m72; set => SetProperty(ref _m72, value); }
    public double WarmthEnergyKilojoules { get => _warmthEnergyKilojoules; set => SetProperty(ref _warmthEnergyKilojoules, value); }
    public double WarmthSeconds { get => _warmthSeconds; set => SetProperty(ref _warmthSeconds, value); }

    private async Task RunMoistureAsync()
    {
        try
        {
            _logger.LogInformation("Method B moisture test started. SampleDescription={SampleDescription}", SampleDescription);
            await EnsureConnectedAsync();
            ProcedureLog.Clear();
            StatusText = "方法 B 吸湿透水汽流程运行中";
            ProcedureLog.Add("固定假脚并定位鞋头至风扇 450±10 mm。");
            ProcedureLog.Add("预热并排空水管空气，确认 C1/C2/C3 称重。");
            await _deviceClient.SetOutputsAsync(false, true, true);
            await Task.Delay(250);
            ProcedureLog.Add("恢复假脚温度稳定，启动泵并进入 180 min 正式周期。");
            await _deviceClient.SetOutputsAsync(true, true, true);
            await Task.Delay(500);
            ProcedureLog.Add("模拟 180 min 周期完成，关闭泵、风扇及温控。");
            await _deviceClient.SetOutputsAsync(false, false, false);

            var result = _formulaService.CalculateMethodBMoisture(M11, M12, M21, M22, M31, M32, M41, M42, M51, M52, M61, M62, M71, M72);
            MoistureResultText = result.IsValid
                ? $"T180*={result.T180Corrected:F2} g，XT180*={result.XT180Corrected:F2} g，m180={result.M180:F2} g"
                : $"m180={result.M180:F2} g，超出 15±0.9 g，结果作废";
            MoistureDetailText =
                $"m1={result.M1:F3} g，m2={result.M2:F3} g，m3={result.M3:F3} g，m4={result.M4:F3} g\n" +
                $"m5={result.M5:F3} g，m6={result.M6:F3} g，m7={result.M7:F3} g，m8={result.M8:F3} g，T180={result.T180:F3} g";
            StatusText = result.IsValid ? "吸湿透水汽测试完成" : "吸湿透水汽测试需重测";

            var id = await SaveRunAsync("方法 B - 吸湿透水汽性能", MoistureResultText, result, result.IsValid);
            _logger.LogInformation("Method B moisture test completed. RecordId={RecordId}, IsValid={IsValid}, Result={Result}", id, result.IsValid, MoistureResultText);
        }
        catch (Exception ex)
        {
            StatusText = $"吸湿透水汽测试失败: {ex.Message}";
            _logger.LogError(ex, "Method B moisture test failed. SampleDescription={SampleDescription}", SampleDescription);
            await StopOutputsAfterFailureAsync("方法 B 吸湿透水汽失败后关闭输出");
        }
    }

    private async Task RunWarmthAsync()
    {
        try
        {
            _logger.LogInformation("Method B warmth test started. SampleDescription={SampleDescription}", SampleDescription);
            await EnsureConnectedAsync();
            ProcedureLog.Clear();
            StatusText = "方法 B 保暖性能流程运行中";
            ProcedureLog.Add("密封假脚微径管道，穿戴模拟皮肤、标准长筒袜和样品鞋。");
            ProcedureLog.Add("开启风扇和温控，稳定到 38±1 ℃。");
            await _deviceClient.SetOutputsAsync(false, true, true);
            await Task.Delay(500);
            ProcedureLog.Add("记录两个 180 min 周期能量消耗，生成热阻结果。");
            await _deviceClient.SetOutputsAsync(false, false, false);

            var result = _formulaService.CalculateMethodBWarmth(
                WarmthEnergyKilojoules,
                WarmthSeconds,
                _settings.FootAreaSquareMeters,
                _settings.MethodBWarmthTargetTemperatureC,
                _settings.EnvironmentTemperatureC);
            WarmthResultText = $"Q={result.HeatWatts:F3} W，R={result.ThermalResistance:F3} m²·℃/W";
            WarmthDetailText = $"P={result.EnergyKilojoules:F1} kJ，t={result.Seconds:F0} s，Tf={result.FootTemperatureC:F2} ℃，Tc={result.ChamberTemperatureC:F2} ℃";
            StatusText = "保暖性能测试完成";

            var id = await SaveRunAsync("方法 B - 保暖性能", WarmthResultText, result, true);
            _logger.LogInformation("Method B warmth test completed. RecordId={RecordId}, Result={Result}", id, WarmthResultText);
        }
        catch (Exception ex)
        {
            StatusText = $"保暖性能测试失败: {ex.Message}";
            _logger.LogError(ex, "Method B warmth test failed. SampleDescription={SampleDescription}", SampleDescription);
            await StopOutputsAfterFailureAsync("方法 B 保暖性能失败后关闭输出");
        }
    }

    private async Task EnsureConnectedAsync()
    {
        if (!_deviceClient.IsConnected)
        {
            await _deviceClient.ConnectAsync();
        }
    }

    private async Task StopOutputsAfterFailureAsync(string reason)
    {
        try
        {
            await _deviceClient.SetOutputsAsync(false, false, false);
            _logger.LogWarning("Outputs forced off after Method B failure. Reason={Reason}", reason);
        }
        catch (Exception stopEx)
        {
            _logger.LogError(stopEx, "Failed to force outputs off after Method B failure. Reason={Reason}", reason);
        }
    }

    private async Task<long> SaveRunAsync(string method, string summary, object result, bool isValid)
    {
        var data = JsonSerializer.Serialize(new
        {
            Result = result,
            Masses = new { M11, M12, M21, M22, M31, M32, M41, M42, M51, M52, M61, M62, M71, M72 },
            ProcedureLog
        }, new JsonSerializerOptions { WriteIndented = true });

        return await _repository.SaveAsync(new TestRunRecord(
            0,
            method,
            SampleDescription,
            $"环境 {_settings.EnvironmentTemperatureC:F1} ℃ / {_settings.EnvironmentHumidityPercent:F0}%；风速 {_settings.MethodBAirSpeedMetersPerSecond:F2} m/s；周期 180 min",
            summary,
            data,
            isValid,
            DateTime.Now));
    }
}
