//
//  ICCameraMetadataLoader.swift
//  otg_swift
//

import Foundation
@preconcurrency import ImageCaptureCore
import ImageIO

/// 从 `ICCameraFile` 读取拍摄时间；catalog 枚举阶段 EXIF 日期通常尚未加载，需主动 request metadata。
enum ICCameraMetadataLoader {

    static func captureDate(from file: ICCameraFile) async -> Date {
        if let date = immediateCaptureDate(from: file) {
            return date
        }

        if let metadata = await requestMetadata(from: file) {
            if let date = parseCaptureDate(from: metadata) {
                return date
            }
        }

        if let date = immediateCaptureDate(from: file) {
            return date
        }

        if let date = parseCaptureDate(fromFilename: file.name ?? "") {
            return date
        }

        return .distantPast
    }

    // MARK: - Private

    private static func immediateCaptureDate(from file: ICCameraFile) -> Date? {
        file.exifCreationDate ?? file.fileCreationDate ?? file.creationDate
    }

    private static func requestMetadata(from file: ICCameraFile) async -> [AnyHashable: Any]? {
        await withCheckedContinuation { continuation in
            file.requestMetadataDictionary(options: nil) { metadata, error in
                if let error {
                    OTGLog.debug(
                        .connection,
                        "metadata failed for \(file.name ?? "nil"): \(error.localizedDescription)"
                    )
                }
                continuation.resume(returning: metadata)
            }
        }
    }

    private static func parseCaptureDate(from metadata: [AnyHashable: Any]) -> Date? {
        if let exif = metadata[kCGImagePropertyExifDictionary as String] as? [String: Any],
           let date = parseEXIFDateString(exif[kCGImagePropertyExifDateTimeOriginal as String] as? String) {
            return date
        }

        if let tiff = metadata[kCGImagePropertyTIFFDictionary as String] as? [String: Any],
           let date = parseEXIFDateString(tiff[kCGImagePropertyTIFFDateTime as String] as? String) {
            return date
        }

        if let date = parseEXIFDateString(metadata[kCGImagePropertyExifDateTimeOriginal as String] as? String) {
            return date
        }

        return nil
    }

    private static func parseEXIFDateString(_ value: String?) -> Date? {
        guard let value, !value.isEmpty else { return nil }
        return exifDateFormatter.date(from: value)
    }

    /// 部分机身文件名含 `YYYYMMDD_HHMMSS` 或 `IMG_YYYYMMDD_HHMMSS`。
    private static func parseCaptureDate(fromFilename filename: String) -> Date? {
        let stem = (filename as NSString).deletingPathExtension
        let patterns = [
            (#"(\d{8})_(\d{6})"#, ["yyyyMMdd", "HHmmss"]),
            (#"IMG_(\d{8})_(\d{6})"#, ["yyyyMMdd", "HHmmss"])
        ]

        for (pattern, _) in patterns {
            guard let regex = try? NSRegularExpression(pattern: pattern),
                  let match = regex.firstMatch(in: stem, range: NSRange(stem.startIndex..., in: stem)),
                  match.numberOfRanges == 3,
                  let dateRange = Range(match.range(at: 1), in: stem),
                  let timeRange = Range(match.range(at: 2), in: stem) else {
                continue
            }

            let datePart = String(stem[dateRange])
            let timePart = String(stem[timeRange])
            guard let date = filenameDateFormatter.date(from: datePart),
                  let time = filenameTimeFormatter.date(from: timePart) else {
                continue
            }

            var components = Calendar.current.dateComponents([.year, .month, .day], from: date)
            let timeComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: time)
            components.hour = timeComponents.hour
            components.minute = timeComponents.minute
            components.second = timeComponents.second
            return Calendar.current.date(from: components)
        }

        return nil
    }

    private static let exifDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy:MM:dd HH:mm:ss"
        return formatter
    }()

    private static let filenameDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyyMMdd"
        return formatter
    }()

    private static let filenameTimeFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "HHmmss"
        return formatter
    }()
}
