import ComposableArchitecture
import Foundation

// MARK: - Structured App Storage Variable Definitions

public enum AppStorageVariableType: Equatable {
    case boolean(defaultValue: Bool)
    case integer(defaultValue: Int)
    case double(defaultValue: Double)
    case string(defaultValue: String)
    case stringArray(defaultValue: [String])
    case date(defaultValue: Date?)
    case timeInterval(defaultValue: TimeInterval)
    case enumType(cases: [String], defaultCase: String, typeName: String)

    public var displayTypeName: String {
        switch self {
        case .boolean: return "Bool"
        case .integer: return "Int"
        case .double: return "Double"
        case .string: return "String"
        case .stringArray: return "[String]"
        case .date: return "Date?"
        case .timeInterval: return "TimeInterval"
        case .enumType(_, _, let typeName): return typeName
        }
    }
}

// MARK: - Simple Type-Safe Enum Support

public extension AppStorageVariableType {
    /// Creates an enumType case using actual enum types for full type safety
    /// - Parameters:
    ///   - type: The enum type (e.g., AppearanceMode.self)
    ///   - defaultCase: The default enum case (e.g., .system)
    /// - Returns: An enumType case with type-safe configuration
    static func enumType<T: CaseIterable & RawRepresentable>(
        _ type: T.Type,
        defaultCase: T
    ) -> AppStorageVariableType where T.RawValue == String {
        return .enumType(
            cases: type.allCases.map { $0.rawValue },
            defaultCase: defaultCase.rawValue,
            typeName: String(describing: type)
        )
    }
}

public struct AppStorageVariableDefinition {
    public let key: String
    public let type: AppStorageVariableType
    public let displayName: String?
    public let description: String?

    public init(key: String, type: AppStorageVariableType, displayName: String? = nil, description: String? = nil) {
        self.key = key
        self.type = type
        self.displayName = displayName
        self.description = description
    }

    public var computedDisplayName: String {
        return displayName ?? key.camelCaseToTitleCase()
    }
}

public extension String {
    // MARK: - Complete App Storage Variable Registry

