//
//  CourtAvailabilitySettingsView.swift
//  PadelClub
//
//  Created by Razmig Sarkissian on 19/04/2024.
//

import SwiftUI
import LeStorage

struct CourtAvailabilitySettingsView: View {
    @Environment(Tournament.self) var tournament: Tournament
    @EnvironmentObject var dataStore: DataStore
    
    let event: Event
    
    @State private var showingPopover: Bool = false
    @State private var editingSlot: DateInterval?
    
    var courtsUnavailability: [Int: [DateInterval]] {
        let groupedBy = Dictionary(grouping: event.courtsUnavailability, by: { dateInterval in
            return dateInterval.courtIndex
        })
        return groupedBy
    }
    
    var body: some View {
        List {
            let keys = courtsUnavailability.keys.sorted()
            ForEach(keys, id: \.self) { key in
                if let dates = courtsUnavailability[key] {
                    Section {
                        ForEach(dates.sorted(by: \.startDate)) { dateInterval in
                            Menu {
                                Button("dupliquer") {
                                    let duplicatedDateInterval = DateInterval(event: event.id, courtIndex: (dateInterval.courtIndex+1)%tournament.courtCount, startDate: dateInterval.startDate, endDate: dateInterval.endDate)
                                    do {
                                        try dataStore.dateIntervals.addOrUpdate(instance: duplicatedDateInterval)
                                    } catch {
                                        Logger.error(error)
                                    }
                                }
                                Button("éditer") {
                                    editingSlot = dateInterval
                                }
                                Button("effacer", role: .destructive) {
                                    do {
                                        try dataStore.dateIntervals.delete(instance: dateInterval)
                                    } catch {
                                        Logger.error(error)
                                    }
                                }
                            } label: {
                                HStack {
                                    VStack(alignment: .leading, spacing: 0) {
                                        Text(dateInterval.startDate.localizedTime()).font(.largeTitle)
                                        Text(dateInterval.startDate.localizedDay()).font(.caption)
                                    }
                                    Spacer()
                                    VStack {
                                        Image(systemName: "arrowshape.forward.fill")
                                            .tint(.master)
                                        Text("indisponible").foregroundStyle(.logoRed).font(.caption)
                                    }
                                    Spacer()
                                    VStack(alignment: .trailing, spacing: 0) {
                                        Text(dateInterval.endDate.localizedTime()).font(.largeTitle)
                                        Text(dateInterval.endDate.localizedDay()).font(.caption)
                                    }
                                }
                            }
                            .swipeActions {
                                Button(role: .destructive) {
                                    do {
                                        try dataStore.dateIntervals.delete(instance: dateInterval)
                                    } catch {
                                        Logger.error(error)
                                    }
                                } label: {
                                    LabelDelete()
                                }
                            }
                            .buttonStyle(.plain)
                        }
                    } header: {
                        HStack {
                            Text(Court.courtIndexedTitle(atIndex: key))
                            Spacer()
                            if let courtName = tournament.courtNameIfAvailable(atIndex: key) {
                                Text(courtName)
                            }
                        }
                    }
                    .headerProminence(.increased)
                }
            }
        }
        .overlay {
            if courtsUnavailability.isEmpty {
                ContentUnavailableView {
                    Label("Tous les terrains sont disponibles", systemImage: "checkmark.circle.fill").tint(.green)
                } description: {
                    Text("Vous pouvez précisez l'indisponibilité d'une ou plusieurs terrains, que ce soit pour une journée entière ou un créneau précis.")
                } actions: {
                    RowButtonView("Ajouter une indisponibilité", systemImage: "plus.circle.fill") {
                        showingPopover = true
                    }
                }
            }
        }
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                BarButtonView("Ajouter une indisponibilité", icon: "plus.circle.fill") {
                    showingPopover = true
                }
            }
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbarBackground(.visible, for: .navigationBar)
        .navigationTitle("Créneau indisponible")
        .sheet(isPresented: $showingPopover) {
            CourtAvailabilityEditorView(event: event)
        }
        .sheet(item: $editingSlot) { editingSlot in
            CourtAvailabilityEditorView(editingSlot: editingSlot, event: event)
        }
    }
}

struct CourtPicker: View {
    @Environment(Tournament.self) var tournament: Tournament

    let title: String
    @Binding var selection: Int
    let maxCourt: Int

