using LiteDB;

namespace AuthorBuddy.Web.Services;

public class DbAdminService : IDbAdminService
{
    private readonly ILiteDatabase _db;

    private static readonly string[] KnownCollections =
    {
        "users", "projects", "settings", "fileCategories", "documentMeta", "vectors"
    };

    public DbAdminService(ILiteDatabase db)
    {
        _db = db;
    }

    public List<DbCollectionInfo> GetCollections()
    {
        var result = new List<DbCollectionInfo>();
        foreach (var name in KnownCollections)
        {
            var col = _db.GetCollection(name);
            result.Add(new DbCollectionInfo
            {
                Name = name,
                Count = col.Count()
            });
        }
        return result;
    }

    public List<DbRecord> GetAll(string collectionName)
    {
        var col = _db.GetCollection(collectionName);
        var docs = col.FindAll().ToList();
        var result = new List<DbRecord>();

        foreach (var doc in docs)
        {
            var id = doc["_id"].AsInt32;
            var fields = new Dictionary<string, string?>();
            foreach (var key in doc.Keys)
            {
                if (key == "_id") continue;
                fields[key] = BsonToDisplay(doc[key]);
            }
            result.Add(new DbRecord { Id = id, Fields = fields });
        }
        return result;
    }

    public bool Update(string collectionName, int id, Dictionary<string, string?> values)
    {
        try
        {
            var col = _db.GetCollection(collectionName);
            var doc = col.FindById(new BsonValue(id));
            if (doc == null) return false;

            foreach (var kv in values)
            {
                if (kv.Key == "_id") continue;
                doc[kv.Key] = ParseBsonValue(kv.Value);
            }
            return col.Update(doc);
        }
        catch
        {
            return false;
        }
    }

    public bool Delete(string collectionName, int id)
    {
        try
        {
            var col = _db.GetCollection(collectionName);
            return col.Delete(new BsonValue(id));
        }
        catch
        {
            return false;
        }
    }

    private static string? BsonToDisplay(BsonValue val)
    {
        if (val.IsNull) return null;
        if (val.IsDateTime) return val.AsDateTime.ToString("yyyy-MM-dd HH:mm:ss");
        if (val.IsBoolean) return val.AsBoolean.ToString();
        if (val.IsDouble) return val.AsDouble.ToString("G");
        if (val.IsInt32) return val.AsInt32.ToString();
        if (val.IsInt64) return val.AsInt64.ToString();
        if (val.IsString) return val.AsString;
        if (val.IsArray) return $"[Array ({val.AsArray.Count} items)]";
        if (val.IsDocument) return $"[Object]";
        return val.RawValue?.ToString();
    }

    private static BsonValue ParseBsonValue(string? value)
    {
        if (value == null) return BsonValue.Null;
        if (int.TryParse(value, out var i)) return new BsonValue(i);
        if (long.TryParse(value, out var l)) return new BsonValue(l);
        if (double.TryParse(value, out var d)) return new BsonValue(d);
        if (bool.TryParse(value, out var b)) return new BsonValue(b);
        return new BsonValue(value);
    }
}
