//
//  UIWindow+Ext.swift
//  DouYinSwift5
//
//  Created by lym on 2020/7/23.
//  Copyright © 2020 lym. All rights reserved.
//

import Foundation
import UIKit

public extension String {
    static func randomString(_ length: Int) -> String {
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        return String((0 ..< length).map { _ in letters.randomElement()! })
    }

    init(deviceToken: Data) {
        self = deviceToken.map { String(format: "%.2hhx", $0) }.joined()
    }

    /// 是否包含
//    func contains(_ regular: String) -> Bool {
//        return range(of: regular, options: .regularExpression, range: nil, locale: nil) != nil
//    }

    /// 去掉字符串首尾的空格换行，中间的空格和换行忽略
    var trimmed: String {
        return trimmingCharacters(in: .whitespacesAndNewlines)
    }

    func removeSpaceAndNewLine() -> String {
        return trimmingCharacters(in: .whitespacesAndNewlines)
    }

    var removingAllWhitespace: String {
        return replacingOccurrences(of: " ", with: "")
    }

    /// 是否不为空
    ///
    /// "", "  ", "\n", "  \n   "都视为空
    /// 不为空返回true， 为空返回false
    var isNotBlank: Bool {
        return !trimmed.isEmpty
    }

    /// 字符串的全部范围
    var rangeOfAll: NSRange {
        return NSRange(location: 0, length: count)
    }

    /// 是否为 nil 或者为 ""
    static func realEmpty(str: String?) -> Bool {
        return (str == nil || str == "")
    }

    /// JSON 字符串 转换为 字典
    func toDictionary() -> [String: Any]? {
        guard let jsonData = data(using: .utf8),
              let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        else {
            return nil
        }
        return (dict as! [String: Any])
    }

    /// JSON 字符串 转换为  Array
    func jsonStringToArray() -> [Any]? {
        guard let jsonData: Data = data(using: .utf8),
              let array = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
        else {
            return nil
        }
        return (array as! [Any])
    }

    /// 获取范围
    @discardableResult
    func matchStrRange(_ matchStr: String) -> [NSRange] {
        var selfStr = self as NSString
        var withStr = Array(repeating: "X", count: (matchStr as NSString).length).joined(separator: "") // 辅助字符串
        if matchStr == withStr { withStr = withStr.lowercased() } // 临时处理辅助字符串差错
        var allRange = [NSRange]()
        while selfStr.range(of: matchStr).location != NSNotFound {
            let range = selfStr.range(of: matchStr)
            allRange.append(NSRange(location: range.location, length: range.length))
            selfStr = selfStr.replacingCharacters(in: NSMakeRange(range.location, range.length), with: withStr) as NSString
        }
        return allRange
    }

    /// 数字和字母混合
    static func randomAlphaNumericString(length: Int) -> String {
        let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let allowedCharsCount = UInt32(allowedChars.count)
        var randomString = ""

        for _ in 0 ..< length {
            let randomNum = Int(arc4random_uniform(allowedCharsCount))
            let randomIndex = allowedChars.index(allowedChars.startIndex, offsetBy: randomNum)
            let newCharacter = allowedChars[randomIndex]
            randomString += String(newCharacter)
        }

        return randomString
    }
    
    /// 生成指定长度的随机数字字符串
    static func randomNumber(length: Int) -> String {
        var result = ""
        for _ in 0..<length {
            let digit = Int.random(in: 0...9)
            result.append("\(digit)")
        }
        return result
    }

    /// 支持动态键的翻译方法
    func localized(_ bundle: Bundle = .main, tableName: String = "Localizable") -> String {
        return NSLocalizedString(self, tableName: tableName, bundle: bundle, comment: "")
    }
}

// MAKR : 正则分割
// 定义一个结构体来承载分割后的结果
struct SplitedResult {
    let fragment: String
    let isMatched: Bool
    let captures: [String?]
}

