/*
 * Copyright (c) 2025, Modern Notes Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.micode.notes.viewmodel;

import android.util.Log;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import net.micode.notes.data.Notes;
import net.micode.notes.data.NotesRepository;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * 笔记列表ViewModel
 * <p>
 * 负责笔记列表的业务逻辑，与UI层（Activity）解耦
 * 管理笔记列表的加载、创建、删除、搜索、移动等操作
 * </p>
 *
 * @see NotesRepository
 * @see Note
 */
public class NotesListViewModel extends ViewModel {
    private static final String TAG = "NotesListViewModel";

    private final NotesRepository repository;

    // 笔记列表LiveData
    private final MutableLiveData<List<NotesRepository.NoteInfo>> notesLiveData = new MutableLiveData<>();

    // 加载状态LiveData
    private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);

    // 错误消息LiveData
    private final MutableLiveData<String> errorMessage = new MutableLiveData<>();

    // 选中的笔记ID集合
    private final HashSet<Long> selectedNoteIds = new HashSet<>();

    // 当前文件夹ID
    private long currentFolderId = Notes.ID_ROOT_FOLDER;

    // 文件夹路径LiveData（用于面包屑导航）
    private final MutableLiveData<List<NotesRepository.NoteInfo>> folderPathLiveData = new MutableLiveData<>();

    // 侧栏刷新通知LiveData（删除等操作后通知侧栏刷新）
    private final MutableLiveData<Boolean> sidebarRefreshNeeded = new MutableLiveData<>(false);

    // 文件夹导航历史（用于返回上一级）
    private final List<Long> folderHistory = new ArrayList<>();

    /**
     * 构造函数
     *
     * @param repository 笔记数据仓库
     */
    public NotesListViewModel(NotesRepository repository) {
        this.repository = repository;
        Log.d(TAG, "ViewModel created");
    }

    /**
     * 获取笔记列表LiveData
     *
     * @return 笔记列表LiveData
     */
    public MutableLiveData<List<NotesRepository.NoteInfo>> getNotesLiveData() {
        return notesLiveData;
    }

    /**
     * 获取加载状态LiveData
     *
     * @return 加载状态LiveData
     */
    public MutableLiveData<Boolean> getIsLoading() {
        return isLoading;
    }

    /**
     * 获取错误消息LiveData
     *
     * @return 错误消息LiveData
     */
    public MutableLiveData<String> getErrorMessage() {
        return errorMessage;
    }

    /**
     * 加载笔记列表
     * <p>
     * 从指定文件夹加载笔记列表，同时加载文件夹路径用于面包屑导航
     * </p>
     *
     * @param folderId 文件夹ID，{@link Notes#ID_ROOT_FOLDER} 表示根文件夹
     */
    public void loadNotes(long folderId) {
        this.currentFolderId = folderId;
        isLoading.postValue(true);
        errorMessage.postValue(null);

        // 加载文件夹路径
        repository.getFolderPath(folderId, new NotesRepository.Callback<List<NotesRepository.NoteInfo>>() {
            @Override
            public void onSuccess(List<NotesRepository.NoteInfo> path) {
                folderPathLiveData.postValue(path);
            }

            @Override
            public void onError(Exception error) {
                Log.e(TAG, "Failed to load folder path", error);
            }
        });

        // 加载笔记
        repository.getNotes(folderId, new NotesRepository.Callback<List<NotesRepository.NoteInfo>>() {
            @Override
            public void onSuccess(List<NotesRepository.NoteInfo> notes) {
                isLoading.postValue(false);
                notesLiveData.postValue(notes);
                Log.d(TAG, "Successfully loaded " + notes.size() + " notes");
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "加载笔记失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 刷新笔记列表
     * <p>
     * 重新加载当前文件夹的笔记列表
     * </p>
     */
    public void refreshNotes() {
        loadNotes(currentFolderId);
    }

    /**
     * 创建新笔记
     * <p>
     * 在当前文件夹下创建一个空笔记，并刷新列表
     * </p>
     */
    public void createNote() {
        isLoading.postValue(true);
        errorMessage.postValue(null);

        repository.createNote(currentFolderId, new NotesRepository.Callback<Long>() {
            @Override
            public void onSuccess(Long noteId) {
                isLoading.postValue(false);
                Log.d(TAG, "Successfully created note with ID: " + noteId);
                refreshNotes();
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "创建笔记失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 删除单个笔记
     * <p>
     * 将笔记移动到回收站，并刷新列表
     * </p>
     *
     * @param noteId 笔记ID
     */
    public void deleteNote(long noteId) {
        isLoading.postValue(true);
        errorMessage.postValue(null);

        repository.deleteNote(noteId, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer rowsAffected) {
                isLoading.postValue(false);
                selectedNoteIds.remove(noteId);
                refreshNotes();
                Log.d(TAG, "Successfully deleted note: " + noteId);
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "删除笔记失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 批量删除笔记
     * <p>
     * 将选中的所有笔记移动到回收站
     * </p>
     */
    public void deleteSelectedNotes() {
        if (selectedNoteIds.isEmpty()) {
            errorMessage.postValue("请先选择要删除的笔记");
            return;
        }

        isLoading.postValue(true);
        errorMessage.postValue(null);

        List<Long> noteIds = new ArrayList<>(selectedNoteIds);
        repository.deleteNotes(noteIds, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer rowsAffected) {
                isLoading.postValue(false);
                selectedNoteIds.clear();
                refreshNotes();
                Log.d(TAG, "Successfully deleted " + rowsAffected + " notes");
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "批量删除失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 搜索笔记
     * <p>
     * 根据关键字搜索笔记，更新笔记列表
     * </p>
     *
     * @param keyword 搜索关键字
     */
    public void searchNotes(String keyword) {
        isLoading.postValue(true);
        errorMessage.postValue(null);

        repository.searchNotes(keyword, new NotesRepository.Callback<List<NotesRepository.NoteInfo>>() {
            @Override
            public void onSuccess(List<NotesRepository.NoteInfo> notes) {
                isLoading.postValue(false);
                notesLiveData.postValue(notes);
                Log.d(TAG, "Search returned " + notes.size() + " results");
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "搜索失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 切换笔记选中状态
     *
     * @param noteId 笔记ID
     * @param selected 是否选中
     */
    public void toggleNoteSelection(long noteId, boolean selected) {
        if (selected) {
            selectedNoteIds.add(noteId);
        } else {
            selectedNoteIds.remove(noteId);
        }
    }

    /**
     * 全选笔记
     * <p>
     * 选中当前列表中的所有笔记
     * </p>
     */
    public void selectAllNotes() {
        List<NotesRepository.NoteInfo> notes = notesLiveData.getValue();
        if (notes != null) {
            for (NotesRepository.NoteInfo note : notes) {
                selectedNoteIds.add(note.getId());
            }
        }
    }

    /**
     * 取消全选
     * <p>
     * 清空所有选中的笔记
     * </p>
     */
    public void deselectAllNotes() {
        selectedNoteIds.clear();
    }

    /**
     * 检查是否全选
     *
     * @return 如果所有笔记都被选中返回true
     */
    public boolean isAllSelected() {
        List<NotesRepository.NoteInfo> notes = notesLiveData.getValue();
        if (notes == null || notes.isEmpty()) {
            return false;
        }

        return notes.size() == selectedNoteIds.size();
    }

    /**
     * 获取选中的笔记数量
     *
     * @return 选中的笔记数量
     */
    public int getSelectedCount() {
        return selectedNoteIds.size();
    }

    /**
     * 获取选中的笔记ID列表
     *
     * @return 选中的笔记ID列表
     */
    public List<Long> getSelectedNoteIds() {
        return new ArrayList<>(selectedNoteIds);
    }

    /**
     * 获取当前文件夹ID
     *
     * @return 当前文件夹ID
     */
    public long getCurrentFolderId() {
        return currentFolderId;
    }

    /**
     * 设置当前文件夹
     *
     * @param folderId 文件夹ID
     */
    public void setCurrentFolderId(long folderId) {
        this.currentFolderId = folderId;
    }

    /**
     * 获取文件夹路径LiveData
     *
     * @return 文件夹路径LiveData
     */
    public MutableLiveData<List<NotesRepository.NoteInfo>> getFolderPathLiveData() {
        return folderPathLiveData;
    }

    /**
     * 获取侧栏刷新通知LiveData
     *
     * @return 侧栏刷新通知LiveData
     */
    public MutableLiveData<Boolean> getSidebarRefreshNeeded() {
        return sidebarRefreshNeeded;
    }

    /**
     * 触发侧栏刷新
     */
    public void triggerSidebarRefresh() {
        sidebarRefreshNeeded.postValue(true);
    }

    /**
     * 进入指定文件夹
     *
     * @param folderId 文件夹ID
     */
    public void enterFolder(long folderId) {
        // 将当前文件夹添加到历史记录
        if (currentFolderId != Notes.ID_ROOT_FOLDER && currentFolderId != Notes.ID_CALL_RECORD_FOLDER) {
            folderHistory.add(currentFolderId);
        }
        loadNotes(folderId);
    }

    /**
     * 返回上一级文件夹
     *
     * @return 是否成功返回上一级
     */
    public boolean navigateUp() {
        if (!folderHistory.isEmpty()) {
            long parentFolderId = folderHistory.remove(folderHistory.size() - 1);
            loadNotes(parentFolderId);
            return true;
        }
        return false;
    }

    /**
     * 清除选择状态
     * <p>
     * 退出多选模式时调用
     * </p>
     */
    public void clearSelection() {
        selectedNoteIds.clear();
    }

    /**
     * 获取文件夹列表
     * <p>
     * 加载所有文件夹类型的笔记
     * </p>
     */
    public void loadFolders() {
        isLoading.postValue(true);
        errorMessage.postValue(null);

        repository.getFolders(new NotesRepository.Callback<List<NotesRepository.NoteInfo>>() {
            @Override
            public void onSuccess(List<NotesRepository.NoteInfo> folders) {
                isLoading.postValue(false);
                notesLiveData.postValue(folders);
                Log.d(TAG, "Successfully loaded " + folders.size() + " folders");
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "加载文件夹失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 移动选中的笔记到指定文件夹
     * <p>
     * 批量移动笔记到目标文件夹
     * </p>
     *
     * @param targetFolderId 目标文件夹ID
     */
    public void moveSelectedNotesToFolder(long targetFolderId) {
        if (selectedNoteIds.isEmpty()) {
            errorMessage.postValue("请先选择要移动的笔记");
            return;
        }

        isLoading.postValue(true);
        errorMessage.postValue(null);

        List<Long> noteIds = new ArrayList<>(selectedNoteIds);
        repository.moveNotes(noteIds, targetFolderId, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer rowsAffected) {
                isLoading.postValue(false);
                selectedNoteIds.clear();
                refreshNotes();
                Log.d(TAG, "Successfully moved " + rowsAffected + " notes");
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "移动笔记失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 切换选中笔记的置顶状态
     */
    public void toggleSelectedNotesPin() {
        if (selectedNoteIds.isEmpty()) {
            errorMessage.postValue("请先选择要操作的笔记");
            return;
        }

        isLoading.postValue(true);
        errorMessage.postValue(null);

        // 检查当前选中笔记的置顶状态
        List<NotesRepository.NoteInfo> allNotes = notesLiveData.getValue();
        if (allNotes == null) return;

        boolean hasUnpinned = false;
        for (NotesRepository.NoteInfo note : allNotes) {
            if (selectedNoteIds.contains(note.getId())) {
                if (!note.isPinned) {
                    hasUnpinned = true;
                    break;
                }
            }
        }

        // 如果有未置顶的，则全部置顶；否则全部取消置顶
        final boolean newPinState = hasUnpinned;
        List<Long> noteIds = new ArrayList<>(selectedNoteIds);

        repository.batchTogglePin(noteIds, newPinState, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer rowsAffected) {
                isLoading.postValue(false);
                // 保持选中状态，方便用户查看
                refreshNotes();
                Log.d(TAG, "Successfully toggled pin state to " + newPinState);
            }

            @Override
            public void onError(Exception error) {
                isLoading.postValue(false);
                String message = "置顶操作失败: " + error.getMessage();
                errorMessage.postValue(message);
                Log.e(TAG, message, error);
            }
        });
    }

    /**
     * 检查选中的笔记是否全部已置顶
     *
     * @return 如果所有选中的笔记都已置顶返回true
     */
    public boolean isAllSelectedPinned() {
        if (selectedNoteIds.isEmpty()) return false;

        List<NotesRepository.NoteInfo> allNotes = notesLiveData.getValue();
        if (allNotes == null) return false;

        for (NotesRepository.NoteInfo note : allNotes) {
            if (selectedNoteIds.contains(note.getId())) {
                if (!note.isPinned) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * ViewModel销毁时的清理
     * <p>
     * 清理资源和状态
     * </p>
     */
    @Override
    protected void onCleared() {
        super.onCleared();
        selectedNoteIds.clear();
        Log.d(TAG, "ViewModel cleared");
    }
}