    static let appStorageVariables: [AppStorageVariableDefinition] = [
        AppStorageVariableDefinition(
            key: Self.selectedBackendEnvironment,
            type: .enumType(
                cases: ["production", "staging"],
                defaultCase: "production",
                typeName: "BackendEnvironment"
            ),
            displayName: "Backend Environment Override",
            description: "Staff builds only. Overrides backend environment selection."
        ),
        // Boolean Flags
        AppStorageVariableDefinition(
            key: Self.hasSeenHowToUseAudio,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen the audio usage tutorial"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenContextPrompt,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen the context prompt tutorial"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenFtuxTwoClips,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen the two clips FTUX"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenCellularSceneUploadsAlert,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen cellular upload warning"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenFeaturedArtist,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen featured artist content"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenInternationalInvitesAlert,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen international invites alert"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenCreateFirstSong,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen create first song prompt"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenRemasterTooltip,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen remaster tooltip"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenHooksOnboarding,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen hooks onboarding flow"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenFirstTimeTabSelection,
            type: .boolean(defaultValue: false),
            description: "Whether user has completed first-time tab selection experience"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenOmniPlayerTooltipThisSession,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen omniplayer tooltip this session"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenTapToMakeMoreExtensionsTooltip,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen tap to make extensions tooltip"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenExtendOmniPlayerTooltip,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen extend omniplayer tooltip"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenAudioCreateStyleTooltip,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen audio create style tooltip"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenVideoSongArtWalkthroughAlert,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen video song art walkthrough"
        ),
        // Boolean Flags
        AppStorageVariableDefinition(
            key: Self.hasUsedCaptionsFeature,
            type: .boolean(defaultValue: false),
            description: "Whether user has used captions feature"
        ),
        AppStorageVariableDefinition(
            key: Self.hasUsedVideoCoversFeature,
            type: .boolean(defaultValue: false),
            description: "Whether user has used video covers feature"
        ),
        AppStorageVariableDefinition(
            key: Self.hasRated,
            type: .boolean(defaultValue: false),
            description: "Whether user has rated the app"
        ),
        AppStorageVariableDefinition(
            key: Self.contactSyncSeen,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen contact sync prompt"
        ),
        AppStorageVariableDefinition(
            key: Self.showInviteFriends,
            type: .boolean(defaultValue: true),
            description: "Whether to show invite friends prompts"
        ),
        AppStorageVariableDefinition(
            key: Self.isCreatorsToFollowVisible,
            type: .boolean(defaultValue: true),
            description: "Whether creators to follow section is visible"
        ),
        AppStorageVariableDefinition(
            key: Self.isShareAssetCreationMuted,
            type: .boolean(defaultValue: false),
            description: "Whether share asset creation is muted"
        ),
        AppStorageVariableDefinition(
            key: Self.isCompactPlayerVisible,
            type: .boolean(defaultValue: false),
            description: "Whether compact player is visible"
        ),
        AppStorageVariableDefinition(
            key: Self.lastCameraFlashToggleMode,
            type: .boolean(defaultValue: false),
            description: "Last camera flash toggle state"
        ),
        AppStorageVariableDefinition(
            key: Self.tappedAddNumberButtonInProfile,
            type: .boolean(defaultValue: false),
            description: "Whether user tapped add phone number in profile"
        ),
        AppStorageVariableDefinition(
            key: Self.readyNewGensCount,
            type: .integer(defaultValue: 0),
            description: "Number of new gens ready to play"
        ),
        AppStorageVariableDefinition(
            key: Self.dismissedInviteFriendsDiscover,
            type: .boolean(defaultValue: false),
            description: "Whether user dismissed invite friends in discover"
        ),
        AppStorageVariableDefinition(
            key: Self.dismissedContactSyncCreatorsToFollow,
            type: .boolean(defaultValue: false),
            description: "Whether user dismissed contact sync creators prompt"
        ),
        AppStorageVariableDefinition(
            key: Self.dismissedContactSyncDiscover,
            type: .boolean(defaultValue: false),
            description: "Whether user dismissed contact sync in discover"
        ),
        AppStorageVariableDefinition(
            key: Self.dismissedInternationalInvitesDiscover,
            type: .boolean(defaultValue: false),
            description: "Whether user dismissed international invites in discover"
        ),
        AppStorageVariableDefinition(
            key: Self.dismissedFeaturedArtistDiscover,
            type: .boolean(defaultValue: false),
            description: "Whether user dismissed featured artist in discover"
        ),
        AppStorageVariableDefinition(
            key: Self.hasDismissedPushNotificationBanner,
            type: .boolean(defaultValue: false),
            description: "Whether user dismissed push notification banner"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenNewSongsOmniPlayerTooltip,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen new songs ready tooltip"
        ),

        // Integer Counters
        AppStorageVariableDefinition(
            key: Self.likeCount,
            type: .integer(defaultValue: 0),
            description: "Number of likes given by user"
        ),
        AppStorageVariableDefinition(
            key: Self.shareCount,
            type: .integer(defaultValue: 0),
            description: "Number of shares by user"
        ),
        AppStorageVariableDefinition(
            key: Self.addedToPlaylist,
            type: .integer(defaultValue: 0),
            description: "Number of clips added to playlists"
        ),
        AppStorageVariableDefinition(
            key: Self.songCreateCount,
            type: .integer(defaultValue: 0),
            description: "Number of songs created by user"
        ),
        AppStorageVariableDefinition(
            key: Self.promoCodeUrlRedemptionsLeft,
            type: .integer(defaultValue: 0),
            description: "Number of promo code redemptions remaining"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenDeprecateScenesBanner,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen the deprecate scenes banner"
        ),
        AppStorageVariableDefinition(
            key: Self.hasSeenV5Announcement,
            type: .boolean(defaultValue: false),
            description: "Whether user has seen the V5 announcement"
        ),

        // Time Intervals
        AppStorageVariableDefinition(
            key: Self.lastRatingRequestSeen,
            type: .timeInterval(defaultValue: 0),
            description: "Timestamp of last rating request shown"
        ),

        // Strings
        AppStorageVariableDefinition(
            key: Self.promoCodeUrl,
            type: .string(defaultValue: ""),
            description: "Current promo code URL"
        ),
        AppStorageVariableDefinition(
            key: Self.alignedLyricsMap,
            type: .string(defaultValue: ""),
            description: "Map of aligned lyrics data"
        ),
        AppStorageVariableDefinition(
            key: Self.analyticsSessionId,
            type: .string(defaultValue: ""),
            description: "Current analytics session identifier"
        ),

        // String Arrays
        AppStorageVariableDefinition(
            key: Self.dismissedAnnouncements,
            type: .stringArray(defaultValue: []),
            description: "List of dismissed announcement IDs"
        ),
        AppStorageVariableDefinition(
            key: Self.dismissedNotificationsBannerId,
            type: .string(defaultValue: ""),
            description: "ID of the currently dismissed notification banner"
        ),
        AppStorageVariableDefinition(
            key: Self.clipsTippedToCaption,
            type: .stringArray(defaultValue: []),
            description: "List of clip IDs that were tipped to have captions"
        ),

        // Dates
        AppStorageVariableDefinition(
            key: Self.lastNotificationNotifiedAtV2,
            type: .date(defaultValue: nil),
            description: "Last notification timestamp (V2)"
        ),
        AppStorageVariableDefinition(
            key: Self.lastDiscoverUpdateAt,
            type: .date(defaultValue: nil),
            description: "Last discover content update timestamp"
        ),

        // Enums - Using manual string definitions to avoid module dependencies
        AppStorageVariableDefinition(
            key: Self.appearanceMode,
            type: .enumType(
                cases: ["light", "dark", "system"],
                defaultCase: "system",
                typeName: "AppearanceMode"
            ),
            description: "App appearance mode preference"
        ),
        AppStorageVariableDefinition(
            key: Self.lastCreateMode,
            type: .enumType(
                cases: ["text", "camera", "audio"],
                defaultCase: "text",
                typeName: "TabId"
            ),
            description: "Last used creation mode"
        ),
    ]
}

private extension String {
    func camelCaseToTitleCase() -> String {
        let result = self.reduce("") { result, character in
            if character.isUppercase && !result.isEmpty {
                return result + " " + String(character)
            } else if result.isEmpty {
                return String(character.uppercased())
            } else {
                return result + String(character)
            }
        }
        return result
    }
}