extension String {
    /// 正则分割字符串
    func split(
        usingRegex pattern: String,
        options: NSRegularExpression.Options = .dotMatchesLineSeparators
    ) -> [SplitedResult] {
        do {
            let regex = try NSRegularExpression(pattern: pattern, options: options)
            let matches = regex.matches(in: self, options: [], range: NSRange(location: 0, length: utf16.count))

            var currentIndex = startIndex
            var range: Range<String.Index>
            var captures: [String?] = []
            var results: [SplitedResult] = []
            for match in matches {
                range = Range(match.range, in: self)!
                if range.lowerBound > currentIndex {
                    results.append(SplitedResult(fragment: String(self[currentIndex ..< range.lowerBound]), isMatched: false, captures: []))
                }

                if match.numberOfRanges > 1 {
                    for i in 1 ..< match.numberOfRanges {
                        if let _range = Range(match.range(at: i), in: self) {
                            captures.append(String(self[_range]))
                        } else {
                            captures.append(nil)
                        }
                    }
                }

                results.append(SplitedResult(fragment: String(self[range]), isMatched: true, captures: captures))
                currentIndex = range.upperBound
                captures.removeAll()
            }

            if endIndex > currentIndex {
                results.append(SplitedResult(fragment: String(self[currentIndex ..< endIndex]), isMatched: false, captures: []))
            }

            return results
        } catch {
            fatalError("正则表达式有误，请更正后再试！")
        }
    }
}

extension String {
    // base64
    func encodeBase64() -> String {
        let plainData = data(using: String.Encoding.utf8)
        let base64String = plainData?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0))
        return base64String!
    }

    //
    func decodeBase64() -> String {
        let decodedData = NSData(base64Encoded: self, options: NSData.Base64DecodingOptions(rawValue: 0))
        let decodedString = NSString(data: decodedData! as Data, encoding: String.Encoding.utf8.rawValue)! as String
        return decodedString
    }
}

extension String {
    /// 计算字体宽度 字体大小
    public func textWidth(font: UIFont) -> CGFloat {
        let str = self as NSString
        let size = CGSize(width: 20000, height: 100)
        let attributes = [NSAttributedString.Key.font: font]
        let labelSize = str.boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: attributes, context: nil).size
        return labelSize.width
    }

    /// 计算指定字体的尺寸
    ///
    /// - Parameters:
    ///   - font: 字体
    ///   - size: 区域大小
    ///   - lineBreakMode: 换行模式
    /// - Returns: 尺寸
    func size(for font: UIFont, size: CGSize, lineBreakMode: NSLineBreakMode) -> CGSize {
        var attr: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: font]
        if lineBreakMode != .byWordWrapping {
            let paragraphStyle = NSMutableParagraphStyle()
            paragraphStyle.lineBreakMode = lineBreakMode
            attr[.paragraphStyle] = paragraphStyle
        }
        let rect = (self as NSString).boundingRect(with: size, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attr, context: nil)
        return rect.size
    }
}

// MARK: - Extensions

extension String {
    var isValidEmail: Bool {
        let emailPattern = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
        let emailPred = NSPredicate(format: "SELF MATCHES %@", emailPattern)
        return emailPred.evaluate(with: self)
    }
    
    var isValidNickname: Bool{
        return self.trimmed.count >= 2
    }
}

extension String {
    /// Displays a number with B, M, K suffixes based on magnitude
    static func displayNumber(_ num: NSNumber, scale: Int) -> String {
        if num.doubleValue == 0 {
            return "0"
        }

        let dm = NSDecimalNumber(decimal: num.decimalValue)
        let handler = NSDecimalNumberHandler(
            roundingMode: .down,
            scale: Int16(scale),
            raiseOnExactness: false,
            raiseOnOverflow: false,
            raiseOnUnderflow: false,
            raiseOnDivideByZero: true
        )

        let dm_1 = NSDecimalNumber(string: "1.0")
        let dm_1000 = NSDecimalNumber(string: "1000.0")
        let dm_1000000 = NSDecimalNumber(string: "1000000.0")
        let dm_1000000000 = NSDecimalNumber(string: "1000000000.0")

        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = scale
        formatter.numberStyle = .decimal
        formatter.roundingMode = .down
        formatter.locale = Locale.current // Assuming LanguagesUtils.locale() returns current locale

        switch num.doubleValue {
        case let value where value >= 1000000000:
            let number = dm.dividing(by: dm_1000000000, withBehavior: handler)
            guard let res = formatter.string(from: number) else { return "" }
            return "\(res)B"

        case let value where value >= 1000000:
            let number = dm.dividing(by: dm_1000000, withBehavior: handler)
            guard let res = formatter.string(from: number) else { return "" }
            return "\(res)M"

        case let value where value >= 1000:
            let number = dm.dividing(by: dm_1000, withBehavior: handler)
            guard let res = formatter.string(from: number) else { return "" }
            return "\(res)K"

        default:
            let number = dm.dividing(by: dm_1, withBehavior: handler)
            guard let res = formatter.string(from: number) else { return "" }
            return res
        }
    }

