using System.Text.Json;
using Health.Application.AI;
using Health.Application.Exercises;
using Health.Application.HealthArchives;
using Health.Application.HealthRecords;
using Health.Application.Medications;
using Health.Infrastructure.AI.AgentHandlers;

namespace Health.Infrastructure.AI;

public sealed class AiToolExecutionService(
    AppDbContext db,
    VisionClient visionClient,
    IHealthArchiveService healthArchives,
    IHealthRecordService healthRecords,
    IExerciseService exercises,
    IMedicationService medications,
    IAiWriteConfirmationStore confirmations) : IAiToolExecutionService
{
    private readonly AppDbContext _db = db;
    private readonly VisionClient _visionClient = visionClient;
    private readonly IHealthArchiveService _healthArchives = healthArchives;
    private readonly IHealthRecordService _healthRecords = healthRecords;
    private readonly IExerciseService _exercises = exercises;
    private readonly IMedicationService _medications = medications;
    private readonly IAiWriteConfirmationStore _confirmations = confirmations;

    public async Task<object> ExecuteAsync(string toolName, string arguments, Guid userId, CancellationToken ct)
    {
        using var json = JsonDocument.Parse(arguments);
        var root = json.RootElement;
        return await (toolName switch
        {
            "record_health_data" => HealthDataAgentHandler.Execute(toolName, root, userId, _healthRecords),
            "query_health_records" => CommonAgentHandler.Execute(toolName, root, userId, _healthRecords, _healthArchives, ct),
            "check_archive" => CommonAgentHandler.Execute(toolName, root, userId, _healthRecords, _healthArchives, ct),
            "manage_medication" => MedicationAgentHandler.Execute(toolName, root, userId, _medications, ct),
            "analyze_report" => ReportAgentHandler.AnalyzeReport(_db, userId, root, _visionClient),
            "manage_exercise" => ExerciseAgentHandler.Execute(toolName, root, _db, userId, _exercises, ct),
            "manage_archive" => CommonAgentHandler.ExecuteManageArchive(_healthArchives, userId, root, ct),
            _ => Task.FromResult<object>(new { success = false, message = $"未知工具: {toolName}" }),
        });
    }

    public async Task<AiConfirmedWriteResult> ConfirmAsync(Guid commandId, Guid userId, CancellationToken ct)
    {
        await using var transaction = await _db.Database.BeginTransactionAsync(ct);
        var command = await _confirmations.TakeAsync(commandId, userId, ct);
        if (command == null)
            return new AiConfirmedWriteResult(40004, null, "确认请求不存在、已执行或已过期");

        try
        {
            var result = await ExecuteAsync(command.ToolName, command.Arguments, userId, ct);
            if (!Succeeded(result, out var error))
            {
                await transaction.RollbackAsync(ct);
                return new AiConfirmedWriteResult(40001, result, error ?? "写入失败，请检查内容后重试");
            }
            await _confirmations.CompleteAsync(command, ct);
            await transaction.CommitAsync(ct);
            return new AiConfirmedWriteResult(0, result, null);
        }
        catch (Exception ex)
        {
            await transaction.RollbackAsync(ct);
            return new AiConfirmedWriteResult(50001, null, $"写入失败: {ex.Message}");
        }
    }

    private static bool Succeeded(object result, out string? error)
    {
        using var json = JsonDocument.Parse(JsonSerializer.Serialize(result));
        var root = json.RootElement;
        error = root.TryGetProperty("message", out var message) ? message.GetString() : null;
        return !root.TryGetProperty("success", out var success) || success.ValueKind != JsonValueKind.False;
    }
}
