//
//  TravelAlbumOTGCoreTests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

/// 旅拍相册 OTG Core 逻辑测试。
final class TravelAlbumOTGCoreTests: XCTestCase {
    func testPlatformDetectorPrefersVendorID() {
        let sony = CameraDeviceInfo(
            name: "Unknown",
            manufacturer: nil,
            model: nil,
            serialNumber: nil,
            usbVendorID: 0x054C,
            usbProductID: nil
        )
        let canon = CameraDeviceInfo(
            name: "EOS R6",
            manufacturer: nil,
            model: nil,
            serialNumber: nil,
            usbVendorID: nil,
            usbProductID: nil
        )

        XCTAssertEqual(PlatformDetector.detect(from: sony), .sony)
        XCTAssertEqual(PlatformDetector.detect(from: canon), .canon)
    }

    func testPTPCommandBuildAndParse() throws {
        let data = PTPHelper.buildCommand(code: 0x1001, transactionID: 7, parameters: [1, 2])

        let parsed = try PTPHelper.parseContainer(data)

        XCTAssertEqual(parsed.length, 20)
        XCTAssertEqual(parsed.type, PTPContainerType.command.rawValue)
        XCTAssertEqual(parsed.code, 0x1001)
        XCTAssertEqual(parsed.transactionID, 7)
        XCTAssertEqual(parsed.params, [1, 2])
    }

    func testPhotoFormatMatcherResolvesJpegRawPeers() {
        let jpeg = CameraObject(id: "J", filename: "IMG_0001.JPG", fileSize: 1, capturedAt: Date())
        let raw = CameraObject(id: "R", filename: "IMG_0001.ARW", fileSize: 2, capturedAt: Date())
        let other = CameraObject(id: "O", filename: "IMG_0002.MOV", fileSize: 3, capturedAt: Date())

        XCTAssertEqual(TravelAlbumOTGPhotoFormatMatcher.classify(name: jpeg.filename), .jpeg)
        XCTAssertEqual(TravelAlbumOTGPhotoFormatMatcher.classify(name: raw.filename), .raw)
        XCTAssertEqual(TravelAlbumOTGPhotoFormatMatcher.classify(name: other.filename, isVideo: true), .other)

        let jpgTargets = TravelAlbumOTGPhotoFormatMatcher.resolveUploadTargets(
            requested: [raw],
            allObjects: [jpeg, raw, other],
            option: .jpg
        )
        let pairTargets = TravelAlbumOTGPhotoFormatMatcher.resolveUploadTargets(
            requested: [jpeg],
            allObjects: [jpeg, raw, other],
            option: .jpegRaw
        )

        XCTAssertEqual(jpgTargets.map(\.id), ["J"])
        XCTAssertEqual(pairTargets.map(\.id), ["J", "R"])
    }

    func testOSSAlbumObjectKeyUsesAlbumModule() {
        var calendar = Calendar(identifier: .gregorian)
        calendar.timeZone = TimeZone(secondsFromGMT: 0)!
        let date = calendar.date(from: DateComponents(year: 2026, month: 7, day: 7))!
        let uuid = UUID(uuidString: "11111111-2222-3333-4444-555555555555")!

        let key = OSSUploadPolicy.objectKey(
            fileName: "A/B.JPG",
            scenicId: 9,
            moduleType: "album",
            date: date,
            uuid: uuid,
            timeZone: TimeZone(secondsFromGMT: 0)!
        )

        XCTAssertTrue(key.hasPrefix("album/20260707/9/11111111222233334444555555555555_"))
        XCTAssertTrue(key.hasSuffix("A_B.JPG"))
    }

    func testOSSPunchPointObjectKeyUsesAndroidUserPath() {
        let previousUserId = AppStore.shared.session.userId
        AppStore.shared.session.userId = "u900"
        defer { AppStore.shared.session.userId = previousUserId }

        var calendar = Calendar(identifier: .gregorian)
        calendar.timeZone = TimeZone(secondsFromGMT: 0)!
        let date = calendar.date(from: DateComponents(year: 2026, month: 7, day: 9))!
        let uuid = UUID(uuidString: "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")!

        let key = OSSUploadPolicy.objectKey(
            fileName: "guide/photo.jpg",
            scenicId: 9,
            moduleType: "punch_point",
            date: date,
            uuid: uuid,
            timeZone: TimeZone(secondsFromGMT: 0)!
        )

        XCTAssertEqual(key, "punch_point/20260709/u900/aaaaaaaabbbbccccddddeeeeeeeeeeee_guide_photo.jpg")
    }

    func testOSSRealNameObjectKeyUsesAndroidUserPath() {
        let previousUserId = AppStore.shared.session.userId
        AppStore.shared.session.userId = "u901"
        defer { AppStore.shared.session.userId = previousUserId }

        var calendar = Calendar(identifier: .gregorian)
        calendar.timeZone = TimeZone(secondsFromGMT: 0)!
        let date = calendar.date(from: DateComponents(year: 2026, month: 7, day: 13))!
        let uuid = UUID(uuidString: "11111111-2222-3333-4444-555555555555")!

        let key = OSSUploadPolicy.objectKey(
            fileName: "id/front.jpg",
            scenicId: 9,
            moduleType: "real_name_auth",
            date: date,
            uuid: uuid,
            timeZone: TimeZone(secondsFromGMT: 0)!
        )

        XCTAssertEqual(key, "real_name_auth/20260713/u901/11111111222233334444555555555555_id_front.jpg")
    }

    func testOSSRealNamePathDoesNotChangeAvatarOrBankCardModules() {
        let date = Date(timeIntervalSince1970: 0)
        let uuid = UUID(uuidString: "11111111-2222-3333-4444-555555555555")!
        let timeZone = TimeZone(secondsFromGMT: 0)!

        let avatar = OSSUploadPolicy.objectKey(
            fileName: "avatar.jpg",
            scenicId: 9,
            moduleType: "user_avatar",
            date: date,
            uuid: uuid,
            timeZone: timeZone
        )
        let bankCard = OSSUploadPolicy.objectKey(
            fileName: "bank.jpg",
            scenicId: 9,
            moduleType: "bank_card",
            date: date,
            uuid: uuid,
            timeZone: timeZone
        )

        XCTAssertTrue(avatar.hasPrefix("avatar/19700101/9/"))
        XCTAssertTrue(bankCard.hasPrefix("bank_card/19700101/9/"))
    }
}
