//
//  Event_v2.swift
//  Padel Tournament
//
//  Created by razmig on 10/03/2024.
//

import Foundation
import LeStorage
import SwiftUI

@Observable
class Event: ModelObject, Storable {
    
    static func resourceName() -> String { return "events" }
    static func tokenExemptedMethods() -> [HTTPMethod] { return [] }

    var id: String = Store.randomId()
    var creator: String?
    var club: String?
    var creationDate: Date = Date()
    var name: String?
    var tenupId: String?
    
    internal init(creator: String? = nil, club: String? = nil, name: String? = nil, tenupId: String? = nil) {
        self.creator = creator
        self.club = club
        self.name = name
        self.tenupId = tenupId
    }
    
    override func deleteDependencies() throws {
        DataStore.shared.tournaments.deleteDependencies(self.tournaments)
        DataStore.shared.dateIntervals.deleteDependencies(self.courtsUnavailability)
    }
    
    // MARK: - Computed dependencies
    
    var tournaments: [Tournament] {
        Store.main.filter { $0.event == self.id }
    }
    
    func clubObject() -> Club? {
        guard let club else { return nil }
        return Store.main.findById(club)
    }
    
    var courtsUnavailability: [DateInterval] {
        Store.main.filter(isIncluded: { $0.event == id })
    }
    
    // MARK: -
    
    func eventCourtCount() -> Int {
        tournaments.map { $0.courtCount }.max() ?? 2
    }

    func eventStartDate() -> Date {
        tournaments.map { $0.startDate }.min() ?? Date()
    }
    
    func eventDayDuration() -> Int {
        tournaments.map { $0.dayDuration }.max() ?? 1
    }

    func eventTitle() -> String {
        if let name, name.isEmpty == false {
            return name
        } else {
            return "Événement"
        }
    }

    func existingBuild(_ build: any TournamentBuildHolder) -> Tournament? {
        tournaments.first(where: { $0.isSameBuild(build) })
    }
    
    func tournamentsCourtsUsed(exluding tournamentId: String) -> [DateInterval] {
        tournaments.filter { $0.id != tournamentId }.flatMap({ tournament in
            tournament.getPlayedMatchDateIntervals(in: self)
        })
    }
    
    func insertOnServer() throws {
        try DataStore.shared.events.writeChangeAndInsertOnServer(instance: self)
        for tournament in self.tournaments {
            try tournament.insertOnServer()
        }
        for dataInterval in self.courtsUnavailability {
            try dataInterval.insertOnServer()
        }
    }
    
}


extension Event {
    enum CodingKeys: String, CodingKey {
        case _id = "id"
        case _creator = "creator"
        case _club = "club"
        case _creationDate = "creationDate"
        case _name = "name"
        case _tenupId = "tenupId"
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        
        try container.encode(id, forKey: ._id)
        
        if let creator = creator {
            try container.encode(creator, forKey: ._creator)
        } else {
            try container.encodeNil(forKey: ._creator)
        }
        
        if let club = club {
            try container.encode(club, forKey: ._club)
        } else {
            try container.encodeNil(forKey: ._club)
        }
        
        try container.encode(creationDate, forKey: ._creationDate)
        
        if let name = name {
            try container.encode(name, forKey: ._name)
        } else {
            try container.encodeNil(forKey: ._name)
        }
        
        if let tenupId = tenupId {
            try container.encode(tenupId, forKey: ._tenupId)
        } else {
            try container.encodeNil(forKey: ._tenupId)
        }
    }

}
