import AppKit
import Foundation
@testable import peekaboo
import Testing

@Suite("Image Capture Logic Tests", .tags(.imageCapture, .unit))
struct ImageCaptureLogicTests {
    // MARK: - File Name Generation Tests

    @Test("File name generation for displays", .tags(.fast))
    func fileNameGenerationDisplays() throws {
        // We can't directly test private methods, but we can test the logic
        // through public interfaces and verify the expected patterns

        // Test that different screen indices would generate different names
        let command1 = try ImageCommand.parse(["--screen-index", "0", "--format", "png"])
        let command2 = try ImageCommand.parse(["--screen-index", "1", "--format", "png"])

        #expect(command1.screenIndex == 0)
        #expect(command2.screenIndex == 1)
        #expect(command1.format == .png)
        #expect(command2.format == .png)
    }

    @Test("File name generation for applications", .tags(.fast))
    func fileNameGenerationApplications() throws {
        let command = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Test App",
            "--window-title", "Main Window",
            "--format", "jpg"
        ])

        #expect(command.app == "Test App")
        #expect(command.windowTitle == "Main Window")
        #expect(command.format == .jpg)
    }

    @Test("Output path generation", .tags(.fast))
    func outputPathGeneration() throws {
        // Test default path behavior
        let defaultCommand = try ImageCommand.parse([])
        #expect(defaultCommand.path == nil)

        // Test custom path
        let customCommand = try ImageCommand.parse(["--path", "/tmp/screenshots"])
        #expect(customCommand.path == "/tmp/screenshots")

        // Test path with filename
        let fileCommand = try ImageCommand.parse(["--path", "/tmp/test.png"])
        #expect(fileCommand.path == "/tmp/test.png")
    }

    // MARK: - Mode Determination Tests

    @Test("Mode determination comprehensive", .tags(.fast))
    func modeDeterminationComprehensive() throws {
        // Screen mode (default when no app specified)
        let screenCmd = try ImageCommand.parse([])
        #expect(screenCmd.mode == nil)
        #expect(screenCmd.app == nil)

        // Window mode (when app specified but no explicit mode)
        let windowCmd = try ImageCommand.parse(["--app", "Finder"])
        #expect(windowCmd.mode == nil) // Will be determined as window during execution
        #expect(windowCmd.app == "Finder")

        // Explicit modes
        let explicitScreen = try ImageCommand.parse(["--mode", "screen"])
        #expect(explicitScreen.mode == .screen)

        let explicitWindow = try ImageCommand.parse(["--mode", "window", "--app", "Safari"])
        #expect(explicitWindow.mode == .window)
        #expect(explicitWindow.app == "Safari")

        let explicitMulti = try ImageCommand.parse(["--mode", "multi"])
        #expect(explicitMulti.mode == .multi)
    }

    // MARK: - Window Targeting Tests

    @Test("Window targeting by title", .tags(.fast))
    func windowTargetingByTitle() throws {
        let command = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Safari",
            "--window-title", "Main Window"
        ])

        #expect(command.mode == .window)
        #expect(command.app == "Safari")
        #expect(command.windowTitle == "Main Window")
        #expect(command.windowIndex == nil)
    }

    @Test("Window targeting by index", .tags(.fast))
    func windowTargetingByIndex() throws {
        let command = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Terminal",
            "--window-index", "0"
        ])

        #expect(command.mode == .window)
        #expect(command.app == "Terminal")
        #expect(command.windowIndex == 0)
        #expect(command.windowTitle == nil)
    }

    @Test("Window targeting priority - title vs index", .tags(.fast))
    func windowTargetingPriority() throws {
        // When both title and index are specified, both are preserved
        let command = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Xcode",
            "--window-title", "Main",
            "--window-index", "1"
        ])

        #expect(command.windowTitle == "Main")
        #expect(command.windowIndex == 1)
        // In actual execution, title matching would take precedence
    }

    // MARK: - Screen Targeting Tests

    @Test("Screen targeting by index", .tags(.fast))
    func screenTargetingByIndex() throws {
        let command = try ImageCommand.parse([
            "--mode", "screen",
            "--screen-index", "1"
        ])

        #expect(command.mode == .screen)
        #expect(command.screenIndex == 1)
    }

    @Test(
        "Screen index edge cases",
        arguments: [-1, 0, 1, 5, 99, Int.max]
    )
    func screenIndexEdgeCases(index: Int) throws {
        let command = try ImageCommand.parse([
            "--mode", "screen",
            "--screen-index", String(index)
        ])

        #expect(command.screenIndex == index)
        // Validation happens during execution, not parsing
    }

    // MARK: - Capture Focus Tests

    @Test("Capture focus modes", .tags(.fast))
    func captureFocusModes() throws {
        // Default background mode
        let defaultCmd = try ImageCommand.parse([])
        #expect(defaultCmd.captureFocus == .background)

        // Explicit background mode
        let backgroundCmd = try ImageCommand.parse(["--capture-focus", "background"])
        #expect(backgroundCmd.captureFocus == .background)

        // Foreground mode
        let foregroundCmd = try ImageCommand.parse(["--capture-focus", "foreground"])
        #expect(foregroundCmd.captureFocus == .foreground)
    }

    // MARK: - Image Format Tests

    @Test("Image format handling", .tags(.fast))
    func imageFormatHandling() throws {
        // Default PNG format
        let defaultCmd = try ImageCommand.parse([])
        #expect(defaultCmd.format == .png)

        // Explicit PNG format
        let pngCmd = try ImageCommand.parse(["--format", "png"])
        #expect(pngCmd.format == .png)

        // JPEG format
        let jpgCmd = try ImageCommand.parse(["--format", "jpg"])
        #expect(jpgCmd.format == .jpg)
    }

    @Test("MIME type mapping", .tags(.fast))
    func mimeTypeMapping() {
        // Test MIME type logic (as used in SavedFile creation)
        let pngMime = ImageFormat.png == .png ? "image/png" : "image/jpeg"
        let jpgMime = ImageFormat.jpg == .jpg ? "image/jpeg" : "image/png"

        #expect(pngMime == "image/png")
        #expect(jpgMime == "image/jpeg")
    }

    // MARK: - Error Handling Tests

    @Test("Error code mapping", .tags(.fast))
    func errorCodeMapping() {
        // Test error code mapping logic used in handleError
        let testCases: [(CaptureError, ErrorCode)] = [
            (.screenRecordingPermissionDenied, .PERMISSION_ERROR_SCREEN_RECORDING),
            (.accessibilityPermissionDenied, .PERMISSION_ERROR_ACCESSIBILITY),
            (.appNotFound("test"), .APP_NOT_FOUND),
            (.windowNotFound, .WINDOW_NOT_FOUND),
            (.fileWriteError("test", nil), .FILE_IO_ERROR),
            (.invalidArgument("test"), .INVALID_ARGUMENT),
            (.unknownError("test"), .UNKNOWN_ERROR)
        ]

        // Verify error mapping logic exists
        for (_, expectedCode) in testCases {
            // We can't directly test the private method, but verify the errors exist
            // Verify the error exists (non-nil check not needed for value types)
            #expect(Bool(true))
            #expect(!expectedCode.rawValue.isEmpty)
        }
    }

    // MARK: - SavedFile Creation Tests

    @Test("SavedFile creation for screen capture", .tags(.fast))
    func savedFileCreationScreenCapture() {
        let savedFile = SavedFile(
            path: "/tmp/screen-0.png",
            item_label: "Display 1 (Index 0)",
            window_title: nil,
            window_id: nil,
            window_index: nil,
            mime_type: "image/png"
        )

        #expect(savedFile.path == "/tmp/screen-0.png")
        #expect(savedFile.item_label == "Display 1 (Index 0)")
        #expect(savedFile.window_title == nil)
        #expect(savedFile.window_id == nil)
        #expect(savedFile.window_index == nil)
        #expect(savedFile.mime_type == "image/png")
    }

    @Test("SavedFile creation for window capture", .tags(.fast))
    func savedFileCreationWindowCapture() {
        let savedFile = SavedFile(
            path: "/tmp/safari-main.jpg",
            item_label: "Safari",
            window_title: "Main Window",
            window_id: 12345,
            window_index: 0,
            mime_type: "image/jpeg"
        )

        #expect(savedFile.path == "/tmp/safari-main.jpg")
        #expect(savedFile.item_label == "Safari")
        #expect(savedFile.window_title == "Main Window")
        #expect(savedFile.window_id == 12345)
        #expect(savedFile.window_index == 0)
        #expect(savedFile.mime_type == "image/jpeg")
    }

    // MARK: - Complex Configuration Tests

    @Test("Complex multi-window capture configuration", .tags(.fast))
    func complexMultiWindowConfiguration() throws {
        let command = try ImageCommand.parse([
            "--mode", "multi",
            "--app", "Visual Studio Code",
            "--format", "png",
            "--path", "/tmp/vscode-windows",
            "--capture-focus", "foreground",
            "--json-output"
        ])

        #expect(command.mode == .multi)
        #expect(command.app == "Visual Studio Code")
        #expect(command.format == .png)
        #expect(command.path == "/tmp/vscode-windows")
        #expect(command.captureFocus == .foreground)
        #expect(command.jsonOutput == true)
    }

    @Test("Complex screen capture configuration", .tags(.fast))
    func complexScreenCaptureConfiguration() throws {
        let command = try ImageCommand.parse([
            "--mode", "screen",
            "--screen-index", "1",
            "--format", "jpg",
            "--path", "/Users/test/screenshots/display-1.jpg",
            "--json-output"
        ])

        #expect(command.mode == .screen)
        #expect(command.screenIndex == 1)
        #expect(command.format == .jpg)
        #expect(command.path == "/Users/test/screenshots/display-1.jpg")
        #expect(command.jsonOutput == true)
    }

    // MARK: - Performance Tests

    @Test("Configuration parsing performance", .tags(.performance))
    func configurationParsingPerformance() {
        let complexArgs = [
            "--mode", "multi",
            "--app", "Long Application Name With Many Words",
            "--window-title", "Very Long Window Title That Might Be Common",
            "--window-index", "5",
            "--screen-index", "2",
            "--format", "jpg",
            "--path", "/very/long/path/to/some/directory/structure/screenshots/image.jpg",
            "--capture-focus", "foreground",
            "--json-output"
        ]

        let startTime = CFAbsoluteTimeGetCurrent()

        // Parse many times to test performance
        for _ in 1...100 {
            do {
                let command = try ImageCommand.parse(complexArgs)
                #expect(command.mode == .multi)
            } catch {
                Issue.record("Parsing should not fail: \(error)")
            }
        }

        let duration = CFAbsoluteTimeGetCurrent() - startTime
        #expect(duration < 1.0) // Should parse 1000 configs within 1 second
    }

    // MARK: - Integration Readiness Tests

    @Test("Command readiness for screen capture", .tags(.fast))
    func commandReadinessScreenCapture() throws {
        let command = try ImageCommand.parse(["--mode", "screen"])

        // Verify command is properly configured for screen capture
        #expect(command.mode == .screen)
        #expect(command.app == nil) // No app needed for screen capture
        #expect(command.format == .png) // Has default format
    }

    @Test("Command readiness for window capture", .tags(.fast))
    func commandReadinessWindowCapture() throws {
        let command = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Finder"
        ])

        // Verify command is properly configured for window capture
        #expect(command.mode == .window)
        #expect(command.app == "Finder") // App is required
        #expect(command.format == .png) // Has default format
    }

    @Test("Command validation for invalid configurations", .tags(.fast))
    func commandValidationInvalidConfigurations() {
        // These should parse successfully but would fail during execution

        // Window mode without app (would fail during execution)
        do {
            let command = try ImageCommand.parse(["--mode", "window"])
            #expect(command.mode == .window)
            #expect(command.app == nil) // This would cause execution failure
        } catch {
            Issue.record("Should parse successfully")
        }

        // Invalid screen index (would fail during execution)
        do {
            let command = try ImageCommand.parse(["--screen-index", "-1"])
            #expect(command.screenIndex == -1) // This would cause execution failure
        } catch {
            Issue.record("Should parse successfully")
        }
    }
}

