/*
 * Copyright (c) 2010-2011, The MiCode Open Source Community (www.micode.net)
 *
 * 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.tool;

import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;
import android.util.Log;

import net.micode.notes.data.Notes;
import net.micode.notes.data.Notes.CallNote;
import net.micode.notes.data.Notes.NoteColumns;
import net.micode.notes.ui.NotesListAdapter.AppWidgetAttribute;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * 数据工具类 - 提供批量数据库操作和查询功能
 * 功能包括：批量删除/移动笔记、文件夹计数、存在性检查、小部件查询等
 */
public class DataUtils {
    private static final String TAG = "DataUtils";

    /**
     * 批量删除笔记
     *
     * @param resolver 内容解析器
     * @param ids      要删除的笔记ID集合
     * @return 删除成功返回true，否则返回false
     */
    public static boolean batchDeleteNotes(ContentResolver resolver, Set<Long> ids) {
        // 参数有效性检查
        if (resolver == null) {
            Log.w(TAG, "ContentResolver is null");
            return false;
        }

        if (ids == null || ids.isEmpty()) {
            Log.d(TAG, "No notes to delete");
            return true;
        }

        ArrayList<ContentProviderOperation> operations = new ArrayList<>(ids.size());

        for (long id : ids) {
            // 防止删除系统根文件夹
            if (id == Notes.ID_ROOT_FOLDER) {
                Log.w(TAG, "Skipping system root folder deletion");
                continue;
            }

            // 添加删除操作
            operations.add(ContentProviderOperation
                    .newDelete(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id))
                    .build());
        }

        if (operations.isEmpty()) {
            Log.d(TAG, "No valid operations to execute");
            return true;
        }

