//
//  SchedulerView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 07/04/2024.
//

import SwiftUI
import LeStorage

extension GroupStage: Schedulable {
    func titleLabel() -> String {
        self.groupStageTitle()
    }
}
extension Round: Schedulable {
    func titleLabel() -> String {
        self.roundTitle()
    }
}

struct SchedulerView: View {
    @EnvironmentObject var dataStore: DataStore
    var tournament: Tournament
    var destination: ScheduleDestination

    var body: some View {
        @Bindable var tournament = tournament
        
        List {
            switch destination {
            case .scheduleGroupStage:
                Section {
                    MatchFormatPickingView(matchFormat: $tournament.groupStageMatchFormat) {
                        Task {
                            tournament.matchScheduler()?.updateSchedule(tournament: tournament)
                        }
                    }
                    .onChange(of: tournament.groupStageMatchFormat) {
                        let groupStages = tournament.groupStages()
                        groupStages.forEach { groupStage in
                            groupStage.updateMatchFormat(tournament.groupStageMatchFormat)
                        }
                        do {
                            try dataStore.tournaments.addOrUpdate(instance: tournament)
                            try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
                        } catch {
                            Logger.error(error)
                        }
                        
                    }
                } footer: {
                    if tournament.groupStageMatchFormat.weight > tournament.groupStageSmartMatchFormat().weight {
                        Button {
                            tournament.groupStageMatchFormat = tournament.groupStageSmartMatchFormat()
                        } label: {
                            Text("devrait être joué au moins en " + tournament.groupStageSmartMatchFormat().format + ", ") + Text("modifier ?").underline().foregroundStyle(.master)
                        }
                        .buttonStyle(.plain)
                    }
                }

                ForEach(tournament.groupStages()) {
                    GroupStageScheduleEditorView(groupStage: $0, tournament: tournament)
                        .id(UUID())
                }
            case .scheduleBracket:
                ForEach(tournament.rounds()) { round in
                    _roundView(round)
                }
            default:
                EmptyView()
            }
        }
        .headerProminence(.increased)
        .monospacedDigit()
        .onChange(of: tournament.groupStageMatchFormat) {
            let groupStages = tournament.groupStages()
            tournament.groupStages().forEach { groupStage in
                groupStage.updateMatchFormat(tournament.groupStageMatchFormat)
            }
            
            do {
                try dataStore.tournaments.addOrUpdate(instance: tournament)
                try dataStore.groupStages.addOrUpdate(contentOfs: groupStages)
            } catch {
                Logger.error(error)
            }
        }
    }
    
    @ViewBuilder
    func _roundView(_ round: Round) -> some View {
        Section {
            NavigationLink {
                RoundScheduleEditorView(round: round, tournament: tournament)
                    .navigationTitle(round.titleLabel())
                    .environment(tournament)
            } label: {
                LabeledContent {
                    Text(round.matchFormat.format)//.font(.title2)
                } label: {
                    if let startDate = round.getStartDate() {
                        HStack {
                            Text(startDate.formattedAsHourMinute()).font(.title2).fontWeight(.semibold)
                            if let estimatedEndDate = round.estimatedEndDate(tournament.additionalEstimationDuration) {
                                Image(systemName: "arrowshape.forward.fill")
                                Text(estimatedEndDate.formattedAsHourMinute()).font(.title2).fontWeight(.semibold)
                            }
                        }
                        Text(startDate.formattedAsDate())
                    } else {
                        Text("Aucun horaire")
                    }
                }
            }
        } header: {
            Text(round.titleLabel())
        } footer: {
            let federalFormat = tournament.roundSmartMatchFormat(round.index)
            if round.matchFormat.weight > federalFormat.weight {
                Button {
                    round.updateMatchFormatAndAllMatches(federalFormat)
                    do {
                        try dataStore.rounds.addOrUpdate(instance: round)
                    } catch {
                        Logger.error(error)
                    }
                } label: {
                    Text("devrait être joué au moins en " + federalFormat.format + ", ") + Text("modifier ?").underline().foregroundStyle(.master)
                }
                .buttonStyle(.plain)
            }
        }
        
        if round.index != 0 {
            Section {
                NavigationLink {
                    LoserRoundScheduleEditorView(upperRound: round, tournament: tournament)
                        .environment(tournament)
                } label: {
                    LabeledContent {
                        let count = round.loserRounds().filter({ $0.isDisabled() == false }).count
                        Text(count.formatted() + " tour" + count.pluralSuffix)
                    } label: {
                        if let startDate = round.getLoserRoundStartDate() {
                            HStack {
                                Text(startDate.formattedAsHourMinute()).font(.title3)
                                if let estimatedEndDate = round.estimatedLoserRoundEndDate(tournament.additionalEstimationDuration) {
                                    Image(systemName: "arrowshape.forward.fill")
                                    Text(estimatedEndDate.formattedAsHourMinute()).font(.title3)
                                }
                            }
                            Text(startDate.formattedAsDate())
                        } else {
                            Text("Aucun horaire")
                        }
                    }
                }
            } header: {
                Text("Match de classement \(round.roundTitle(.short))")
            } footer: {
                if round.index == 1, let semi = round.loserRounds().first {
                    let federalFormat = tournament.loserBracketSmartMatchFormat(1)
                    if semi.matchFormat.weight > federalFormat.weight {
                        Button {
                            round.updateMatchFormatAndAllMatches(federalFormat)
                            do {
                                try dataStore.rounds.addOrUpdate(instance: round)
                            } catch {
                                Logger.error(error)
                            }
                        } label: {
                            Text("devrait être joué au moins en " + federalFormat.format + ", ") + Text("modifier ?").underline().foregroundStyle(.master)
                        }
                        .buttonStyle(.plain)
                    }
                }
            }
        }
    }
}

//#Preview {
//    SchedulerView(tournament: Tournament.mock(), destination: .scheduleBracket)
//}
