import Foundation

// MARK: - Chat Models
struct ChatHistoryItem {
    let role: String
    let parts: [ChatPart]
}

struct ChatPart {
    let text: String
}

// MARK: - API Request Models
struct GeminiRequest: Codable {
    let contents: [GeminiContent]
    let generationConfig: GenerationConfig
}

struct GeminiContent: Codable {
    let role: String
    let parts: [GeminiPart]
}

struct GeminiPart: Codable {
    let text: String
}

struct GenerationConfig: Codable {
    let responseMimeType: String
    let temperature: Double
    let maxOutputTokens: Int
}

// MARK: - API Response Models
struct GeminiResponse: Codable {
    let candidates: [GeminiCandidate]?
}

struct GeminiCandidate: Codable {
    let content: GeminiContentResponse?
}

struct GeminiContentResponse: Codable {
    let parts: [GeminiPartResponse]?
}

struct GeminiPartResponse: Codable {
    let text: String?
}

// MARK: - Song Response Models
struct SongResponse: Codable {
    let reply: String
    let lyrics: LyricsStructure?
    let songs: [Song]
    let suggestions: [String]
}

struct LyricsStructure: Codable, Hashable {
    let sections: [LyricsSection]
}

struct LyricsSection: Codable, Hashable {
    let type: String
    let content: String
}

struct Song: Codable, Identifiable, Hashable {
    let id = UUID().uuidString
    let title: String
    let genres: [String]
    let artwork: String?
    let audioURL: String?
    
    // Custom coding keys to exclude id from JSON serialization
    private enum CodingKeys: String, CodingKey {
        case title, genres, artwork, audioURL
    }
    
    // Custom Hashable implementation
    func hash(into hasher: inout Hasher) {
        hasher.combine(title)
        hasher.combine(genres)
        hasher.combine(artwork)
        hasher.combine(audioURL)
    }
    
    static func == (lhs: Song, rhs: Song) -> Bool {
        return lhs.title == rhs.title &&
               lhs.genres == rhs.genres &&
               lhs.artwork == rhs.artwork &&
               lhs.audioURL == rhs.audioURL
    }
}

// MARK: - Streaming Response Model
struct StreamingData: Codable {
    let candidates: [StreamingCandidate]?
}

struct StreamingCandidate: Codable {
    let content: StreamingContent?
}

struct StreamingContent: Codable {
    let parts: [StreamingPart]?
}

struct StreamingPart: Codable {
    let text: String?
}