using Health.Application.HealthArchives;
using Health.Application.HealthRecords;

namespace Health.Infrastructure.AI.AgentHandlers;

/// <summary>
/// 共享工具处理器——被多个 Agent 引用的通用工具
/// </summary>
public static class CommonAgentHandler
{
    public static readonly ToolDefinition QueryHealthRecordsTool = new()
    {
        Function = new()
        {
            Name = "query_health_records", Description = "查询近期健康数据",
            Parameters = new { type = "object", properties = new { type = new { type = "string" }, days = new { type = "integer" } } }
        }
    };

    public static readonly ToolDefinition CheckArchiveTool = new()
    {
        Function = new() { Name = "check_archive", Description = "查询患者健康档案", Parameters = new { type = "object", properties = new { } } }
    };

    public static List<ToolDefinition> Tools => [QueryHealthRecordsTool, CheckArchiveTool];

    public static async Task<object> Execute(
        string toolName,
        JsonElement args,
        Guid userId,
        IHealthRecordService healthRecords,
        IHealthArchiveService archives,
        CancellationToken ct = default)
    {
        return toolName switch
        {
            "query_health_records" => await ExecuteQueryHealthRecords(healthRecords, userId, args, ct),
            "check_archive" => await ExecuteCheckArchive(archives, userId, ct),
            _ => new { success = false, message = $"未知工具: {toolName}" }
        };
    }

    private static async Task<object> ExecuteQueryHealthRecords(IHealthRecordService healthRecords, Guid userId, JsonElement args, CancellationToken ct)
    {
        var type = args.TryGetProperty("type", out var t) ? t.GetString() : null;
        var days = args.TryGetProperty("days", out var d) ? d.GetInt32() : 7;
        var records = await healthRecords.GetRecordsAsync(userId, type, days, ct);
        return new { count = records.Count, records };
    }

    private static async Task<object> ExecuteCheckArchive(IHealthArchiveService archives, Guid userId, CancellationToken ct)
    {
        var archive = await archives.GetAsync(userId, ct);
        if (archive == null) return new { found = false };
        return new
        {
            found = true, archive.Diagnosis, archive.SurgeryType,
            SurgeryDate = archive.SurgeryDate?.ToString("yyyy-MM-dd"), archive.Surgeries,
            archive.Allergies, archive.DietRestrictions, archive.ChronicDiseases, archive.FamilyHistory,
        };
    }

    public static readonly ToolDefinition ManageArchiveTool = new()
    {
        Function = new()
        {
            Name = "manage_archive", Description = "管理用户健康档案",
            Parameters = new
            {
                type = "object",
                properties = new
                {
                    action = new { type = "string", description = "update_diagnosis/update_surgery/update_allergies/update_chronic_diseases/update_diet_restrictions/query" },
                    diagnosis = new { type = "string" },
                    surgery_type = new { type = "string" },
                    surgery_date = new { type = "string" },
                    allergies = new { type = "array", items = new { type = "string" } },
                    chronic_diseases = new { type = "array", items = new { type = "string" } },
                    diet_restrictions = new { type = "array", items = new { type = "string" } },
                },
                required = new[] { "action" }
            }
        }
    };

    public static Task<object> ExecuteManageArchive(
        IHealthArchiveService archives,
        Guid userId,
        JsonElement args,
        CancellationToken ct = default)
    {
        var action = args.TryGetProperty("action", out var a) ? a.GetString()! : "query";
        var request = new HealthArchiveUpdateRequest(
            args.TryGetProperty("diagnosis", out var diagnosis) ? diagnosis.GetString() : null,
            args.TryGetProperty("surgery_type", out var surgeryType) ? surgeryType.GetString() : null,
            args.TryGetProperty("surgery_date", out var surgeryDate) && DateOnly.TryParse(surgeryDate.GetString(), out var date) ? date : null,
            ReadStringArray(args, "allergies"),
            ReadStringArray(args, "diet_restrictions"),
            ReadStringArray(args, "chronic_diseases"),
            args.TryGetProperty("family_history", out var familyHistory) ? familyHistory.GetString() : null);
        return archives.ExecuteAiActionAsync(userId, action, request, ct);
    }

    private static IReadOnlyList<string>? ReadStringArray(JsonElement args, string propertyName) =>
        args.TryGetProperty(propertyName, out var value) && value.ValueKind == JsonValueKind.Array
            ? value.EnumerateArray().Select(x => x.GetString()).Where(x => !string.IsNullOrWhiteSpace(x)).Cast<string>().ToList()
            : null;
}
