//
// Copyright (c) Double Symmetry GmbH
// Commercial use requires a license. See https://rntp.dev/pricing
//

import XCTest

@testable import Models

final class MediaURLTests: XCTestCase {

  // MARK: - String inputs

  func testHTTPSStringIsRemote() {
    let url = MediaURL(object: "https://example.com/song.mp3")
    XCTAssertNotNil(url)
    XCTAssertFalse(url!.isLocal)
    XCTAssertEqual(url!.value.absoluteString, "https://example.com/song.mp3")
  }

  func testHTTPStringIsRemote() {
    let url = MediaURL(object: "http://example.com/song.mp3")
    XCTAssertNotNil(url)
    XCTAssertFalse(url!.isLocal)
  }

  func testFileURLStringIsLocal() {
    let url = MediaURL(object: "file:///var/mobile/Documents/song.mp3")
    XCTAssertNotNil(url)
    XCTAssertTrue(url!.isLocal)
    XCTAssertEqual(url!.value.path, "/var/mobile/Documents/song.mp3")
    XCTAssertTrue(url!.value.isFileURL)
  }

  func testFileURLWithUnencodedSpaceFallsBackToFilePath() {
    // `URL(string:)` returns nil for unencoded spaces; we fall back to a
    // file-URL-from-path so callers don't have to pre-encode.
    let url = MediaURL(object: "file:///tmp/has space.mp3")
    XCTAssertNotNil(url)
    XCTAssertTrue(url!.isLocal)
    XCTAssertEqual(url!.value.path, "/tmp/has space.mp3")
  }

  func testBareAbsolutePathIsLocal() {
    let url = MediaURL(object: "/var/mobile/Documents/song.mp3")
    XCTAssertNotNil(url)
    XCTAssertTrue(url!.isLocal)
    XCTAssertEqual(url!.value.path, "/var/mobile/Documents/song.mp3")
    XCTAssertTrue(url!.value.isFileURL)
  }

  func testCustomSchemePassesThrough() {
    let url = MediaURL(object: "ipod-library://item/song?id=42")
    XCTAssertNotNil(url)
    XCTAssertFalse(url!.isLocal)
    XCTAssertEqual(url!.value.scheme, "ipod-library")
  }

  func testEmptyStringRejected() {
    XCTAssertNil(MediaURL(object: ""))
  }

  func testNilRejected() {
    XCTAssertNil(MediaURL(object: nil))
  }

  // MARK: - Dictionary inputs

  func testDictWithFileURI() {
    let url = MediaURL(object: ["uri": "file:///tmp/song.mp3"] as [String: Any])
    XCTAssertNotNil(url)
    XCTAssertTrue(url!.isLocal)
  }

  func testDictWithHTTPURI() {
    let url = MediaURL(object: ["uri": "https://example.com/song.mp3"] as [String: Any])
    XCTAssertNotNil(url)
    XCTAssertFalse(url!.isLocal)
  }

  func testDictWithLegacyURLKey() {
    // V4-compat: `url` key is also accepted in addition to `uri`.
    let url = MediaURL(object: ["url": "https://example.com/song.mp3"] as [String: Any])
    XCTAssertNotNil(url)
    XCTAssertEqual(url!.value.absoluteString, "https://example.com/song.mp3")
  }

  func testDictWithHeaders() {
    let url = MediaURL(object: [
      "uri": "https://example.com/song.mp3",
      "headers": ["Authorization": "Bearer xyz"],
    ] as [String: Any])
    XCTAssertNotNil(url)
    XCTAssertEqual(url!.headers?["Authorization"], "Bearer xyz")
  }

  func testStringInputHasNoHeaders() {
    let url = MediaURL(object: "https://example.com/song.mp3")
    XCTAssertNil(url!.headers)
  }

  func testDictWithMissingURIRejected() {
    XCTAssertNil(MediaURL(object: [:] as [String: Any]))
  }

  // MARK: - asset:// bundle resolution

  func testAssetSchemeWithNonexistentResourceReturnsNil() {
    // No resource named "definitely_does_not_exist.mp3" in the test bundle.
    XCTAssertNil(MediaURL(object: "asset://definitely_does_not_exist.mp3"))
  }

  func testAssetSchemeWithEmptyNameReturnsNil() {
    XCTAssertNil(MediaURL(object: "asset://"))
  }

  // MARK: - MediaItem-equivalent derivation
  // MediaItem derives sourceUrl and sourceType from MediaURL.isLocal and
  // MediaURL.value. These tests verify the contract that code path depends on.

  func testLocalURLProducesBarePath() {
    let url = MediaURL(object: "file:///var/mobile/Documents/song.mp3")!
    // MediaItem uses `url.value.path` when isLocal == true
    XCTAssertTrue(url.isLocal)
    XCTAssertEqual(url.value.path, "/var/mobile/Documents/song.mp3")
  }

  func testRemoteURLProducesAbsoluteString() {
    let url = MediaURL(object: "https://example.com/song.mp3")!
    // MediaItem uses `url.value.absoluteString` when isLocal == false
    XCTAssertFalse(url.isLocal)
    XCTAssertEqual(url.value.absoluteString, "https://example.com/song.mp3")
  }

  func testBarePathProducesFileURLWithCorrectPath() {
    let url = MediaURL(object: "/var/mobile/Documents/song.mp3")!
    XCTAssertTrue(url.isLocal)
    XCTAssertTrue(url.value.isFileURL)
    // Round-trip: path extracted from the file URL matches the original input
    XCTAssertEqual(url.value.path, "/var/mobile/Documents/song.mp3")
  }

  func testDictWithBarePathIsLocal() {
    let url = MediaURL(object: ["uri": "/tmp/downloaded.mp3"] as [String: Any])!
    XCTAssertTrue(url.isLocal)
    XCTAssertEqual(url.value.path, "/tmp/downloaded.mp3")
  }
}
