//
//  LegacyDataModels.swift
//  Yattee
//
//  Data models for parsing v1 UserDefaults format during migration.
//

import Foundation

// MARK: - Legacy Instance

/// Represents a v1 Instance stored in UserDefaults under the "instances" key.
/// The v1 format used Defaults.Serializable with a bridge that stored instances as [String: String] dictionaries.
struct LegacyInstance {
    /// The app type: "invidious", "piped", "peerTube", "local"
    let app: String

    /// UUID string identifier
    let id: String

    /// User-defined name for the instance
    let name: String

    /// The API URL string (e.g., "https://invidious.example.com")
    let apiURL: String

    /// Optional frontend URL (used by Piped)
    let frontendURL: String?

    /// Whether the instance proxies videos
    let proxiesVideos: Bool

    /// Whether to use Invidious Companion
    let invidiousCompanion: Bool

    /// Parses a dictionary from v1 UserDefaults format.
    /// - Parameter dictionary: The serialized instance dictionary
    /// - Returns: A LegacyInstance if parsing succeeds, nil otherwise
    static func parse(from dictionary: [String: Any]) -> LegacyInstance? {
        guard let app = dictionary["app"] as? String,
              let id = dictionary["id"] as? String,
              let apiURL = dictionary["apiURL"] as? String else {
            return nil
        }

        let name = dictionary["name"] as? String ?? ""
        let frontendURL = dictionary["frontendURL"] as? String
        let proxiesVideos = (dictionary["proxiesVideos"] as? String) == "true"
        let invidiousCompanion = (dictionary["invidiousCompanion"] as? String) == "true"

        return LegacyInstance(
            app: app,
            id: id,
            name: name,
            apiURL: apiURL,
            frontendURL: frontendURL?.isEmpty == true ? nil : frontendURL,
            proxiesVideos: proxiesVideos,
            invidiousCompanion: invidiousCompanion
        )
    }

    /// Converts the legacy app type string to the v2 InstanceType.
    var instanceType: InstanceType? {
        switch app.lowercased() {
        case "invidious":
            return .invidious
        case "piped":
            return .piped
        case "peertube":
            return .peertube
        default:
            return nil
        }
    }

    /// The URL object for this instance.
    var url: URL? {
        URL(string: apiURL)
    }
}

// MARK: - Legacy Import Item

/// Represents an instance to be imported from v1 data.
/// Only instances are imported - users need to re-add their accounts after import.
struct LegacyImportItem: Identifiable, Sendable {
    /// New UUID for UI identification
    let id: UUID

    /// The original v1 instance ID
    let legacyInstanceID: String

    /// The type of instance (Invidious or Piped)
    let instanceType: InstanceType

    /// The instance URL
    let url: URL

    /// User-defined name for the instance
    let name: String?

    /// Whether this item is selected for import
    var isSelected: Bool = true

    /// Current reachability status
    var reachabilityStatus: ReachabilityStatus = .unknown

    /// Display name for the UI
    var displayName: String {
        if let name, !name.isEmpty {
            return name
        }
        return url.host ?? url.absoluteString
    }
}

// MARK: - Reachability Status

/// Status of an instance's reachability check.
enum ReachabilityStatus: Sendable {
    /// Not yet checked
    case unknown
    /// Currently checking
    case checking
    /// Instance is reachable
    case reachable
    /// Instance is unreachable
    case unreachable
}

// MARK: - Migration Result

/// Result of an import operation.
struct MigrationResult {
    /// Items that were successfully imported
    let succeeded: [LegacyImportItem]

    /// Items that failed to import with their errors
    let failed: [(item: LegacyImportItem, error: MigrationError)]

    /// Items that were skipped because they already exist
    let skippedDuplicates: [LegacyImportItem]

    /// Whether all selected items were successfully imported
    var isFullSuccess: Bool {
        failed.isEmpty
    }

    /// Total number of items processed
    var totalProcessed: Int {
        succeeded.count + failed.count + skippedDuplicates.count
    }
}

// MARK: - Migration Error

/// Errors that can occur during migration.
enum MigrationError: LocalizedError, Sendable {
    case invalidURL
    case unknown(String)

    var errorDescription: String? {
        switch self {
        case .invalidURL:
            return String(localized: "migration.error.invalidURL")
        case .unknown(let message):
            return message
        }
    }
}
