import XCTest

final class RosettaUITests: XCTestCase {
    override func setUpWithError() throws {
        continueAfterFailure = false
    }

    private func launchFixture(mode: String) -> XCUIApplication {
        let app = XCUIApplication()
        app.launchArguments += ["-ui-test-voice-recording-fixture"]
        app.launchEnvironment["UI_TEST_VOICE_RECORDING_MODE"] = mode
        app.launch()
        return app
    }

    private func attachScreenshot(_ app: XCUIApplication, name: String) {
        let attachment = XCTAttachment(screenshot: app.screenshot())
        attachment.name = name
        attachment.lifetime = .keepAlways
        add(attachment)
    }

    @MainActor
    func testVoiceRecordingFixtureIdleLoads() {
        let app = launchFixture(mode: "idle")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.mic.button"].exists)
        attachScreenshot(app, name: "voice-fixture-idle")
    }

    @MainActor
    func testVoiceRecordingFixtureRecordingUnlockedLoads() {
        let app = launchFixture(mode: "recordingUnlocked")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.fixture.recordingPanel"].exists)
        XCTAssertTrue(app.otherElements["voice.recording.slideToCancel"].exists)
        attachScreenshot(app, name: "voice-fixture-recording-unlocked")
    }

    @MainActor
    func testVoiceRecordingFixtureLocking30Snapshot() {
        let app = launchFixture(mode: "locking30")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.fixture.lockView"].waitForExistence(timeout: 5))
        attachScreenshot(app, name: "voice-fixture-locking-30")
    }

    @MainActor
    func testVoiceRecordingFixtureLocking70SnapshotAndGeometry() {
        let app = launchFixture(mode: "locking70")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))

        let lockView = app.otherElements["voice.fixture.lockView"]
        XCTAssertTrue(lockView.waitForExistence(timeout: 5))
        XCTAssertEqual(lockView.frame.width, 40, accuracy: 1.0)
        XCTAssertEqual(lockView.frame.height, 72, accuracy: 1.0)
        attachScreenshot(app, name: "voice-fixture-locking-70")
    }

    @MainActor
    func testVoiceRecordingFixtureTimerDoesNotEllipsize() {
        let app = launchFixture(mode: "recordingUnlocked")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))

        let timer = app.staticTexts["voice.recording.timer"]
        XCTAssertTrue(timer.waitForExistence(timeout: 5))
        XCTAssertFalse(timer.label.contains("…"))
        XCTAssertFalse(timer.label.contains("..."))
        attachScreenshot(app, name: "voice-fixture-timer")
    }

    @MainActor
    func testVoiceRecordingFixtureCancelDragLoads() {
        let app = launchFixture(mode: "cancelDrag")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.fixture.recordingPanel"].exists)
        attachScreenshot(app, name: "voice-fixture-cancel-drag")
    }

    @MainActor
    func testVoiceRecordingFixtureRecordingLockedHas120StopArea() {
        let app = launchFixture(mode: "recordingLocked")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.fixture.lockView"].waitForExistence(timeout: 5))

        let stopArea = app.buttons["voice.recording.stopArea"]
        XCTAssertTrue(stopArea.waitForExistence(timeout: 5))
        XCTAssertGreaterThanOrEqual(stopArea.frame.width, 119.5)
        XCTAssertLessThanOrEqual(stopArea.frame.width, 120.5)
        XCTAssertGreaterThanOrEqual(stopArea.frame.height, 119.5)
        XCTAssertLessThanOrEqual(stopArea.frame.height, 120.5)

        let stopButton = app.buttons["voice.recording.stop"]
        XCTAssertTrue(stopButton.waitForExistence(timeout: 5))
        XCTAssertEqual(stopButton.frame.width, 40, accuracy: 1.0)
        XCTAssertEqual(stopButton.frame.height, 40, accuracy: 1.0)

        attachScreenshot(app, name: "voice-fixture-recording-locked")
    }

    @MainActor
    func testVoiceRecordingFixtureLockedStopButtonIsTappable() {
        let app = launchFixture(mode: "recordingLocked")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))

        let stopButton = app.buttons["voice.recording.stop"]
        XCTAssertTrue(stopButton.waitForExistence(timeout: 5))
        stopButton.tap()

        XCTAssertTrue(app.otherElements["voice.fixture.stopTapped"].waitForExistence(timeout: 2))
        attachScreenshot(app, name: "voice-fixture-stop-tapped")
    }

    @MainActor
    func testVoiceRecordingFixtureStopSnapshot() {
        let app = launchFixture(mode: "stop")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.buttons["voice.recording.stop"].waitForExistence(timeout: 5))
        attachScreenshot(app, name: "voice-fixture-stop")
    }

    @MainActor
    func testVoiceRecordingFixtureWaitingPreviewLoads() {
        let app = launchFixture(mode: "waitingPreview")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.fixture.lockView"].waitForExistence(timeout: 5))
        attachScreenshot(app, name: "voice-fixture-waiting-preview")
    }

    @MainActor
    func testVoiceRecordingFixturePreviewLoads() {
        let app = launchFixture(mode: "preview")

        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.otherElements["voice.preview.panel"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.buttons["voice.preview.send"].exists)
        XCTAssertTrue(app.buttons["voice.preview.recordMore"].exists)
        XCTAssertTrue(app.buttons["voice.preview.delete"].exists)
        XCTAssertTrue(app.buttons["voice.preview.playPause"].exists)
        XCTAssertTrue(app.otherElements["voice.preview.waveform"].exists)
        attachScreenshot(app, name: "voice-fixture-preview")
    }

    @MainActor
    func testVoiceRecordingFixturePreviewReplacesInputRowWithoutTrailingGap() {
        let app = launchFixture(mode: "preview")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))

        let preview = app.otherElements["voice.preview.panel"]
        let composer = app.otherElements["voice.fixture.composer"]
        XCTAssertTrue(preview.waitForExistence(timeout: 5))
        XCTAssertTrue(composer.waitForExistence(timeout: 5))

        XCTAssertEqual(preview.frame.minX, composer.frame.minX + 16, accuracy: 1.5)
        XCTAssertEqual(preview.frame.maxX, composer.frame.maxX - 16, accuracy: 1.5)

        let composerTextView = app.textViews["voice.composer.textView"]
        if composerTextView.exists {
            XCTAssertFalse(composerTextView.isHittable)
        }

        attachScreenshot(app, name: "voice-fixture-preview-row-parity")
    }

    @MainActor
    func testVoiceRecordingFixturePreviewTrimmedLoads() {
        let app = launchFixture(mode: "previewTrimmed")
        XCTAssertTrue(app.otherElements["voice.fixture.screen"].waitForExistence(timeout: 5))
        XCTAssertTrue(app.buttons["voice.preview.send"].exists)
        attachScreenshot(app, name: "voice-fixture-preview-trimmed")
    }
}