    /// Displays double with K rule, showing one decimal place for large numbers
    static func displayDouble(_ num: Double) -> String {
        if num < 1000.0 {
            return displayNumber(NSNumber(value: num), scale: 0)
        }
        return displayNumber(NSNumber(value: num), scale: 1)
    }

    /// Displays integer with K rule, defaultscale is 0
    static func displayInteger(_ num: Int) -> String {
        displayNumber(NSNumber(value: num), scale: 0)
    }

    /// Displays timer from milliseconds
    static func displayTimer(_ ms: Int) -> String {
        let day = ms / (1000 * 60 * 60 * 24)
        let hour = (ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)
        let minute = (ms % (1000 * 60 * 60)) / (1000 * 60)
        let second = (ms % (1000 * 60)) / 1000

        switch (day, hour, minute) {
        case let (d, _, _) where d >= 1:
            return String(format: "%ldd %ldh", day, hour)
        case let (0, h, m) where h > 0:
            return String(format: "%ldh %ldm", hour, m)
        case let (0, 0, m) where m >= 0:
            return String(format: "%02ld:%02ld", m, second)
        default:
            return String(format: "%02ld:%02ld", minute, second)
        }
    }

    /// Formats integer with thousand separator
    static func thousandString(_ num: Int) -> String {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = 0
        formatter.numberStyle = .decimal
        formatter.locale = Locale.current
        return formatter.string(from: NSNumber(value: num)) ?? ""
    }

    /// Formats double with thousand separator, two decimal places
    static func thousandString(float num: Double) -> String {
        thousandString(float: num, maxDigits: 2)
    }

    /// Converts formatted string back to double
    static func float(fromThousandString string: String) -> Double {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = 2
        formatter.numberStyle = .decimal
        formatter.locale = Locale.current
        return formatter.number(from: string)?.doubleValue ?? 0.0
    }

    /// Formats double with thousand separator and specified decimal places
    static func thousandString(float num: Double, maxDigits: Int) -> String {
        thousandString(float: num, maxDigits: maxDigits, roundingMode: .down)
    }

    /// Formats double with thousand separator, specified decimal places and rounding mode
    static func thousandString(float num: Double, maxDigits: Int, roundingMode: NumberFormatter.RoundingMode) -> String {
        thousandString(float: num, maxDigits: maxDigits, locale: Locale.current, roundingMode: roundingMode)
    }

    /// Formats double with thousand separator, specified decimal places, locale, and rounding mode
    static func thousandString(float num: Double, maxDigits: Int, locale: Locale, roundingMode: NumberFormatter.RoundingMode) -> String {
        let formatter = NumberFormatter()
        formatter.maximumFractionDigits = maxDigits
        formatter.numberStyle = .decimal
        formatter.roundingMode = roundingMode
        formatter.locale = locale
        return formatter.string(from: NSNumber(value: num)) ?? ""
    }

    /// Formats number with ordinal suffix (st, nd, rd, th)
    static func numberSequence(_ num: Int) -> String {
        let subNum = num % 10
        if num > 10 && num < 20 {
            return "\(num)th"
        }

        switch subNum {
        case 1:
            return "\(num)st"
        case 2:
            return "\(num)nd"
        case 3:
            return "\(num)rd"
        default:
            return "\(num)th"
        }
    }
    
    /// 将括号以及括号内的文字的range全部输出
    static func findBracketRanges(in text: String) -> [NSRange] {
        // 匹配英文 () 或中文 （）
        let pattern = "(\\([^)]*\\))|(（[^）]*）)"
        
        guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
            print("Invalid regex pattern")
            return []
        }
        
        let nsString = text as NSString
        let range = NSRange(location: 0, length: nsString.length)
        
        var ranges: [NSRange] = []
        regex.enumerateMatches(in: text, options: [], range: range) { (match, _, _) in
            if let matchRange = match?.range {
                ranges.append(matchRange)
            }
        }
        
        return ranges
    }
    
    /// 将（）()中的文字删除后，剩余的文字
    static func removeBracketContents(from text: String) -> String {
        let ranges = findBracketRanges(in: text)
        guard !ranges.isEmpty else { return text }
        
        let nsString = text as NSString
        let mutable = NSMutableString(string: text)
        
        // 倒序删除，避免 range 偏移
        for range in ranges.reversed() {
            mutable.deleteCharacters(in: range)
        }
        
        return String(mutable)
    }
}
