//
//  CalendarView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 01/03/2024.
//

import SwiftUI
import LeStorage

struct CalendarView: View {
    @EnvironmentObject var dataStore: DataStore
    @Environment(NavigationViewModel.self) var navigation: NavigationViewModel
    @Environment(FederalDataViewModel.self) var federalDataViewModel: FederalDataViewModel
    let date: Date
    let tournaments: [FederalTournamentHolder]
    let daysOfWeek = Date.capitalizedFirstLettersOfWeekdays
    let columns = Array(repeating: GridItem(.flexible()), count: 7)
    let color = Color.master

    @State private var days: [Date] = []
    @State private var counts = [Int : Int]()
    @State private var newTournament: Tournament?
    
    @ViewBuilder
    var body: some View {
        VStack {
            HStack {
                ForEach(daysOfWeek.indices, id: \.self) { index in
                Text(daysOfWeek[index])
                        .fontWeight(.black)
                        .foregroundStyle(color)
                        .frame(maxWidth: .infinity)
                }
            }
            LazyVGrid(columns: columns) {
                ForEach(days, id: \.self) { day in
                    _dayView(day)
                }
            }
        }
        .sheet(item: $newTournament) { tournament in
            EventCreationView(startingDate: tournament.startDate, tournaments: [tournament], selectedClub: federalDataViewModel.selectedClub())
                .environment(navigation)
                .tint(.master)
        }
        .onAppear {
            days = date.calendarDisplayDays
            setupCounts()
        }
        .onChange(of: date) {
            days = date.calendarDisplayDays
            setupCounts()
        }
    }
    
    @ViewBuilder
    private func _dayView(_ day: Date) -> some View {
        if day.monthInt != date.monthInt {
            Text("")
        } else {
            Menu {
                Button("Créer un tournoi") {
                    let tournament = Tournament.newEmptyInstance()
                    tournament.startDate = day.atNine()
                    if federalDataViewModel.categories.isEmpty == false {
                        tournament.tournamentCategory = federalDataViewModel.categories.first!
                    }
                    if federalDataViewModel.levels.isEmpty == false {
                        tournament.tournamentLevel = federalDataViewModel.levels.first!
                    }
                    if federalDataViewModel.ageCategories.isEmpty == false {
                        tournament.federalTournamentAge = federalDataViewModel.ageCategories.first!
                    }
                    newTournament = tournament
                }
                
                Divider()

                let tournamentsByDay = tournaments.filter { day.dayInt >= $0.startDate.dayInt && day.dayInt < $0.startDate.dayInt + $0.dayDuration }
                ForEach(tournamentsByDay, id: \.holderId) { tournamentHolder in
                    if let tournament = tournamentHolder as? Tournament {
                        Section {
                            Button(tournament.tournamentTitle(.short)) {
                                navigation.path.append(tournament)
                            }
                        } header: {
                            Text("sur " + tournament.dayDuration.formatted() + " jour" + tournament.dayDuration.pluralSuffix)
                        }
                    } else if let tournament = tournamentHolder as? FederalTournament {
                        Menu {
                            ForEach(tournament.tournaments, id: \.id) { build in
                                if federalDataViewModel.isFederalTournamentValidForFilters(tournament, build: build) {
                                    Button(build.buildHolderTitle()) {
                                        _createOrShow(federalTournament: tournament, existingTournament: event(forTournament: tournament)?.existingBuild(build), build: build)
                                    }
                                }
                            }
                        } label: {
                            Text(tournament.clubLabel())
                            Text("sur " + tournament.dayDuration.formatted() + " jour" + tournament.dayDuration.pluralSuffix)
                        }
                    }
                }
            } label: {
                Text(day.formatted(.dateTime.day()))
                    .fontWeight(.bold)
                    .foregroundStyle((counts[day.dayInt] != nil ? Color.white : Color.black))
                    .frame(maxWidth: .infinity, minHeight: 40)
                    .background(
                        Circle()
                            .foregroundStyle(
                                Date.now.startOfDay == day.startOfDay
                                ? (counts[day.dayInt] != nil ? Color.logoRed : Color.green)
                                :  (counts[day.dayInt] != nil ? Color.master : Color.beige)
                            )
                    )
                    .overlay(alignment: .bottomTrailing) {
                        if let count = counts[day.dayInt] {
                            Image(systemName: count <= 50 ? "\(count).circle.fill" : "plus.circle.fill")
                                .foregroundColor(.secondary)
                                .imageScale(.medium)
                                .background (
                                    Color(.systemBackground)
                                        .clipShape(.circle)
                                )
                                .offset(x: 5, y: 5)
                        }
                    }
            }
            .buttonStyle(.plain)
        }

    }
    
    func setupCounts() {
        let filteredTournaments = tournaments
        let mappedItems = filteredTournaments.flatMap { tournamentHolder in
            (0..<tournamentHolder.dayDuration).map({ dayDuration in
                (tournamentHolder.startDate.dayInt + dayDuration, tournamentHolder.tournaments.count)
            })
        }
        counts = Dictionary(mappedItems, uniquingKeysWith: +)
    }
    
    func event(forTournament tournament: FederalTournamentHolder) -> Event? {
        guard let federalTournament = tournament as? FederalTournament else { return nil }
        return dataStore.events.first(where: { $0.tenupId == federalTournament.id.string })
    }
    
    private func _createOrShow(federalTournament: FederalTournament, existingTournament: Tournament?, build: any TournamentBuildHolder) {
        if let existingTournament {
            navigation.agendaDestination = .activity
            navigation.path.append(existingTournament)
        } else {
            let event = federalTournament.getEvent()
            let newTournament = Tournament.newEmptyInstance()
            newTournament.event = event.id
            //todo
            //newTournament.umpireMail()
            //newTournament.jsonData = jsonData
            newTournament.tournamentLevel = build.level
            newTournament.tournamentCategory = build.category
            newTournament.federalTournamentAge = build.age
            newTournament.dayDuration = federalTournament.dayDuration
            newTournament.startDate = federalTournament.startDate.atBeginningOfDay(hourInt: 9)
            newTournament.setupFederalSettings()
            do {
                try dataStore.tournaments.addOrUpdate(instance: newTournament)
            } catch {
                Logger.error(error)
            }
            navigation.path.append(newTournament)
        }
    }

}

//#Preview {
//    CalendarView(date: .now, tournaments: [])
//}