// MARK: - Extended Capture Logic Tests

@Suite("Advanced Image Capture Logic", .tags(.imageCapture, .integration))
struct AdvancedImageCaptureLogicTests {
    @Test("Multi-mode capture scenarios", .tags(.fast))
    func multiModeCaptureScenarios() throws {
        // Multi mode with app (should capture all windows)
        let multiWithApp = try ImageCommand.parse([
            "--mode", "multi",
            "--app", "Safari"
        ])
        #expect(multiWithApp.mode == .multi)
        #expect(multiWithApp.app == "Safari")

        // Multi mode without app (should capture all screens)
        let multiWithoutApp = try ImageCommand.parse(["--mode", "multi"])
        #expect(multiWithoutApp.mode == .multi)
        #expect(multiWithoutApp.app == nil)
    }

    @Test("Focus mode implications", .tags(.fast))
    func focusModeImplications() throws {
        // Foreground focus should work with any capture mode
        let foregroundScreen = try ImageCommand.parse([
            "--mode", "screen",
            "--capture-focus", "foreground"
        ])
        #expect(foregroundScreen.captureFocus == .foreground)

        let foregroundWindow = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Terminal",
            "--capture-focus", "foreground"
        ])
        #expect(foregroundWindow.captureFocus == .foreground)

        // Background focus (default) should work without additional permissions
        let backgroundCapture = try ImageCommand.parse([
            "--mode", "window",
            "--app", "Finder"
        ])
        #expect(backgroundCapture.captureFocus == .background)
    }

    @Test("Path handling edge cases", .tags(.fast))
    func pathHandlingEdgeCases() throws {
        // Relative paths
        let relativePath = try ImageCommand.parse(["--path", "./screenshots/test.png"])
        #expect(relativePath.path == "./screenshots/test.png")

        // Home directory expansion
        let homePath = try ImageCommand.parse(["--path", "~/Desktop/capture.jpg"])
        #expect(homePath.path == "~/Desktop/capture.jpg")

        // Absolute paths
        let absolutePath = try ImageCommand.parse(["--path", "/tmp/absolute/path.png"])
        #expect(absolutePath.path == "/tmp/absolute/path.png")

        // Paths with spaces
        let spacePath = try ImageCommand.parse(["--path", "/path with spaces/image.png"])
        #expect(spacePath.path == "/path with spaces/image.png")

        // Unicode paths
        let unicodePath = try ImageCommand.parse(["--path", "/tmp/测试/スクリーン.png"])
        #expect(unicodePath.path == "/tmp/测试/スクリーン.png")
    }

    @Test("Command execution readiness matrix", .tags(.fast))
    func commandExecutionReadinessMatrix() {
        let scenarios = createTestScenarios()

        for scenario in scenarios {
            do {
                let command = try ImageCommand.parse(scenario.args)
                if scenario.shouldBeReady {
                    // Verify basic readiness
                    #expect(command.format == .png)
                    #expect(command.captureFocus == .background)
                }
            } catch {
                if scenario.shouldBeReady {
                    Issue.record("Scenario '\(scenario.description)' should parse successfully: \(error)")
                }
            }
        }
    }

    @Test("Error propagation scenarios", .tags(.fast))
    func errorPropagationScenarios() {
        // Test that invalid arguments are properly handled
        let invalidArgs: [[String]] = [
            ["--mode", "invalid"],
            ["--format", "bmp"],
            ["--capture-focus", "invalid"],
            ["--screen-index", "abc"],
            ["--window-index", "xyz"]
        ]

        for args in invalidArgs {
            #expect(throws: (any Error).self) {
                _ = try ImageCommand.parse(args)
            }
        }
    }

    @Test("Memory efficiency with complex configurations", .tags(.memory))
    func memoryEfficiencyComplexConfigurations() {
        // Test that complex configurations don't cause excessive memory usage
        let complexConfigs: [[String]] = [
            ["--mode", "multi", "--app", String(repeating: "LongAppName", count: 100)],
            ["--window-title", String(repeating: "VeryLongTitle", count: 200)],
            ["--path", String(repeating: "/very/long/path", count: 50)],
            Array(repeating: ["--mode", "screen"], count: 100).flatMap(\.self)
        ]

        for config in complexConfigs {
            do {
                _ = try ImageCommand.parse(config)
                #expect(Bool(true)) // Command parsed successfully
            } catch {
                // Some may fail due to argument parsing limits, which is expected
                #expect(Bool(true))
            }
        }
    }

    // MARK: - Helper Functions

    private struct TestScenario {
        let args: [String]
        let shouldBeReady: Bool
        let description: String
    }

    private func createTestScenarios() -> [TestScenario] {
        [
            TestScenario(
                args: ["--mode", "screen"],
                shouldBeReady: true,
                description: "Basic screen capture"
            ),
            TestScenario(
                args: ["--mode", "screen", "--screen-index", "0"],
                shouldBeReady: true,
                description: "Screen with index"
            ),
            TestScenario(
                args: ["--mode", "window", "--app", "Finder"],
                shouldBeReady: true,
                description: "Basic window capture"
            ),
            TestScenario(
                args: ["--mode", "window", "--app", "Safari", "--window-title", "Main"],
                shouldBeReady: true,
                description: "Window with title"
            ),
            TestScenario(
                args: ["--mode", "window", "--app", "Terminal", "--window-index", "0"],
                shouldBeReady: true,
                description: "Window with index"
            ),
            TestScenario(
                args: ["--mode", "multi"],
                shouldBeReady: true,
                description: "Multi-screen capture"
            ),
            TestScenario(
                args: ["--mode", "multi", "--app", "Xcode"],
                shouldBeReady: true,
                description: "Multi-window capture"
            ),
            TestScenario(
                args: ["--app", "Finder"],
                shouldBeReady: true,
                description: "Implicit window mode"
            ),
            TestScenario(
                args: [],
                shouldBeReady: true,
                description: "Default screen capture"
            )
        ]
    }
}
