import XCTest
import RideFormCore
@testable import RideForm

final class RecordingPersistenceTests: XCTestCase {
    func testTwoSessionsExportCancellationAndRelaunch() throws {
        let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
        let repository = SessionRepository(directory: root.appendingPathComponent("Sessions"))
        func record(_ timestamp: Double) throws -> URL {
            let manifest = SessionManifest()
            let url = try repository.begin(manifest: manifest)
            repository.enqueue(.motion(MotionSample(sensorTimestamp: timestamp)))
            let done = expectation(description: "saved")
            repository.finalize(summary: CaptureSummary(capabilities: [.motion: .available, .accelerometer: .unavailable(reason: "disabled"), .gyroscope: .available], acceptedCounts: [.motion: 1], ended: ClockAnchor(hostUptime: timestamp + 1), clockMapping: ClockMapping(), rotationConvention: RotationConvention())) { result in
                if case .failure(let error) = result { XCTFail(String(describing: error)) }
                done.fulfill()
            }
            wait(for: [done], timeout: 5)
            return url
        }
        let first = try record(1.1234567890123457)
        let original = try Data(contentsOf: first.appendingPathComponent("manifest.json"))
        let exporter = ShareExporter(temporaryDirectory: root.appendingPathComponent("share"))
        let files = try exporter.prepare(bundle: first)
        XCTAssertTrue(files.contains { $0.pathExtension == "zip" })
        // Cancelling the share sheet only abandons presentation, never modifies evidence.
        _ = try record(8.987654321098765)
        let relaunched = SessionRepository(directory: repository.directory)
        XCTAssertEqual(try relaunched.list().count, 2)
        XCTAssertEqual(try relaunched.load(first).motion.samples[0].sensorTimestamp, 1.1234567890123457)
        XCTAssertEqual(try Data(contentsOf: first.appendingPathComponent("manifest.json")), original)
    }
    func testRelaunchRecoveryRetainsIncompleteOriginal() throws {
        let root = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
        let first = SessionRepository(directory: root)
        let source = try first.begin(manifest: SessionManifest())
        first.enqueue(.motion(MotionSample(sensorTimestamp: 2)))
        let checkpoint = expectation(description: "checkpoint")
        first.checkpoint { _ in checkpoint.fulfill() }
        wait(for: [checkpoint], timeout: 5)
        let bytes = try Data(contentsOf: source.appendingPathComponent("manifest.json"))
        let relaunched = SessionRepository(directory: root)
        let recovery = expectation(description: "recovery")
        relaunched.recoverIncomplete(source) { result in
            switch result {
            case .failure(let error): XCTFail(String(describing: error))
            case .success(let url):
                XCTAssertNotEqual(url, source)
                let session = try? relaunched.load(url)
                XCTAssertEqual(session?.motion.samples.count, 1)
                XCTAssertEqual(session?.manifest.boundaries.status, "interrupted")
            }
            recovery.fulfill()
        }
        wait(for: [recovery], timeout: 5)
        XCTAssertEqual(try Data(contentsOf: source.appendingPathComponent("manifest.json")), bytes)
        XCTAssertEqual(try relaunched.list().count, 2)
    }
}
