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, AppDbContext db, Guid userId)
    {
        return toolName switch
        {
            "query_health_records" => await ExecuteQueryHealthRecords(db, userId, args),
            "check_archive" => await ExecuteCheckArchive(db, userId),
            _ => new { success = false, message = $"未知工具: {toolName}" }
        };
    }

    private static async Task<object> ExecuteQueryHealthRecords(AppDbContext db, Guid userId, JsonElement args)
    {
        var type = args.TryGetProperty("type", out var t) ? t.GetString() : null;
        var days = args.TryGetProperty("days", out var d) ? d.GetInt32() : 7;

        var query = db.HealthRecords.Where(r => r.UserId == userId);
        if (!string.IsNullOrEmpty(type) && Enum.TryParse<HealthMetricType>(type, ignoreCase: true, out var mt))
            query = query.Where(r => r.MetricType == mt);

        query = query.Where(r => r.RecordedAt >= DateTime.UtcNow.AddDays(-days));

        var records = await query.OrderByDescending(r => r.RecordedAt).Take(30).Select(r => new
        {
            r.Id, Type = r.MetricType.ToString(), r.Systolic, r.Diastolic, r.Value, r.Unit, r.IsAbnormal, r.RecordedAt,
        }).ToListAsync();

        return new { count = records.Count, records };
    }

    private static async Task<object> ExecuteCheckArchive(AppDbContext db, Guid userId)
    {
        var archive = await db.HealthArchives.FirstOrDefaultAsync(a => a.UserId == userId);
        if (archive == null) return new { found = false };
        return new
        {
            found = true, archive.Diagnosis, archive.SurgeryType,
            SurgeryDate = archive.SurgeryDate?.ToString("yyyy-MM-dd"),
            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 async Task<object> ExecuteManageArchive(AppDbContext db, Guid userId, JsonElement args)
    {
        var action = args.TryGetProperty("action", out var a) ? a.GetString()! : "query";
        var archive = await db.HealthArchives.FirstOrDefaultAsync(x => x.UserId == userId);
        if (archive == null)
        {
            archive = new HealthArchive { Id = Guid.NewGuid(), UserId = userId };
            db.HealthArchives.Add(archive);
        }

        switch (action)
        {
            case "update_diagnosis":
                archive.Diagnosis = args.TryGetProperty("diagnosis", out var d) ? d.GetString() : archive.Diagnosis;
                break;
            case "update_surgery":
                archive.SurgeryType = args.TryGetProperty("surgery_type", out var st) ? st.GetString() : archive.SurgeryType;
                if (args.TryGetProperty("surgery_date", out var sd))
                    archive.SurgeryDate = DateOnly.TryParse(sd.GetString(), out var date) ? date : archive.SurgeryDate;
                break;
            case "update_allergies":
                if (args.TryGetProperty("allergies", out var al) && al.ValueKind == JsonValueKind.Array)
                    archive.Allergies = [.. al.EnumerateArray().Select(x => x.GetString()!)];
                break;
            case "update_chronic_diseases":
                if (args.TryGetProperty("chronic_diseases", out var cd) && cd.ValueKind == JsonValueKind.Array)
                    archive.ChronicDiseases = [.. cd.EnumerateArray().Select(x => x.GetString()!)];
                break;
            case "update_diet_restrictions":
                if (args.TryGetProperty("diet_restrictions", out var dr) && dr.ValueKind == JsonValueKind.Array)
                    archive.DietRestrictions = [.. dr.EnumerateArray().Select(x => x.GetString()!)];
                break;
            default: // query
                return new
                {
                    found = true, archive.Diagnosis, archive.SurgeryType,
                    SurgeryDate = archive.SurgeryDate?.ToString("yyyy-MM-dd"),
                    archive.Allergies, archive.DietRestrictions, archive.ChronicDiseases, archive.FamilyHistory,
                };
        }

        archive.UpdatedAt = DateTime.UtcNow;
        await db.SaveChangesAsync();
        return new { success = true };
    }
}
