using Firebase.Extensions;
using Firebase.Firestore;
using System;
using UnityEngine;

/// <summary>
/// This class will download or upload the prompts from/to the Firestore
/// </summary>
public class PromptListLoader : MonoBehaviour
{
    public PromptList promptList;

    [Header("Enter a prompt here to push it to database")]
    public Prompt addPrompt;

    private FirebaseFirestore db;


    private void Awake()
    {
        FirebaseInitializer.Instance.onFirebaseReady += Initialize;
    }

    private void Initialize()
    {
        FirebaseInitializer.Instance.onFirebaseReady -= Initialize;
        db = FirebaseFirestore.DefaultInstance;
        LoadPromptsFromFirestore();
    }

    /// <summary>
    /// Will erase your prompt list scriptable object and load everything from firestore
    /// </summary>
    [ContextMenu("Load Prompts From Firestore")]
    private void LoadPromptsFromFirestore()
    {
        if (promptList == null)
        {
            Debug.LogError("You must provide a prompt list scriptable object", this);
            return;
        }

        CollectionReference promptsRef = db.Collection("prompts");
        promptsRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
        {
            QuerySnapshot snapshot = task.Result;
            if (snapshot.Count > 0)
            {
                promptList.prompts.Clear();
                foreach (DocumentSnapshot prompt in snapshot.Documents)
                {
                    Prompt temp = prompt.ConvertTo<Prompt>();
                    if (string.IsNullOrEmpty(temp.id))
                    {
                        Debug.LogError("Found a prompt with an empty id. Stopping right here before anything bad happens.", this);
                        return;
                    }
                    promptList.prompts.Add(temp);
                }
            }
            else
            {
                Debug.LogError("Couldn't get any prompts from Firestore", this);
            }
        });
    }

    /// <summary>
    /// Will erase full online database and replace with a new list of prompts
    /// </summary>
    [ContextMenu("Save Prompt list to Firestore")]
    private void SavePromptsToFirestore()
    {
        if (promptList.prompts.Count <= 0)
        {
            Debug.LogError("your prompt list is empty, I shouldn't save it to the database", this);
            return;
        }

        EraseFirestore(() =>
        {
            foreach (Prompt p in promptList.prompts)
            {
                AddPromptToFirestore(p);
            }
        });
    }

    /// <summary>
    /// Erase all firestore
    /// </summary>
    /// <param name="OnCleanComplete"></param>
    [ContextMenu("DELETE ALL Firestore")]
    private void EraseFirestore(Action OnCleanComplete)
    {
        CollectionReference promptCol = db.Collection("prompts");
        promptCol.GetSnapshotAsync().ContinueWithOnMainThread(task =>
        {
            QuerySnapshot snapshot = task.Result;
            if (snapshot.Count > 0)
            {
                foreach (DocumentSnapshot prompt in snapshot.Documents)
                {
                    Debug.Log($"deleting {prompt.Id}");
                    prompt.Reference.DeleteAsync();
                }
                Debug.Log($"Database fully cleaned");
                OnCleanComplete?.Invoke();
            }
            else
            {
                Debug.LogWarning("Couldn't get any prompts from Firestore (maybe it wa empty)", this);
                OnCleanComplete?.Invoke();
            }
        });
    }

    /// <summary>
    /// Will add a prompt to the firestore
    /// </summary>
    private void AddPromptToFirestore(Prompt _prompt = null)
    {
        if (_prompt == null)
            _prompt = addPrompt;

        DocumentReference newEntry = db.Collection("prompts").Document();
        newEntry.SetAsync(_prompt).ContinueWithOnMainThread(task =>
        {
            if (task.IsCompletedSuccessfully)
            {
                Debug.Log($"prompt {newEntry.Id} has been added", this);
            }
            else
            {
                Debug.LogError($"prompt {newEntry.Id} has not been added {task.Exception.Message}", this);
            }
        });
    }

    [ContextMenu("Add Prompt To Firestore")]
    private void AddPromptToFirestore()
    {
        AddPromptToFirestore(addPrompt);
    }

    /// <summary>
    /// 
    /// </summary>
    [ContextMenu("Generate Random Id")]
    private void GenerateRandomId()
    {
        addPrompt.id = Guid.NewGuid().ToString();
    }
}

