/*
 * 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.data;

import android.content.ContentResolver;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

import net.micode.notes.model.Note;
import net.micode.notes.data.NotesRepository.NoteInfo;

import java.util.List;

import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

/**
 * NotesRepository 单元测试
 * <p>
 * 测试笔记数据仓库的各个功能
 * </p>
 *
 * @see NotesRepository
 */
@RunWith(MockitoJUnitRunner.class)
public class NotesRepositoryTest {

    private static final String TAG = "NotesRepositoryTest";

    @Mock
    private ContentResolver mockContentResolver;

    private NotesRepository repository;

    @Before
    public void setUp() {
        repository = new NotesRepository(mockContentResolver);
    }

    @After
    public void tearDown() {
        repository.shutdown();
    }

    /**
     * 测试创建Repository实例
     */
    @Test
    public void testRepositoryCreation() {
        assertNotNull("Repository should not be null", repository);
    }

    /**
     * 测试获取笔记列表
     */
    @Test
    public void testGetNotes() {
        // Arrange
        long folderId = Notes.ID_ROOT_FOLDER;

        // Act
        repository.getNotes(folderId, new NotesRepository.Callback<List<NoteInfo>>() {
            @Override
            public void onSuccess(List<NoteInfo> result) {
                assertNotNull("Notes list should not be null", result);
                // Mock返回空列表，实际应用中会有数据
                assertTrue("Notes count should be >= 0", result.size() >= 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试创建笔记
     */
    @Test
    public void testCreateNote() {
        // Arrange
        long folderId = Notes.ID_ROOT_FOLDER;

        // Act
        repository.createNote(folderId, new NotesRepository.Callback<Long>() {
            @Override
            public void onSuccess(Long noteId) {
                assertNotNull("Note ID should not be null", noteId);
                assertTrue("Note ID should be > 0", noteId > 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试更新笔记内容
     */
    @Test
    public void testUpdateNote() {
        // Arrange
        long noteId = 1L;
        String content = "测试笔记内容";

        // Act
        repository.updateNote(noteId, content, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer rowsAffected) {
                assertNotNull("Rows affected should not be null", rowsAffected);
                assertTrue("Rows affected should be >= 0", rowsAffected >= 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试删除笔记
     */
    @Test
    public void testDeleteNote() {
        // Arrange
        long noteId = 1L;

        // Act
        repository.deleteNote(noteId, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer rowsAffected) {
                assertNotNull("Rows affected should not be null", rowsAffected);
                assertTrue("Rows affected should be >= 0", rowsAffected >= 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试搜索笔记
     */
    @Test
    public void testSearchNotes() {
        // Arrange
        String keyword = "测试";

        // Act
        repository.searchNotes(keyword, new NotesRepository.Callback<List<NoteInfo>>() {
            @Override
            public void onSuccess(List<NoteInfo> result) {
                assertNotNull("Search results should not be null", result);
                assertTrue("Search results count should be >= 0", result.size() >= 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试搜索空关键字
     */
    @Test
    public void testSearchNotesWithEmptyKeyword() {
        // Arrange
        String keyword = "";

        // Act
        repository.searchNotes(keyword, new NotesRepository.Callback<List<NoteInfo>>() {
            @Override
            public void onSuccess(List<NoteInfo> result) {
                assertNotNull("Search results should not be null", result);
                // 空关键字应返回空列表
                assertEquals("Search results should be empty", 0, result.size());
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试获取笔记统计
     */
    @Test
    public void testCountNotes() {
        // Arrange
        long folderId = Notes.ID_ROOT_FOLDER;

        // Act
        repository.countNotes(folderId, new NotesRepository.Callback<Integer>() {
            @Override
            public void onSuccess(Integer count) {
                assertNotNull("Count should not be null", count);
                assertTrue("Count should be >= 0", count >= 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }

    /**
     * 测试获取文件夹列表
     */
    @Test
    public void testGetFolders() {
        // Act
        repository.getFolders(new NotesRepository.Callback<List<NoteInfo>>() {
            @Override
            public void onSuccess(List<NoteInfo> result) {
                assertNotNull("Folders should not be null", result);
                assertTrue("Folders count should be >= 0", result.size() >= 0);
            }

            @Override
            public void onError(Exception error) {
                fail("Should not throw error: " + error.getMessage());
            }
        });
    }
}
