import Foundation

/// Wire shape returned by `GET /m/contact-render` — must mirror the server-side
/// `RenderedContact` in `codebase/@features/api/src/features/contact-render/renderer.ts`.
struct RenderedContact: Codable, Sendable {
    let clientId: Int
    let handle: String
    let channel: String
    let firstName: String
    let lastNameEmojis: String
    let notesBlock: String
    let iCloudIdentifier: String?
    let renderedAt: String
}

struct RenderedContactList: Codable, Sendable {
    let items: [RenderedContact]
    /// Server-side flag flipped by the quinn.my UI's `[Backup]` button. When
    /// true, the poller runs a fresh full-store vCard dump before processing
    /// renders, then calls `/m/contact-render/backup-complete` to clear it.
    let backupRequested: Bool
}

/// Posted to `POST /m/contact-render/ack` after CNContactStore write succeeds.
/// `writeState` values match the Postgres CHECK constraint on
/// `contact_relationships.icloud_write_state`.
struct ContactRenderAckItem: Codable, Sendable {
    let clientId: Int
    let iCloudIdentifier: String
    let writeState: String  // 'pending' | 'linked'
}

struct ContactRenderAckBody: Codable, Sendable {
    let items: [ContactRenderAckItem]
}

/// Outcome of a single ContactsWriter.upsert — feeds both the ack payload and
/// the dry-run diff JSONL.
struct ContactUpsertResult: Codable, Sendable {
    enum Action: String, Codable, Sendable {
        case created
        case updated
        case dryRun = "dry_run"
    }

    let handle: String
    let clientId: Int
    let identifier: String
    let action: Action
    let before: ContactFieldTriple?
    let after: ContactFieldTriple

    var writeState: String {
        switch action {
        case .dryRun: return "pending"
        default: return "linked"
        }
    }
}

struct ContactFieldTriple: Codable, Sendable {
    let givenName: String
    let familyName: String
    let note: String
}
