//
//  MediaPreviewItem.swift
//  suixinkan
//

import UIKit

/// 媒体预览资源项，描述可全屏预览的图片或视频。
public struct MediaPreviewItem: Hashable {

    /// 媒体类型。
    public enum MediaType: Equatable {
        case image
        case video
    }

    /// 预览资源来源。
    public enum Source {
        case remoteImage(URL)
        case localImageFile(URL)
        case image(UIImage)
        case remoteVideo(URL)
        case localVideoFile(URL)
    }

    /// 资源唯一标识，用于 Diffable Data Source。
    public let id: UUID

    /// 预览资源来源。
    public let source: Source

    /// 创建媒体预览资源项。
    public init(id: UUID = UUID(), source: Source) {
        self.id = id
        self.source = source
    }

    /// 媒体类型。
    public var mediaType: MediaType {
        switch source {
        case .remoteImage, .localImageFile, .image:
            return .image
        case .remoteVideo, .localVideoFile:
            return .video
        }
    }

    /// 是否为图片资源。
    public var isImage: Bool {
        mediaType == .image
    }

    /// 是否为视频资源。
    public var isVideo: Bool {
        mediaType == .video
    }

    /// 通过远程图片地址创建资源项，空字符串或非法地址返回 nil。
    public static func remoteImage(_ urlString: String) -> MediaPreviewItem? {
        makeRemoteURL(from: urlString).map { MediaPreviewItem(source: .remoteImage($0)) }
    }

    /// 通过远程视频地址创建资源项，空字符串或非法地址返回 nil。
    public static func remoteVideo(_ urlString: String) -> MediaPreviewItem? {
        makeRemoteURL(from: urlString).map { MediaPreviewItem(source: .remoteVideo($0)) }
    }

    /// 通过本地图片文件地址创建资源项。
    public static func localImage(url: URL) -> MediaPreviewItem {
        MediaPreviewItem(source: .localImageFile(url))
    }

    /// 通过本地图片对象创建资源项。
    public static func image(_ image: UIImage) -> MediaPreviewItem {
        MediaPreviewItem(source: .image(image))
    }

    /// 通过本地视频文件地址创建资源项。
    public static func localVideo(url: URL) -> MediaPreviewItem {
        MediaPreviewItem(source: .localVideoFile(url))
    }

    /// 将起始索引限制在可用范围内。
    public static func clampedStartIndex(_ startIndex: Int, itemCount: Int) -> Int {
        guard itemCount > 0 else { return 0 }
        return min(max(0, startIndex), itemCount - 1)
    }

    /// 从媒体数组中读取安全的起始资源项。
    public static func currentItem(in items: [MediaPreviewItem], startIndex: Int) -> MediaPreviewItem? {
        guard !items.isEmpty else { return nil }
        return items[clampedStartIndex(startIndex, itemCount: items.count)]
    }

    public static func == (lhs: MediaPreviewItem, rhs: MediaPreviewItem) -> Bool {
        lhs.id == rhs.id
    }

    public func hash(into hasher: inout Hasher) {
        hasher.combine(id)
    }

    private static func makeRemoteURL(from text: String) -> URL? {
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmed.isEmpty, let url = URL(string: trimmed) else { return nil }
        guard let scheme = url.scheme?.lowercased(), ["http", "https"].contains(scheme) else { return nil }
        return url
    }
}
