//
//  LoserRoundsView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 04/04/2024.
//

import SwiftUI

class UpperRound: Identifiable, Selectable {
    var id: String { round.id }
    let round: Round
    var loserRounds: [LoserRound] {
        LoserRound.updateDestinations(fromLoserRounds: round.loserRounds(), inUpperBracketRound: round)
    }
    let title: String
    let playedMatches: [Match]

    init(round: Round) {
        self.round = round
        self.title = round.roundTitle(.short)
        self.playedMatches = round.playedMatches()
    }
    
    func loserMatches() -> [Match] {
        loserRounds.flatMap({ $0.allMatches }).filter({ $0.disabled == false })
    }
    
    func status() -> (Int, Int) {
        let loserMatches = loserMatches()
        return (loserMatches.filter { $0.hasEnded() }.count, loserMatches.count)
    }
}

extension UpperRound: Equatable {
    static func == (lhs: UpperRound, rhs: UpperRound) -> Bool {
        lhs.id == rhs.id
    }
    
    func selectionLabel(index: Int) -> String {
        return title
    }
    
    func badgeValue() -> Int? {
#if _DEBUG_TIME //DEBUGING TIME
        let start = Date()
        defer {
            let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
            print("func badgeValue round of: ", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
        }
#endif
        return playedMatches.filter({ $0.isRunning() }).count
    }
    
    func badgeValueColor() -> Color? {
        return nil
    }
    
    func badgeImage() -> Badge? {
#if _DEBUG_TIME //DEBUGING TIME
        let start = Date()
        defer {
            let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
            print("func badgeImage of round: ", id, duration.formatted(.units(allowed: [.seconds, .milliseconds])))
        }
#endif
        return playedMatches.allSatisfy({ $0.hasEnded() }) ? .checkmark : nil
    }
}


struct LoserRound: Identifiable, Selectable {
    let turnIndex: Int
    let rounds: [Round]
    let allMatches: [Match]
    
    init(turnIndex: Int, rounds: [Round]) {
        self.turnIndex = turnIndex
        self.rounds = rounds
        self.allMatches = rounds.flatMap { $0.playedMatches() }
    }
    
    var id: Int {
        return turnIndex
    }
    
    var shouldBeDisplayed: Bool {
#if _DEBUG_TIME //DEBUGING TIME
        let start = Date()
        defer {
            let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
            print("func shouldBeDisplayed loserRound", duration.formatted(.units(allowed: [.seconds, .milliseconds])))
        }
#endif
        
        return allMatches.first(where: { $0.disabled == false }) != nil
    }

    static func updateDestinations(fromLoserRounds loserRounds: [Round], inUpperBracketRound upperBracketRound: Round) -> [LoserRound] {
#if _DEBUG_TIME //DEBUGING TIME
        let start = Date()
        defer {
            let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
            print("func updateDestinations(fromLoserRounds", duration.formatted(.units(allowed: [.seconds, .milliseconds])))
        }
#endif        
        var rounds = [LoserRound]()
        let allLoserRounds = upperBracketRound.loserRoundsAndChildren()
        for (index, round) in loserRounds.enumerated() {
            rounds.append(LoserRound(turnIndex: index, rounds: upperBracketRound.loserRounds(forRoundIndex: round.index, loserRoundsAndChildren: allLoserRounds)))
        }
        
        return rounds
    }
    
    static func enabledLoserRounds(inLoserRounds loserRounds: [Round], inUpperBracketRound upperBracketRound: Round) -> [Round] {
        let allLoserRounds = upperBracketRound.loserRoundsAndChildren()
        return loserRounds.filter { loserRound in
            upperBracketRound.loserRounds(forRoundIndex: loserRound.index, loserRoundsAndChildren: allLoserRounds).anySatisfy({ $0.isDisabled() == false })
        }
    }

    
}

extension LoserRound: Equatable {
    static func == (lhs: LoserRound, rhs: LoserRound) -> Bool {
        lhs.id == rhs.id
    }
    
    
    func selectionLabel(index: Int) -> String {
        if index < turnIndex {
            return "Tour #\(index + 1)"
        }
        return "Tour #\(turnIndex + 1)"
    }
    
    func badgeValue() -> Int? {
        let runningMatches: [Match] = allMatches.filter { $0.disabled == false && $0.isRunning() }
        return runningMatches.count
    }
    
    func badgeValueColor() -> Color? {
        return nil
    }
    
    func badgeImage() -> Badge? {
#if _DEBUG_TIME //DEBUGING TIME
        let start = Date()
        defer {
            let duration = Duration.milliseconds(Date().timeIntervalSince(start) * 1_000)
            print("func badgeImage loserRound", duration.formatted(.units(allowed: [.seconds, .milliseconds])))
        }
#endif

        return allMatches.filter { $0.disabled == false }.allSatisfy({ $0.hasEnded() }) ? .checkmark : nil
    }
}


struct LoserRoundsView: View {
    var upperBracketRound: UpperRound
    @State private var selectedRound: LoserRound?
    @State private var isEditingTournamentSeed = false

    init(upperBracketRound: UpperRound) {
        self.upperBracketRound = upperBracketRound
        _selectedRound = State(wrappedValue: upperBracketRound.loserRounds.first(where: { $0.rounds.anySatisfy({ $0.getActiveLoserRound() != nil }) }) ?? upperBracketRound.loserRounds.first(where: { $0.shouldBeDisplayed }))
        
        if upperBracketRound.loserRounds.allSatisfy({ $0.shouldBeDisplayed == false }) {
            _isEditingTournamentSeed = .init(wrappedValue: true)
        }
    }
    
    var destinations: [LoserRound] {
        isEditingTournamentSeed ? upperBracketRound.loserRounds : upperBracketRound.loserRounds.filter({ $0.shouldBeDisplayed })
    }

    var body: some View {
        VStack(spacing: 0) {
            GenericDestinationPickerView(selectedDestination: $selectedRound, destinations: destinations, nilDestinationIsValid: true)
            switch selectedRound {
            case .some(let selectedRound):
                LoserRoundView(loserBracket: selectedRound)
            default:
                LoserRoundSettingsView(upperBracketRound: upperBracketRound)
            }
        }
        .environment(\.isEditingTournamentSeed, $isEditingTournamentSeed)
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
    }
}
