import Foundation
import UIKit
import CoreImage.CIFilterBuiltins

// MARK: - 条形码生成器
class BarcodeGenerator {
    
    // MARK: - 单例
    static let shared = BarcodeGenerator()
    
    private init() {}
    
    // MARK: - 生成条形码图片
    /// 根据内容和类型生成条形码图片
    /// - Parameters:
    ///   - content: 条形码内容
    ///   - type: 条形码类型
    ///   - size: 图片尺寸，默认 CGSize(width: 300, height: 120)
    /// - Returns: 生成的条形码图片
    func generateBarcode(from content: String, type: String, size: CGSize = CGSize(width: 300, height: 120), showText: Bool = true) -> UIImage? {
        guard !content.isEmpty else { return nil }
        
        // 根据条形码类型选择合适的生成方式
        switch type.lowercased() {
        case let t where t.contains("ean13"):
            return generateEAN13Barcode(from: content, size: size, showText: showText)
        case let t where t.contains("ean8"):
            return generateEAN8Barcode(from: content, size: size, showText: showText)
        case let t where t.contains("upce"):
            return generateUPCEBarcode(from: content, size: size, showText: showText)
        case let t where t.contains("code39"):
            return generateCode39Barcode(from: content, size: size, showText: showText)
        case let t where t.contains("code128"):
            return generateCode128Barcode(from: content, size: size, showText: showText)
        case let t where t.contains("pdf417"):
            return generatePDF417Barcode(from: content, size: size, showText: showText)
        case let t where t.contains("itf14"):
            return generateITF14Barcode(from: content, size: size, showText: showText)
        default:
            // 默认使用 Code 128
            return generateCode128Barcode(from: content, size: size, showText: showText)
        }
    }
    
    // MARK: - EAN-13 条形码生成
    private func generateEAN13Barcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.code128BarcodeGenerator()
        
        // EAN-13 需要13位数字
        let paddedContent = content.padding(toLength: 13, withPad: "0", startingAt: 0)
        filter.message = Data(paddedContent.utf8)
        filter.quietSpace = 7.0
        
