import Foundation

struct EventV2Choice: Codable, Equatable {
    let choiceId: String
    let text: String
    let energyCost: Int?
    let moneyCost: Int?
    let diamondCost: Int?
}

struct EventV2Effects: Codable, Equatable {
    let stats: [String: Double]?
    let resources: EventV2Resources?
}

struct EventV2Resources: Codable, Equatable {
    let energy: Double?
    let money: Double?
    let diamonds: Double?
}

/// An affinity change applied to a named NPC during event resolution, used to
/// show e.g. "Mom +5 affinity" on the decision-confirmation screen.
struct EventV2RelationshipChange: Codable, Equatable {
    let personId: String
    let name: String
    let affinityDelta: Double
}

struct EventV2Metadata: Codable, Equatable {
    let category: String?
    let status: String?
    let kind: String?
    let choiceId: String?
}

struct EventV2PromptEnvelope: Codable, Equatable {
    let type: String
    let eventId: String
    let instanceId: String
    let prompt: String
    let choices: [EventV2Choice]
    let metadata: EventV2Metadata?
}

struct EventV2ResolvedEnvelope: Codable, Equatable {
    let type: String
    let eventId: String
    let instanceId: String
    let resolutionText: String
    let effects: EventV2Effects?
    /// Affinity changes attributed to named NPCs (e.g. "Mom +5 affinity").
    let resolvedRelationships: [EventV2RelationshipChange]?
    let metadata: EventV2Metadata?
}

struct EventV2ErrorEnvelope: Codable, Equatable {
    let type: String
    let code: String
    let message: String
    let eventId: String?
    let instanceId: String?
}

enum EventV2Envelope: Codable, Equatable {
    case prompt(EventV2PromptEnvelope)
    case resolved(EventV2ResolvedEnvelope)
    case error(EventV2ErrorEnvelope)

    enum CodingKeys: String, CodingKey {
        case type
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let type = try container.decode(String.self, forKey: .type)

        switch type {
        case "event_prompt":
            self = .prompt(try EventV2PromptEnvelope(from: decoder))
        case "event_resolved":
            self = .resolved(try EventV2ResolvedEnvelope(from: decoder))
        case "event_error":
            self = .error(try EventV2ErrorEnvelope(from: decoder))
        default:
            throw DecodingError.dataCorruptedError(
                forKey: .type,
                in: container,
                debugDescription: "Unsupported v2 event type: \(type)"
            )
        }
    }

    func encode(to encoder: Encoder) throws {
        switch self {
        case .prompt(let value):
            try value.encode(to: encoder)
        case .resolved(let value):
            try value.encode(to: encoder)
        case .error(let value):
            try value.encode(to: encoder)
        }
    }
}
