import Foundation
import PokerCoach

/// Which of the products this build is.
///
/// One codebase, two apps per game: the tournament coach and the cash coach. Everything the two
/// differ in — the name on the screen, the bundle id, where the history lives, the keys the
/// settings are kept under, the subscription sold — is written down here once and read from
/// here, never from a bundle. The app shell chooses ONE of these before anything else runs; the
/// suite and the command line get the tournament one unless a test says otherwise.
public struct AppVariant: Sendable, Equatable {

    public enum Format: String, Sendable, CaseIterable {
        /// Blinds climb, nine players, three paid.
        case tournament
        /// Blinds stay put, a hundred big blinds to sit down with, cash out when you like.
        case cash
    }

    public let format: Format
    /// The name on Home and on the phone.
    public let displayName: String
    public let bundleID: String
    /// The Application Support folder the history lives in. Two apps, two folders, two histories.
    public let historyFolder: String
    /// Every UserDefaults key starts with this. On iOS each app has its own defaults anyway; on
    /// a Mac two apps that shared a prefix would share a tutorial-seen flag.
    public let defaultsPrefix: String
    /// The one product sold. Permanent once a build carrying it has been uploaded.
    public let storeProductID: String
    /// The key the free-hands tally lives under. The tournament app's is the unprefixed name it
    /// shipped with, so nobody's count resets.
    public let tallyKey: String
    /// The last part of this product's page on thedigitaladlab.com. The About link in Settings
    /// and the privacy link on the paywall are built from it, so the cash app points at its own
    /// pages rather than the tournament app's — Apple checks the privacy URL against the listing.
    public let webSlug: String

    public var pageURL: String { "https://www.thedigitaladlab.com/\(webSlug)" }
    public var privacyURL: String { "https://www.thedigitaladlab.com/\(webSlug)-privacy" }

    public init(format: Format, displayName: String, bundleID: String, historyFolder: String,
                defaultsPrefix: String, storeProductID: String, tallyKey: String, webSlug: String) {
        self.format = format
        self.displayName = displayName
        self.bundleID = bundleID
        self.historyFolder = historyFolder
        self.defaultsPrefix = defaultsPrefix
        self.storeProductID = storeProductID
        self.tallyKey = tallyKey
        self.webSlug = webSlug
    }

    /// The tournament coach. Every string here is the one the app shipped with on Ken's phone.
    public static let pokerTutor = AppVariant(
        format: .tournament,
        displayName: "Poker Tutor",
        bundleID: "com.thedigitaladlab.pokertutor",
        historyFolder: "PokerTutor",
        defaultsPrefix: "PokerTutor.",
        storeProductID: "com.thedigitaladlab.pokertutor.yearly",
        tallyKey: "trial.handsPlayed",
        webSlug: "poker-tutor"
    )

    /// The cash coach.
    public static let pokerTutorCash = AppVariant(
        format: .cash,
        displayName: "Poker Tutor Cash",
        bundleID: "com.thedigitaladlab.pokertutor.cash",
        historyFolder: "PokerTutorCash",
        defaultsPrefix: "PokerTutorCash.",
        storeProductID: "com.thedigitaladlab.pokertutor.cash.yearly",
        tallyKey: "PokerTutorCash.trial.handsPlayed",
        webSlug: "poker-tutor-cash"
    )

    /// The product this process is. Set once by the app shell, before the first screen or the
    /// first file read; left at the tournament product by the suite and the command line.
    nonisolated(unsafe) public static var current: AppVariant = .pokerTutor

    /// Makes this the product the process is, and tells the coach which game it is judging.
    ///
    /// Two settings, one call: the identity strings live here and the catalogue edition lives in
    /// `PokerCoach`, which cannot see this type, so they would drift apart if they were set
    /// separately. Every `TableSession` calls this with its own variant, so a session's world is
    /// always the one its variant describes; the suite resets it before every suite.
    public static func use(_ variant: AppVariant) {
        current = variant
        LeakCatalogue.format = variant.coachFormat
    }

    /// The same distinction as the coach draws it.
    public var coachFormat: CoachFormat { format == .cash ? .cash : .tournament }

    /// A settings key under this product's prefix.
    public func key(_ suffix: String) -> String { defaultsPrefix + suffix }

    public var isCash: Bool { format == .cash }
}