        return processBarcodeFilter(filter, context: context, size: size, content: paddedContent, showText: showText)
    }
    
    // MARK: - EAN-8 条形码生成
    private func generateEAN8Barcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.code128BarcodeGenerator()
        
        // EAN-8 需要8位数字
        let paddedContent = content.padding(toLength: 8, withPad: "0", startingAt: 0)
        filter.message = Data(paddedContent.utf8)
        filter.quietSpace = 7.0
        
        return processBarcodeFilter(filter, context: context, size: size, content: paddedContent, showText: showText)
    }
    
    // MARK: - UPC-E 条形码生成
    private func generateUPCEBarcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.code128BarcodeGenerator()
        
        // UPC-E 需要8位数字
        let paddedContent = content.padding(toLength: 8, withPad: "0", startingAt: 0)
        filter.message = Data(paddedContent.utf8)
        filter.quietSpace = 7.0
        
        return processBarcodeFilter(filter, context: context, size: size, content: paddedContent, showText: showText)
    }
    
    // MARK: - Code 39 条形码生成
    private func generateCode39Barcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.code128BarcodeGenerator()
        
        // Code 39 支持字母数字
        filter.message = Data(content.utf8)
        filter.quietSpace = 7.0
        
        return processBarcodeFilter(filter, context: context, size: size, content: content, showText: showText)
    }
    
    // MARK: - Code 128 条形码生成
    private func generateCode128Barcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.code128BarcodeGenerator()
        
        filter.message = Data(content.utf8)
        filter.quietSpace = 7.0
        
        return processBarcodeFilter(filter, context: context, size: size, content: content, showText: showText)
    }
    
    // MARK: - PDF417 条形码生成
    private func generatePDF417Barcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.pdf417BarcodeGenerator()
        
        filter.message = Data(content.utf8)
        filter.minWidth = 3
        filter.maxWidth = 3
        filter.minHeight = 3
        filter.maxHeight = 3
        
        return processBarcodeFilter(filter, context: context, size: size, content: content, showText: showText)
    }
    
    // MARK: - ITF-14 条形码生成
    private func generateITF14Barcode(from content: String, size: CGSize, showText: Bool) -> UIImage? {
        let context = CIContext()
        let filter = CIFilter.code128BarcodeGenerator()
        
        // ITF-14 需要14位数字
        let paddedContent = content.padding(toLength: 14, withPad: "0", startingAt: 0)
        filter.message = Data(paddedContent.utf8)
        filter.quietSpace = 7.0
        
        return processBarcodeFilter(filter, context: context, size: size, content: paddedContent, showText: showText)
    }
    
    // MARK: - 处理条形码滤镜
    private func processBarcodeFilter(_ filter: CIFilter, context: CIContext, size: CGSize, content: String, showText: Bool) -> UIImage? {
        guard let outputImage = filter.outputImage else { return nil }
        
        // 计算缩放比例以适应目标尺寸
        let scaleX = size.width / outputImage.extent.width
        let scaleY = size.height / outputImage.extent.height
        
        // 应用缩放变换
        let transform = CGAffineTransform(scaleX: scaleX, y: scaleY)
        let scaledImage = outputImage.transformed(by: transform)
        
        // 转换为 UIImage
        guard let cgImage = context.createCGImage(scaledImage, from: scaledImage.extent) else { return nil }
        
        let baseImage = UIImage(cgImage: cgImage)
        
        // 如果需要显示文本，在条形码下方添加文本标签
        if showText {
            return addTextLabel(to: baseImage, content: content, size: size)
        }
        
        return baseImage
    }
    
    // MARK: - 添加文本标签
    private func addTextLabel(to image: UIImage, content: String, size: CGSize) -> UIImage? {
        let renderer = UIGraphicsImageRenderer(size: size)
        
        return renderer.image { context in
            // 绘制原始条形码图片
            image.draw(in: CGRect(origin: .zero, size: size))
            
            // 设置文本属性
            let textAttributes: [NSAttributedString.Key: Any] = [
                .font: UIFont.systemFont(ofSize: 12, weight: .medium),
                .foregroundColor: UIColor.black
            ]
            
            // 计算每个字符的位置，让每个数字对应其条形码位置
            let charWidth = size.width / CGFloat(content.count)
            let textY = size.height - 20 // 距离底部20像素
            
            // 为每个字符绘制背景和文本
            for (index, char) in content.enumerated() {
                let charString = String(char)
                let charSize = charString.size(withAttributes: textAttributes)
                
                // 计算字符的X位置（居中对齐到对应的条形码区域）
                let charX = CGFloat(index) * charWidth + (charWidth - charSize.width) / 2
                
                // 绘制字符背景（白色背景，确保可读性）
                let backgroundRect = CGRect(
                    x: charX - 2,
                    y: textY - 2,
                    width: charSize.width + 4,
                    height: charSize.height + 4
                )
                
                UIColor.white.setFill()
                context.fill(backgroundRect)
                
                // 绘制字符
                charString.draw(at: CGPoint(x: charX, y: textY), withAttributes: textAttributes)
            }
        }
    }
    
    // MARK: - 获取条形码图标
    /// 根据条形码类型获取对应的图标名称
    /// - Parameter type: 条形码类型
    /// - Returns: 图标名称
    func getBarcodeIcon(for type: String) -> String {
        let lowercasedType = type.lowercased()
        
        if lowercasedType.contains("ean") || lowercasedType.contains("upc") {
            return "barcode"
        } else if lowercasedType.contains("code39") || lowercasedType.contains("code128") {
            return "barcode.viewfinder"
        } else if lowercasedType.contains("pdf417") {
            return "qrcode.viewfinder"
        } else if lowercasedType.contains("itf14") {
            return "barcode"
        } else {
            return "barcode"
        }
    }
    
    // MARK: - 验证条形码内容
    /// 验证条形码内容是否符合类型要求
    /// - Parameters:
    ///   - content: 条形码内容
    ///   - type: 条形码类型
    /// - Returns: 是否有效
    func validateBarcodeContent(_ content: String, type: String) -> Bool {
        guard !content.isEmpty else { return false }
        
        let lowercasedType = type.lowercased()
        
        switch lowercasedType {
        case let t where t.contains("ean13"):
            return content.count == 13 && content.allSatisfy { $0.isNumber }
        case let t where t.contains("ean8"):
            return content.count == 8 && content.allSatisfy { $0.isNumber }
        case let t where t.contains("upce"):
            return content.count == 8 && content.allSatisfy { $0.isNumber }
        case let t where t.contains("itf14"):
            return content.count == 14 && content.allSatisfy { $0.isNumber }
        case let t where t.contains("code39"):
            // Code 39 支持字母、数字和一些特殊字符
            return content.allSatisfy { $0.isLetter || $0.isNumber || " -.$/+%".contains($0) }
        case let t where t.contains("code128"):
            // Code 128 支持 ASCII 字符
            return content.allSatisfy { $0.asciiValue != nil }
        case let t where t.contains("pdf417"):
            // PDF417 支持二进制数据
            return true
        default:
            return true
        }
    }
}

// MARK: - String 扩展
extension String {
    /// 将字符串填充到指定长度
    /// - Parameters:
    ///   - length: 目标长度
    ///   - pad: 填充字符
    ///   - startingAt: 开始位置
    /// - Returns: 填充后的字符串
    func padding(toLength length: Int, withPad pad: String, startingAt startIndex: Int) -> String {
        if self.count >= length {
            return String(self.prefix(length))
        }
        
        let paddingLength = length - self.count
        let padding = String(repeating: pad, count: paddingLength)
        return self + padding
    }
} 