//
//  PQSingletoRealmUtil.swift
//  PQSpeed
//
//  Created by SanW on 2020/7/7.
//  Copyright © 2020 BytesFlow. All rights reserved.
//

import RealmSwift
import UIKit
import BFCommonKit

public class PQSingletoRealmUtil: NSObject {
    public  var schemaVersion : UInt64 = 32
    public var realmEntry: Realm? {
        let config = Realm.Configuration(
            schemaVersion: schemaVersion,
            migrationBlock: { _, oldSchemaVersion in
                if oldSchemaVersion < 1 {}
            }
        )
        Realm.Configuration.defaultConfiguration = config
        do {
            let realmEntry = try Realm(configuration: config, queue: DispatchQueue.main)
            return realmEntry
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-realm创建失败:\(error)")
        }
        return nil
    }

    public static let shared = PQSingletoRealmUtil()

    // 根据不同的用户ID 初始化不同的数据库 th1
    public func getDraftDB(uid: String) -> Realm {
        let docPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)[0] as String
        let dbPath = docPath.appending("/\(uid)Draft.realm")
        BFLog(message: "生成登录人数据库地址\(dbPath)")

        var config = Realm.Configuration(
            schemaVersion: schemaVersion,
            migrationBlock: { _, oldSchemaVersion in
                if oldSchemaVersion < 1 {}
            }
        )
        config.fileURL = URL(string: dbPath)!
        let defaultRealm = try! Realm(configuration: config)
        return defaultRealm
    }

    /// 写入单个数据
    /// - Parameter objects: <#objects description#>
    /// - Returns: <#description#>
    public func saveObject(object: Object) {
        do {
            try realmEntry?.write {
                realmEntry?.add(object, update: .modified)
                BFLog(message: "Realm-添加单个数据成功:\(object)")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-添加单个数据失败:\(error)")
        }
    }

    /// 写入多个数据
    /// - Parameter objects: <#objects description#>
    /// - Returns: <#description#>
    public func saveObjects(objects: [Object]) {
        do {
            try realmEntry?.write {
                realmEntry?.add(objects, update: .modified)
                BFLog(message: "Realm-添加多个数据成功:\(objects)")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-添加多个数据失败:\(error)")
        }
    }

    /// 写入本地存储数据
    /// - Parameter objects: <#objects description#>
    /// - Returns: <#description#>
    public func saveLocalSaveObject(uniqueId: String, isSelected: Bool) {
        let currentObject = queryLocalStoreObjects(uniqueId: uniqueId)
        if (currentObject?.count ?? 0) > 0 {
            do {
                try realmEntry?.write {
                    currentObject?.first?.isSelected = isSelected
                    (currentObject?.first as? PQLocalStoreModel)?.currentDate = systemCurrentDate()
                    BFLog(message: "Realm-本地已存储数据更新成功:\(currentObject)")
                }
            } catch let error as NSError {
                // handle error
                BFLog(message: "Realm-本地已存储数据更新失败:\(error)")
            }
        } else {
            let storeObject = PQLocalStoreModel()
            storeObject.uniqueId = uniqueId
            storeObject.isSelected = isSelected
            // 未存在则保存
            BFLog(message: "Realm-本地数据未存储，开始存储")
            saveObject(object: storeObject)
        }
    }

    /// 查询本地缓存数据
    /// - Returns: <#description#>
    public func queryLocalStoreObjects(uniqueId: String) -> Results<PQBaseModel>? {
        return queryObjects(PQLocalStoreModel.self, filter: "uniqueId == '\(uniqueId)'")
    }

    /// 查询所有未过期视频缓存数据
    /// - Returns: description
    public func queryVideoObjects() -> Results<PQBaseModel>? {
        // "isSelected == false AND date >= \(Int(Date.init().timeIntervalSince1970) - 24 * 60)"
        return queryObjects(PQVideoListModel.self, filter: "isSelected == false")
    }

    /// 删除已缓存视频数据
    /// - Returns: <#description#>
    public func deleteAllCacheObject() {
        guard let deleteObjecs = realmEntry?.objects(PQVideoListModel.self) else {
            BFLog(message: "Realm-删除已缓存为空")
            return
        }
        do {
            try realmEntry?.write {
                realmEntry?.delete(deleteObjecs)
                BFLog(message: "Realm-删除已缓存视频成功")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
        }
    }

    /// 根据条件查询数据
    /// - Parameters:
    ///   - type: 类型
    ///   - filter: <#filter description#>
    /// - Returns: <#description#>
    public func queryObjects(_ type: PQBaseModel.Type, filter: String) -> Results<PQBaseModel>? {
        let puppies = realmEntry?.objects(type).filter(filter)
        BFLog(message: "查询已缓存数据:type = \(type) \(puppies ?? nil)")
        return puppies
    }

    public func deleteObject() {
        guard let deleteObjecs = realmEntry?.objects(PQVideoListModel.self).filter("isSelected == true") else { return }
        do {
            try realmEntry?.write {
                realmEntry?.delete(deleteObjecs)
                BFLog(message: "Realm-删除已缓存视频成功")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
        }
    }

    /// 删除
    /// - Returns: <#description#>
    public func deleteObject(object: PQVideoListModel) {
        let videoId: Int = object.videoId
        guard let deleteObjecs = realmEntry?.objects(PQVideoListModel.self).filter("videoId == \(videoId)") else { return }
        do {
            try realmEntry?.write {
                realmEntry?.delete(deleteObjecs)
                BFLog(message: "Realm-删除已缓存视频成功")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
        }
    }

    public func deleteObject(_ type: PQBaseModel.Type, filter: String) {
        guard let deleteObjecs = queryObjects(type, filter: filter) else { return }
        do {
            try realmEntry?.write {
                realmEntry?.delete(deleteObjecs)
                BFLog(message: "Realm-删除已缓存视频成功")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-删除已缓存视频失败:\(error)")
        }
    }

    /// 更新缓存视频是否读取过
    /// - Parameter object: <#object description#>
    /// - Returns: <#description#>
    public func updateObject(object: PQVideoListModel) {
        guard let newObject = realmEntry?.objects(PQVideoListModel.self).filter("videoId == \(object.videoId)") else { BFLog(message: "更新 newObject 为空")
            return
        }
        BFLog(message: "更新 newObject = \(newObject)")
        do {
            try realmEntry?.write {
                newObject.first?.isSelected = true
                BFLog(message: "Realm-更新缓存视频已播放成功:\(newObject)")
            }
        } catch let error as NSError {
            // handle error
            BFLog(message: "Realm-更新缓存视频已播放失败:\(error)")
        }
    }

    override private init() {
        super.init()
    }

    override public func copy() -> Any {
        return self
    }

    override public func mutableCopy() -> Any {
        return self
    }

    // MARK: - add by ak 数据库操作 V2 方法

    // MARK: add

    /// 添加一个
    ///
    /// - Parameter object: 添加元素
    public func realmAdd(realm: Realm, object: Object) {
        try! realm.write {
            realm.add(object, update: .modified)
        }
    }

    /// 添加多个
    ///
    /// - Parameter objects: 添加数组
    public func realmAdds(realm: Realm, objects: [Object]) {
        try! realm.write {
            realm.add(objects, update: .modified)
        }
    }

    // MARK: delete

    /// 删除一个
    ///
    /// - Parameter object: 删除元素
    public func realmDelete(realm: Realm, object: Object) {
        try! realm.write {
            realm.delete(object)
        }
    }

    /// 删除多个
    ///
    /// - Parameter objects: 元素数组
    public func realmDeletes(realm: Realm, objects: [Object]) {
        try! realm.write {
            realm.delete(objects)
        }
    }

    /// 条件删除
    ///
    /// - Parameters:
    ///   - object: 元素类型
    ///   - predicate: 条件
    public func realmDeletesWithPredicate(realm: Realm, object: Object.Type, predicate: NSPredicate) {
        let results: [Object] = realmQueryWithParameters(realm: realm, object: object, predicate: predicate)
        if results.count > 0 {
            try! realm.write {
                realm.delete(results)
            }
        }
    }

    /// 删除该类型所有
    ///
    /// - Parameter object: 元素类型
    public func realmDeleteTypeList(realm: Realm, object: Object.Type) {
        let objListResults = realmQueryWithType(realm: realm, object: object)
        if objListResults.count > 0 {
            try! realm.write {
                realm.delete(objListResults)
            }
        }
    }

    /// 删除当前数据库所有
    public func realmDeleteAll(realm: Realm) {
        try! realm.write {
            realm.deleteAll()
        }
    }

    // MARK: update

    /// 更新元素(元素必须有主键)
    ///
    /// - Parameter object: 要更新的元素
    public func realmUpdte(realm: Realm, object _: Object) {
        try! realm.write {
//             realm.up(object, update: true)
        }
    }

    /// 更新元素集合（元素必须有主键）
    ///
    /// - Parameter objects: 元素集合（集合内元素所有属性都要有值）
    public func realmUpdtes(realm: Realm, objects _: [Object]) {
        try! realm.write {
//             realm.add(objects, update: true)
        }
    }

    /// 更新操作 -> 对于realm搜索结果集当中的元素，在action当中直接负值即可修改
    ///
    /// - Parameter action:操作
    public func realmUpdateWithTranstion(realm: Realm, action: (Bool) -> Void) {
        try! realm.write {
            action(true)
        }
    }

    // MARK: query

    /// 查询元素
    /// - Parameter type: 元素类型
    /// - Parameter filter: 查询条件
    public func reamlQueryObjects(realm: Realm, _ type: Object.Type, filter: String) -> Results<Object>? {
        let puppies = realm.objects(type).filter(filter)
        BFLog(message: "查询已缓存数据:type = \(type) \(puppies)")
        return puppies
    }

    public func reamlQueryObjectsV2(realm: Realm, _ type: Object.Type, filter: String) -> String {
        var json: String?
        try! realm.write {
            let puppies: Results<Object> = realm.objects(type).filter(filter)
            BFLog(message: "查询已缓存数据:type = \(type) \(puppies)")
            if puppies.count > 0 {
                json = (puppies.first as? PQEditProjectModel)!.toJSONString(prettyPrint: false)
            }
        }

        return json ?? ""
    }

    /// 查询元素
    ///
    /// - Parameters:
    ///   - object: 元素类型
    /// - Returns: 查询结果
    public func realmQueryWith(realm: Realm, object: Object.Type) -> [Object] {
        let results = realmQueryWithType(realm: realm, object: object)
        var resultsArray = [Object]()
        if results.count > 0 {
            for i in 0...results.count - 1 {
                resultsArray.append(results[i])
            }
        }
        return resultsArray
    }

    /// 查询元素
    ///
    /// - Parameters:
    ///   - object: 元素类型
    ///   - predicate: 查询条件
    /// - Returns: 查询结果
    public func realmQueryWithParameters(realm: Realm, object: Object.Type, predicate: NSPredicate) -> [Object] {
        let results = realmQueryWith(realm: realm, object: object, predicate: predicate)
        var resultsArray = [Object]()
        if results.count > 0 {
            for i in 0...results.count - 1 {
                resultsArray.append(results[i])
            }
        }
        return resultsArray
    }

    /// 分页查询
    ///
    /// - Parameters:
    ///   - object: 查询类型
    ///   - fromIndex: 起始页
    ///   - pageSize: 每页多少个
    /// - Returns: 查询结果
    public func realmQueryWithParametersPage(realm: Realm, object: Object.Type, fromIndex: Int, pageSize: Int) -> [Object] {
        let results = realmQueryWithType(realm: realm, object: object)
        var resultsArray = [Object]()
        if results.count <= pageSize * (fromIndex - 1) || fromIndex <= 0 {
            return resultsArray
        }
        if results.count > 0 {
            for i in pageSize * (fromIndex - 1)...fromIndex * pageSize - 1 {
                resultsArray.append(results[i])
            }
        }
        return resultsArray
    }

    /// 条件排序查询
    ///
    /// - Parameters:
    ///   - object: 查询类型
    ///   - predicate: 查询条件
    ///   - sortedKey: 排序key
    ///   - isAssending: 是否升序
    /// - Returns: 查询结果
    public func realmQueryWithParametersAndSorted(realm: Realm, object: Object.Type, predicate: NSPredicate, sortedKey: String, isAssending: Bool) -> [Object] {
        let results = realmQueryWithSorted(realm: realm, object: object, predicate: predicate, sortedKey: sortedKey, isAssending: isAssending)
        var resultsArray = [Object]()
        if results.count > 0 {
            for i in 0...results.count - 1 {
                resultsArray.append(results[i])
            }
        }
        return resultsArray
    }

    ///  分页条件排序查询
    ///
    /// - Parameters:
    ///   - object: 查询类型
    ///   - predicate: 查询条件
    ///   - sortedKey: 排序key
    ///   - isAssending: 是否升序
    ///   - fromIndex: 起始页
    ///   - pageSize: 每页多少个
    /// - Returns: 查询结果
    public func realmQueryWithParametersAndSortedAndPaged(realm: Realm, object: Object.Type, predicate: NSPredicate, sortedKey: String, isAssending: Bool, fromIndex: Int, pageSize: Int) -> [Object] {
        let results = realmQueryWithSorted(realm: realm, object: object, predicate: predicate, sortedKey: sortedKey, isAssending: isAssending)
        var resultsArray = [Object]()

        if results.count <= pageSize * (fromIndex - 1) || fromIndex <= 0 {
            return resultsArray
        }

        if results.count > 0 {
            for i in pageSize * (fromIndex - 1)...fromIndex * pageSize - 1 {
                resultsArray.append(results[i])
            }
        }
        return resultsArray
    }

    // MARK: private method

    /// 按类型查询
    ///
    /// - Parameter object: 查询元素类型
    /// - Returns: 查询结果
    public func realmQueryWithType(realm: Realm, object: Object.Type) -> Results<Object> {
        return realm.objects(object)
    }

    /// 条件查询
    ///
    /// - Parameters:
    ///   - object: 查询元素类型
    ///   - predicate: 查询条件
    /// - Returns: 查询结果
    public func realmQueryWith(realm: Realm, object: Object.Type, predicate: NSPredicate) -> Results<Object> {
        return realm.objects(object).filter(predicate)
    }

    /// 条件排序查询
    ///
    /// - Parameters:
    ///   - object: 查询类型
    ///   - predicate: 查询条件
    ///   - sortedKey: 排序key
    ///   - isAssending: 是否升序
    /// - Returns: 查询结果
    public func realmQueryWithSorted(realm: Realm, object: Object.Type, predicate: NSPredicate, sortedKey: String, isAssending: Bool) -> Results<Object> {
        return realm.objects(object).filter(predicate)
            .sorted(byKeyPath: sortedKey, ascending: isAssending)
    }
}
