import Foundation

/// Mirrors the `user` object returned by `GET /api/auth/session` and
/// `POST /api/auth/login` (src/app/api/auth/session/route.ts). Field names
/// are already camelCase in the JSON, so no custom `CodingKeys`/key-decoding
/// strategy is needed anywhere in this file.
///
/// Date fields are kept as raw ISO-8601 strings (with fractional seconds,
/// e.g. `2026-08-20T19:37:42.307Z` from `Date.toISOString()`) rather than
/// `Date`, because `JSONDecoder`'s built-in `.iso8601` strategy does NOT
/// parse fractional seconds and would silently fail to decode every
/// timestamp this backend sends. Use `ISO8601.parse(_:)` (Support/ISO8601.swift)
/// where you actually need a `Date`.
struct User: Decodable, Identifiable, Equatable {
    let id: String
    let email: String?
    let name: String?
    let plan: String
    let isGuest: Bool
    let isPro: Bool
    let cancelAtPeriodEnd: Bool
    let emailVerified: Bool
    let launchBonus: Bool
    let freeScanAllowance: Int
    let scanCount: Int
    let company: String?
    let useCase: String?
    let expiresAt: String?
    let createdAt: String?
    let onboardingCompletedAt: String?

    /// True once onboarding (company/use-case/etc.) has been completed — the
    /// dashboard's post-signup wizard on web, skippable but tracked the same
    /// way in the app.
    var hasCompletedOnboarding: Bool { onboardingCompletedAt != nil }

    /// Reconstructs the UUID `newId("usr")` originally minted this account's
    /// `id` from (see `src/lib/auth/tokens.ts` on the backend: `"usr_" +
    /// randomUUID().replace(/-/g, "")` — i.e. `id` IS a UUID with its dashes
    /// stripped and a prefix glued on, nothing more). Re-inserting the
    /// dashes recovers that exact UUID losslessly — no extra network call,
    /// no server-issued token to fetch and cache.
    ///
    /// Passed as StoreKit's `appAccountToken` on purchase (see
    /// `StoreKitPurchaseService.purchase`) so `POST /api/webhooks/apple`
    /// (`src/lib/billing/appleIAP.ts` → `userIdFromAppAccountToken`) can
    /// reverse the same transformation server-side and know which account a
    /// given App Store transaction belongs to — that's the ONLY thing this
    /// value is for; it carries no other meaning to Apple.
    var appleAccountToken: UUID? {
        guard id.hasPrefix("usr_") else { return nil }
        let hex = String(id.dropFirst(4))
        guard hex.count == 32, hex.allSatisfy(\.isHexDigit) else { return nil }
        let parts = [
            hex.prefix(8),
            hex.dropFirst(8).prefix(4),
            hex.dropFirst(12).prefix(4),
            hex.dropFirst(16).prefix(4),
            hex.dropFirst(20),
        ]
        return UUID(uuidString: parts.joined(separator: "-"))
    }
}

/// The minimal user echo returned inline by `POST /api/auth/login` and
/// `/signup` (a subset of `User` — those endpoints don't run the extra
/// queries `/api/auth/session` does). Kept separate so a login response
/// decodes without requiring fields it doesn't send.
struct LoginResponse: Decodable {
    let status: String
    let user: LoginUser
    /// Present only when the request carried `X-Client: ios` — see
    /// src/app/api/auth/login/route.ts. Absent for a browser-style caller.
    let token: String?
    let expiresAt: String?
}

struct LoginUser: Decodable {
    let id: String
    let email: String?
    let name: String?
    let plan: String
    let onboardingCompletedAt: String?
}

struct SessionResponse: Decodable {
    let user: User?
}
