//
//  ImageNamingUtils.swift

import CryptoKit
import Foundation

/// Utility for creating consistent image filenames across platforms
class ImageNamingUtils {

    private static let imageExtension = ".jpg"
    private static let hashLength = 12

    /// Generates a deterministic filename for a problem image
    static func generateImageFilename(problemId: String, imageIndex: Int) -> String {
        let input = "\(problemId)_\(imageIndex)"
        let hash = createHash(from: input)

        return "problem_\(hash)_\(imageIndex)\(imageExtension)"
    }

    /// Legacy method for backward compatibility
    static func generateImageFilename(problemId: String, timestamp: String, imageIndex: Int)
        -> String
    {
        return generateImageFilename(problemId: problemId, imageIndex: imageIndex)
    }

    /// Extracts problem ID from an image filename
    static func extractProblemIdFromFilename(_ filename: String) -> String? {
        guard filename.hasPrefix("problem_") && filename.hasSuffix(imageExtension) else {
            return nil
        }

        let nameWithoutExtension = String(filename.dropLast(imageExtension.count))
        let parts = nameWithoutExtension.components(separatedBy: "_")

        guard parts.count == 3 && parts[0] == "problem" else {
            return nil
        }

        return parts[1]
    }

    /// Validates if a filename follows our naming convention
    static func isValidImageFilename(_ filename: String) -> Bool {
        guard filename.hasPrefix("problem_") && filename.hasSuffix(imageExtension) else {
            return false
        }

        let nameWithoutExtension = String(filename.dropLast(imageExtension.count))
        let parts = nameWithoutExtension.components(separatedBy: "_")

        return parts.count == 3 && parts[0] == "problem" && parts[1].count == hashLength
            && Int(parts[2]) != nil
    }

    /// Migrates an existing filename to our naming convention
    static func migrateFilename(oldFilename: String, problemId: String, imageIndex: Int) -> String {

        if isValidImageFilename(oldFilename) {
            return oldFilename
        }

        return generateImageFilename(problemId: problemId, imageIndex: imageIndex)
    }

    /// Creates a deterministic hash from input string
    private static func createHash(from input: String) -> String {
        let inputData = Data(input.utf8)
        let hashed = SHA256.hash(data: inputData)
        let hashString = hashed.compactMap { String(format: "%02x", $0) }.joined()
        return String(hashString.prefix(hashLength))
    }

    /// Batch renames images for a problem to use our naming convention
    static func batchRenameForProblem(problemId: String, existingFilenames: [String]) -> [String:
        String]
    {
        var renameMap: [String: String] = [:]

        for (index, oldFilename) in existingFilenames.enumerated() {
            let newFilename = generateImageFilename(problemId: problemId, imageIndex: index)
            if newFilename != oldFilename {
                renameMap[oldFilename] = newFilename
            }
        }

        return renameMap
    }

    /// Validates that a collection of filenames follow our naming convention
    static func validateFilenames(_ filenames: [String]) -> ImageValidationResult {
        var validImages: [String] = []
        var invalidImages: [String] = []

        for filename in filenames {
            if isValidImageFilename(filename) {
                validImages.append(filename)
            } else {
                invalidImages.append(filename)
            }
        }

        return ImageValidationResult(
            totalImages: filenames.count,
            validImages: validImages,
            invalidImages: invalidImages
        )
    }

    static func getCanonicalImageFilename(problemId: String, imageIndex: Int) -> String {
        return generateImageFilename(problemId: problemId, imageIndex: imageIndex)
    }

    /// Creates a mapping of existing server filenames to canonical filenames
    static func createServerMigrationMap(
        problemId: String,
        serverImageFilenames: [String],
        localImageCount: Int
    ) -> [String: String] {
        var migrationMap: [String: String] = [:]

        for imageIndex in 0..<localImageCount {
            let canonicalName = getCanonicalImageFilename(
                problemId: problemId, imageIndex: imageIndex)

            if serverImageFilenames.contains(canonicalName) {
                continue
            }

            for serverFilename in serverImageFilenames {
                if isValidImageFilename(serverFilename)
                    && !migrationMap.values.contains(serverFilename)
                {
                    migrationMap[serverFilename] = canonicalName
                    break
                }
            }
        }

        return migrationMap
    }
}

// Result of image filename validation
struct ImageValidationResult {
    let totalImages: Int
    let validImages: [String]
    let invalidImages: [String]

    var isAllValid: Bool {
        return invalidImages.isEmpty
    }

    var validPercentage: Double {
        guard totalImages > 0 else { return 100.0 }
        return (Double(validImages.count) / Double(totalImages)) * 100.0
    }
}