    var body: some View {
        Picker(title, selection: $selection) {
            ForEach(0..<maxCourt, id: \.self) {
                Text(tournament.courtName(atIndex: $0))
            }
        }
    }
}

struct CourtAvailabilityEditorView: View {
    @Environment(Tournament.self) var tournament: Tournament
    @EnvironmentObject var dataStore: DataStore
    @Environment(\.dismiss) private var dismiss
    var editingSlot: DateInterval?
    let event: Event

    @State private var courtIndex: Int
    @State private var startDate: Date
    @State private var endDate: Date
    
    init(editingSlot: DateInterval, event: Event) {
        self.editingSlot = editingSlot
        self.event = event
        _courtIndex = .init(wrappedValue: editingSlot.courtIndex)
        _startDate = .init(wrappedValue: editingSlot.startDate)
        _endDate = .init(wrappedValue: editingSlot.endDate)
    }

    init(event: Event) {
        self.event = event
        _courtIndex = .init(wrappedValue: 0)
        let startDate = event.eventStartDate()
        _startDate = .init(wrappedValue: event.eventStartDate())
        _endDate = .init(wrappedValue: startDate.addingTimeInterval(5400))
    }

    var body: some View {
        NavigationStack {
            Form {
                Section {
                    CourtPicker(title: "Terrain", selection: $courtIndex, maxCourt: tournament.courtCount)
                }
                
                Section {
                    DatePicker("Début", selection: $startDate)
                        .onChange(of: startDate) {
                            if endDate < startDate {
                                endDate = startDate.addingTimeInterval(90*60)
                            }
                        }
                    DatePicker("Fin", selection: $endDate)
                        .onChange(of: endDate) {
                            if startDate > endDate {
                                startDate = endDate.addingTimeInterval(-90*60)
                            }

                        }
                } footer: {
                    FooterButtonView("jour entier") {
                        startDate = startDate.startOfDay
                        endDate = startDate.tomorrowAtNine.startOfDay
                    }
                }
                
                
                Section {
                    DateAdjusterView(date: $startDate)
                } header: {
                    Text("Modifier rapidement l'horaire de début")
                }
                Section {
                    DateAdjusterView(date: $endDate)
                } header: {
                    Text("Modifier rapidement l'horaire de fin")
                }
            }
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    ButtonValidateView {
                        if editingSlot == nil {
                            let dateInterval = DateInterval(event: event.id, courtIndex: courtIndex, startDate: startDate, endDate: endDate)
                            do {
                                try dataStore.dateIntervals.addOrUpdate(instance: dateInterval)
                            } catch {
                                Logger.error(error)
                            }
                        } else {
                            editingSlot?.courtIndex = courtIndex
                            editingSlot?.endDate = endDate
                            editingSlot?.startDate = startDate
                            do {
                                try dataStore.dateIntervals.addOrUpdate(instance: editingSlot!)
                            } catch {
                                Logger.error(error)
                            }
                        }
                        
                        dismiss()
                    }
                }
                
                ToolbarItem(placement: .topBarLeading) {
                    Button("Annuler", role: .cancel) {
                        dismiss()
                    }
                }
            }
            .navigationBarTitleDisplayMode(.inline)
            .toolbarBackground(.visible, for: .navigationBar)
            .navigationTitle(_navigationTitle())
            .tint(.master)
        }
    }
    
    private func _navigationTitle() -> String {
        editingSlot == nil ? "Nouveau créneau" : "Édition du créneau"
    }
}

struct DateAdjusterView: View {
    @Binding var date: Date
    
    var body: some View {
        HStack {
            _createButton(label: "-1h", timeOffset: -1, component: .hour)
            _createButton(label: "-30m", timeOffset: -30, component: .minute)
            _createButton(label: "+30m", timeOffset: 30, component: .minute)
            _createButton(label: "+1h", timeOffset: 1, component: .hour)
        }
        .font(.headline)
    }
    
    private func _createButton(label: String, timeOffset: Int, component: Calendar.Component) -> some View {
        Button(action: {
            date = Calendar.current.date(byAdding: component, value: timeOffset, to: date) ?? date
        }) {
            Text(label)
                .frame(maxWidth: .infinity) // Make buttons take equal space
        }
        .buttonStyle(.borderedProminent)
        .tint(.master)
    }
}