        try {
            ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operations);
            return results != null && results.length > 0;
        } catch (RemoteException | OperationApplicationException e) {
            Log.e(TAG, "Batch delete failed", e);
        }
        return false;
    }

    /**
     * 移动笔记到新文件夹
     *
     * @param resolver    内容解析器
     * @param id          笔记ID
     * @param srcFolderId 源文件夹ID
     * @param desFolderId 目标文件夹ID
     */
    public static void moveNoteToFolder(ContentResolver resolver, long id, long srcFolderId, long desFolderId) {
        if (resolver == null) {
            Log.w(TAG, "ContentResolver is null");
            return;
        }

        ContentValues values = new ContentValues();
        values.put(NoteColumns.PARENT_ID, desFolderId);
        values.put(NoteColumns.ORIGIN_PARENT_ID, srcFolderId);
        values.put(NoteColumns.LOCAL_MODIFIED, 1); // 标记为本地已修改

        resolver.update(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id), values, null, null);
    }

    /**
     * 批量移动笔记到文件夹
     *
     * @param resolver 内容解析器
     * @param ids      笔记ID集合
     * @param folderId 目标文件夹ID
     * @return 移动成功返回true，否则返回false
     */
    public static boolean batchMoveToFolder(ContentResolver resolver, Set<Long> ids, long folderId) {
        if (resolver == null) {
            Log.w(TAG, "ContentResolver is null");
            return false;
        }

        if (ids == null || ids.isEmpty()) {
            Log.d(TAG, "No notes to move");
            return true;
        }

        ArrayList<ContentProviderOperation> operations = new ArrayList<>(ids.size());

        for (long id : ids) {
            operations.add(ContentProviderOperation
                    .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id))
                    .withValue(NoteColumns.PARENT_ID, folderId)
                    .withValue(NoteColumns.LOCAL_MODIFIED, 1)
                    .build());
        }

        try {
            ContentProviderResult[] results = resolver.applyBatch(Notes.AUTHORITY, operations);
            return results != null && results.length > 0;
        } catch (RemoteException | OperationApplicationException e) {
            Log.e(TAG, "Batch move failed", e);
        }
        return false;
    }

    /**
     * 获取用户创建的文件夹数量（排除系统文件夹）
     *
     * @param resolver 内容解析器
     * @return 用户文件夹数量
     */
    public static int getUserFolderCount(ContentResolver resolver) {
        if (resolver == null) {
            Log.w(TAG, "ContentResolver is null");
            return 0;
        }

        String[] projection = {NoteColumns.ID};
        String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?";
        String[] selectionArgs = {
                String.valueOf(Notes.TYPE_FOLDER),
                String.valueOf(Notes.ID_TRASH_FOLDER) // 修正拼写错误：FOLER -> FOLDER
        };

        try (Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
                projection, selection, selectionArgs, null)) {
            return cursor != null ? cursor.getCount() : 0;
        }
    }

    /**
     * 检查指定类型笔记是否可见（不在回收站中）
     *
     * @param resolver 内容解析器
     * @param noteId   笔记ID
     * @param type     笔记类型
     * @return 笔记存在且可见返回true
     */
    public static boolean isNoteVisible(ContentResolver resolver, long noteId, int type) {
        if (resolver == null) return false;

        String selection = NoteColumns.TYPE + "=? AND " + NoteColumns.PARENT_ID + "<>?";
        String[] selectionArgs = {
                String.valueOf(type),
                String.valueOf(Notes.ID_TRASH_FOLDER)
        };

        try (Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
                null, selection, selectionArgs, null)) {
            return cursor != null && cursor.getCount() > 0;
        }
    }

    /**
     * 检查笔记是否存在
     *
     * @param resolver 内容解析器
     * @param noteId   笔记ID
     * @return 笔记存在返回true
     */
    public static boolean doesNoteExist(ContentResolver resolver, long noteId) {
        if (resolver == null) return false;

        try (Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, noteId),
                null, null, null, null)) {
            return cursor != null && cursor.getCount() > 0;
        }
    }

    /**
     * 检查笔记数据是否存在
     *
     * @param resolver 内容解析器
     * @param dataId   数据ID
     * @return 数据存在返回true
     */
    public static boolean doesDataExist(ContentResolver resolver, long dataId) {
        if (resolver == null) return false;

        try (Cursor cursor = resolver.query(ContentUris.withAppendedId(Notes.CONTENT_DATA_URI, dataId),
                null, null, null, null)) {
            return cursor != null && cursor.getCount() > 0;
        }
    }

    /**
     * 检查文件夹名称是否已存在（可见文件夹）
     *
     * @param resolver 内容解析器
     * @param name     文件夹名称
     * @return 名称已存在返回true
     */
    public static boolean isFolderNameExist(ContentResolver resolver, String name) {
        if (resolver == null || TextUtils.isEmpty(name)) return false;

        String selection = NoteColumns.TYPE + "=" + Notes.TYPE_FOLDER +
                " AND " + NoteColumns.PARENT_ID + "<>" + Notes.ID_TRASH_FOLDER +
                " AND " + NoteColumns.SNIPPET + "=?";
        String[] selectionArgs = { name };

        try (Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
                null, selection, selectionArgs, null)) {
            return cursor != null && cursor.getCount() > 0;
        }
    }

    /**
     * 获取文件夹关联的小部件属性
     *
     * @param resolver 内容解析器
     * @param folderId 文件夹ID
     * @return 小部件属性集合
     */
    public static Set<AppWidgetAttribute> getFolderWidgets(ContentResolver resolver, long folderId) {
        Set<AppWidgetAttribute> widgets = new HashSet<>();
        if (resolver == null) return widgets;

        String[] projection = { NoteColumns.WIDGET_ID, NoteColumns.WIDGET_TYPE };
        String selection = NoteColumns.PARENT_ID + "=?";
        String[] selectionArgs = { String.valueOf(folderId) };

        try (Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
                projection, selection, selectionArgs, null)) {

            if (cursor != null && cursor.moveToFirst()) {
                do {
                    try {
                        AppWidgetAttribute widget = new AppWidgetAttribute();
                        widget.widgetId = cursor.getInt(0);
                        widget.widgetType = cursor.getInt(1);
                        widgets.add(widget);
                    } catch (Exception e) {
                        Log.e(TAG, "Error reading widget attributes", e);
                    }
                } while (cursor.moveToNext());
            }
        }
        return widgets;
    }

    /**
     * 通过笔记ID获取电话号码（通话记录笔记）
     *
     * @param resolver 内容解析器
     * @param noteId   笔记ID
     * @return 电话号码，查询失败返回空字符串
     */
    public static String getCallNumber(ContentResolver resolver, long noteId) {
        if (resolver == null) return "";

        String[] projection = { CallNote.PHONE_NUMBER };
        String selection = CallNote.NOTE_ID + "=? AND " + CallNote.MIME_TYPE + "=?";
        String[] selectionArgs = {
                String.valueOf(noteId),
                CallNote.CONTENT_ITEM_TYPE
        };

        try (Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
                projection, selection, selectionArgs, null)) {

            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getString(0);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error getting call number", e);
        }
        return "";
    }

    /**
     * 通过电话号码和呼叫日期查找笔记ID
     *
     * @param resolver    内容解析器
     * @param phoneNumber 电话号码
     * @param callDate    通话日期
     * @return 笔记ID，未找到返回0
     */
    public static long findNoteByCallDetails(ContentResolver resolver, String phoneNumber, long callDate) {
        if (resolver == null || TextUtils.isEmpty(phoneNumber)) return 0;

        String[] projection = { CallNote.NOTE_ID };
        String selection = CallNote.CALL_DATE + "=? AND " + CallNote.MIME_TYPE + "=? AND " +
                "PHONE_NUMBERS_EQUAL(" + CallNote.PHONE_NUMBER + ", ?)";
        String[] selectionArgs = {
                String.valueOf(callDate),
                CallNote.CONTENT_ITEM_TYPE,
                phoneNumber
        };

        try (Cursor cursor = resolver.query(Notes.CONTENT_DATA_URI,
                projection, selection, selectionArgs, null)) {

            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getLong(0);
            }
        } catch (Exception e) {
            Log.e(TAG, "Error finding note by call details", e);
        }
        return 0;
    }

    /**
     * 获取笔记摘要
     *
     * @param resolver 内容解析器
     * @param noteId   笔记ID
     * @return 笔记摘要
     * @throws IllegalArgumentException 笔记不存在时抛出异常
     */
    public static String getNoteSnippet(ContentResolver resolver, long noteId) {
        if (resolver == null) throw new IllegalArgumentException("Resolver is null");

        String[] projection = { NoteColumns.SNIPPET };
        String selection = NoteColumns.ID + "=?";
        String[] selectionArgs = { String.valueOf(noteId) };

        try (Cursor cursor = resolver.query(Notes.CONTENT_NOTE_URI,
                projection, selection, selectionArgs, null)) {

            if (cursor != null && cursor.moveToFirst()) {
                return cursor.getString(0);
            }
            throw new IllegalArgumentException("Note not found with id: " + noteId);
        }
    }

    /**
     * 格式化笔记摘要（移除换行符）
     *
     * @param snippet 原始摘要
     * @return 格式化后的摘要
     */
    public static String formatSnippet(String snippet) {
        if (snippet == null) return null;

        String formatted = snippet.trim();
        int newlineIndex = formatted.indexOf('\n');
        return (newlineIndex != -1) ? formatted.substring(0, newlineIndex) : formatted;
    }

    /* ----------------- 新增功能 ----------------- */

    /**
     * 安全删除笔记（防止系统文件夹被删除）
     *
     * @param resolver 内容解析器
     * @param noteId   笔记ID
     * @return 删除成功返回true
     */
    public static boolean safeDeleteNote(ContentResolver resolver, long noteId) {
        Set<Long> ids = new HashSet<>(1);
        ids.add(noteId);
        return batchDeleteNotes(resolver, ids);
    }

    /**
     * 批量更新笔记的本地修改标志
     *
     * @param resolver 内容解析器
     * @param ids      笔记ID集合
     * @param modified 修改标志值 (1-已修改, 0-未修改)
     * @return 更新成功返回true
     */
    public static boolean batchMarkModified(ContentResolver resolver, Set<Long> ids, int modified) {
        if (resolver == null) return false;

        ArrayList<ContentProviderOperation> operations = new ArrayList<>(ids.size());

        for (long id : ids) {
            operations.add(ContentProviderOperation
                    .newUpdate(ContentUris.withAppendedId(Notes.CONTENT_NOTE_URI, id))
                    .withValue(NoteColumns.LOCAL_MODIFIED, modified)
                    .build());
        }

        try {
            resolver.applyBatch(Notes.AUTHORITY, operations);
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Batch mark modified failed", e);
        }
        return false;
    }
}