//
//  TournamentCashierView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 17/04/2024.
//

import SwiftUI
import Combine

enum CashierDestination: Identifiable, Selectable, Equatable {
    
    static func == (lhs: CashierDestination, rhs: CashierDestination) -> Bool {
        return lhs.id == rhs.id
    }

    case summary
    case groupStage(GroupStage)
    case bracket(Round)
    case all(Tournament)
    
    var id: String { 
        switch self {
        case .summary:
            return String(describing: self)
        case .all(let tournament):
            return tournament.id
        case .groupStage(let groupStage):
            return groupStage.id
        case .bracket(let round):
            return round.id
        }
    }
    
    func selectionLabel() -> String {
        switch self {
        case .summary:
            return "Bilan"
        case .groupStage(let groupStage):
            return groupStage.selectionLabel()
        case .bracket(let round):
            return round.selectionLabel()
        case .all:
            return "Tous"
        }
    }
    
    func displayImageIfValueZero() -> Bool {
        return true
    }
    
    func badgeValue() -> Int? {
        switch self {
        case .summary:
            return nil
        case .groupStage(let groupStage):
            return groupStage.unsortedPlayers().filter({ $0.hasPaid() == false }).count
        case .bracket(let round):
            let playerRegistrations: [PlayerRegistration] = round.seeds().flatMap { $0.unsortedPlayers() }
            return playerRegistrations.filter({ $0.hasPaid() == false }).count
        case .all(_):
            return nil
        }
    }
    
    func badgeValueColor() -> Color? {
        return nil
    }
    
    func badgeImage() -> Badge? {
        switch self {
        case .summary:
            return nil
        case .all:
            return nil
        default:
            return .checkmark
        }
    }

}

struct TournamentCashierView: View {
    var tournament: Tournament
    @State private var selectedDestination: CashierDestination?
    @StateObject private var cashierViewModel: CashierViewModel = CashierViewModel()
    var allDestinations: [CashierDestination]

    init(tournament: Tournament) {
        self.tournament = tournament
        
        var allDestinations : [CashierDestination] = []
        let tournamentHasEnded = tournament.hasEnded()
        if tournamentHasEnded {
            allDestinations.append(.summary)
        }

        let all = CashierDestination.all(tournament)
        allDestinations.append(all)

        let destinations: [CashierDestination] = tournament.groupStages().map { CashierDestination.groupStage($0) }
        allDestinations.append(contentsOf: destinations)
        tournament.rounds().forEach { round in
            if round.seeds().isEmpty == false {
                allDestinations.append(CashierDestination.bracket(round))
            }
        }
        
        if tournamentHasEnded == false {
            allDestinations.append(.summary)
        }

        self.allDestinations = allDestinations

        
        if tournament.hasEnded() {
            if tournament.players().anySatisfy({ $0.hasPaid() == false }) == false {
                _selectedDestination = .init(wrappedValue: .summary)
            } else {
                _selectedDestination = .init(wrappedValue: all)
            }
        } else {
            let gs = tournament.getActiveGroupStage()
            if let gs, let destination = allDestinations.first(where: { $0.id == gs.id }) {
                _selectedDestination = State(wrappedValue: destination)
            } else if let rs = tournament.getActiveRound(withSeeds: true), let destination = allDestinations.first(where: { $0.id == rs.id }) {
                _selectedDestination = State(wrappedValue: destination)
            }
        }
    }
    
    var body: some View {
        VStack(spacing: 0) {
            GenericDestinationPickerView(selectedDestination: $selectedDestination, destinations: allDestinations, nilDestinationIsValid: true)
            switch selectedDestination {
            case .none:
                CashierSettingsView(tournament: tournament)
            case .some(let selectedCall):
                switch selectedCall {
                case .summary:
                    CashierDetailView(tournament: tournament).id(selectedCall.id)
                case .groupStage(let groupStage):
                    CashierView(tournament: tournament, teams: groupStage.teams()).id(selectedCall.id)
                        .searchable(text: $cashierViewModel.searchText, isPresented: $cashierViewModel.isSearching, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Chercher un joueur"))
                case .bracket(let round):
                    CashierView(tournament: tournament, teams: round.seeds()).id(selectedCall.id)
                        .searchable(text: $cashierViewModel.searchText, isPresented: $cashierViewModel.isSearching, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Chercher un joueur"))
                case .all(let tournament):
                    CashierView(tournament: tournament, teams: tournament.selectedSortedTeams()).id(selectedCall.id)
                        .searchable(text: $cashierViewModel.searchText, isPresented: $cashierViewModel.isSearching, placement: .navigationBarDrawer(displayMode: .always), prompt: Text("Chercher un joueur"))
                }
            }
        }
        .environment(tournament)
        .environmentObject(cashierViewModel)
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
        .navigationTitle("Encaissement")
    }
}

//#Preview {
//    TournamentCashierView(tournament: Tournament.mock())
//}

//class DebouncedObject: ObservableObject {
//    @Published var searchText: String = "" {
//        didSet {
//            debounceSearchTextPublisher.send(searchText)
//        }
//    }
//
//    private var debounceSearchTextPublisher = PassthroughSubject<String, Never>()
//    private var cancellables = Set<AnyCancellable>()
//
//    init() {
//        debounceSearchTextPublisher
//            .debounce(for: .milliseconds(300), scheduler: RunLoop.main)
//            .sink { [weak self] in self?.performSearch(with: $0) }
//            .store(in: &cancellables)
//    }
//
//    private func performSearch(with text: String) {
//        // Perform the search with the debounced text
//        print("Performing search with text: \(text)")
//    }
//}
