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?
}

// MARK: - Artist Model
struct Artist: Codable, Identifiable {
    let id: String
    let displayName: String
    let isArtist: Bool
    let bio: String?
    let tags: String?
    let avatarURL: String?
    let coverURL: String?
    
    private enum CodingKeys: String, CodingKey {
        case id
        case displayName
        case isArtist
        case bio
        case tags
        case avatarURL
        case coverURL
    }
}

// MARK: - Uploaded Song Model
struct UploadedSong: Identifiable, Hashable {
    let id: String
    let name: String
    let artistName: String
    let artistId: String
    let createdAt: Date
    let imageURL: String?
    let audioURL: String?
    let originalPrompt: String?
    let rewrittenPrompt: String?
    let status: String?

    // Remix information
    let rootRemixSongId: String?
    let hasBeenRemixed: Bool

    let isCreatedByCurrentUser: Bool
    let isLikedByCreator: Bool

    // Hooks playback start position (in seconds)
    let hooksStartPoint: Double?

    // Custom initializer with default values for remix fields
    init(
        id: String,
        name: String,
        artistName: String,
        artistId: String,
        createdAt: Date,
        imageURL: String? = nil,
        audioURL: String? = nil,
        originalPrompt: String? = nil,
        rewrittenPrompt: String? = nil,
        status: String? = nil,
        rootRemixSongId: String? = nil,
        hasBeenRemixed: Bool = false,
        isCreatedByCurrentUser: Bool = false,
        isLikedByCreator: Bool = false,
        hooksStartPoint: Double? = nil
    ) {
        self.id = id
        self.name = name
        self.artistName = artistName
        self.artistId = artistId
        self.createdAt = createdAt
        self.imageURL = imageURL
        self.audioURL = audioURL
        self.originalPrompt = originalPrompt
        self.rewrittenPrompt = rewrittenPrompt
        self.status = status
        self.rootRemixSongId = rootRemixSongId
        self.hasBeenRemixed = hasBeenRemixed
        self.isCreatedByCurrentUser = isCreatedByCurrentUser
        self.isLikedByCreator = isLikedByCreator
        self.hooksStartPoint = hooksStartPoint
    }

    var promptForDisplay: String {
        if let rewrittenPrompt, !rewrittenPrompt.isEmpty {
            return rewrittenPrompt
        } else if let originalPrompt, !originalPrompt.isEmpty {
            return originalPrompt
        } else {
            return ""
        }
    }

    var isRemix: Bool {
        return rootRemixSongId != nil
    }
}
