//
//  DetailView.swift
//  TigerDine
//
//  Created by Campbell on 9/1/25.
//

import SwiftUI
import SafariServices

struct DetailView: View {
    @State var locationId: Int
    
    @Environment(DiningModel.self) var model
    @Environment(\.openURL) private var openURL
    
    @State private var showingSafari: Bool = false
    @State private var occupancyLoading: Bool = true
    @State private var occupancyPercentage: Double = 0.0

    // This gets the location that we're meant to be displaying details about using the provided ID.
    private var location: DiningLocation {
        return model.locationsByDay[0].first { $0.id == locationId }!
    }
    
    // This creates a list of the time strings for the current day and following 6 days to display in the "Upcoming Hours" section.
    // I realized that it makes a lot more sense to do today + 6 rather than just the current calendar week's hours, because who
    // cares what Tuesday's hours were on Saturday, you want to know what Sunday's hours will be.
    private var weeklyHours: [WeeklyHours] {
        var newWeeklyHours: [WeeklyHours] = []
        for day in model.locationsByDay {
            for location in day {
                if location.id == locationId {
                    let weekdayFormatter = DateFormatter()
                    weekdayFormatter.dateFormat = "EEEE"
                    if let times = location.diningTimes, !times.isEmpty {
                        var timeStrings: [String] = []
                        for time in times {
                            timeStrings.append("\(dateDisplay.string(from: time.openTime)) - \(dateDisplay.string(from: time.closeTime))")
                        }
                        newWeeklyHours.append(
                            WeeklyHours(
                                day: weekdayFormatter.string(from: location.date),
                                date: location.date,
                                timeStrings: timeStrings
                            ))
                    } else {
                        newWeeklyHours.append(
                            WeeklyHours(
                                day: weekdayFormatter.string(from: location.date),
                                date: location.date,
                                timeStrings: ["Closed"]
                            ))
                    }
                }
            }
        }
        return newWeeklyHours
    }
    
    // Still a little broken, does not work for refresh. Need to fix.
    private func getOccupancy() async {
        // Only fetch occupancy data if the location is actually open right now. Otherwise, just exit early and hide the spinner.
        if location.open == .open || location.open == .closingSoon {
            occupancyLoading = true
            switch await getOccupancyPercentage(mdoId: location.mdoId) {
            case .success(let occupancy):
                occupancyPercentage = occupancy
                occupancyLoading = false
            case .failure(let error):
                print(error)
                occupancyLoading = false
            }
        } else {
            occupancyLoading = false
        }
    }
    
    var body: some View {
        ScrollView {
            VStack(alignment: .leading) {
                VStack(alignment: .leading) {
                    Text(location.name)
                        .font(.title)
                        .fontWeight(.bold)
                    Text(location.summary)
                        .font(.title2)
                        .fontWeight(.semibold)
                        .foregroundStyle(.secondary)
                    VStack(alignment: .leading) {
                        switch location.open {
                        case .open:
                            Text("Open")
                                .font(.title3)
                                .foregroundStyle(.green)
                        case .closed:
                            Text("Closed")
                                .font(.title3)
                                .foregroundStyle(.red)
                        case .openingSoon:
                            Text("Opening Soon")
                                .font(.title3)
                                .foregroundStyle(.orange)
                        case .closingSoon:
                            Text("Closing Soon")
                                .font(.title3)
                                .foregroundStyle(.orange)
                        }
                        if let times = location.diningTimes, !times.isEmpty {
                            ForEach(times, id: \.self) { time in
                                Text("\(dateDisplay.string(from: time.openTime)) - \(dateDisplay.string(from: time.closeTime))")
                                    .foregroundStyle(.secondary)
                            }
                        } else {
                            Text("Not Open Today")
                                .foregroundStyle(.secondary)
                        }
                    }
                    #if DEBUG
                    HStack(spacing: 0) {
                        ForEach(Range(1...5), id: \.self) { index in
                            if occupancyPercentage > (20 * Double(index)) {
                                Image(systemName: "person.fill")
                            } else {
                                Image(systemName: "person")
                            }
                        }
                        ProgressView()
                            .progressViewStyle(.circular)
                            .frame(width: 18, height: 18)
                            .opacity(occupancyLoading ? 1 : 0)
                            .task {
                                await getOccupancy()
                            }
                    }
                    .foregroundStyle(Color.accent.opacity(occupancyLoading ? 0.5 : 1.0))
                    .font(.title3)
                    #endif
                }
                .padding(.bottom, 16)
                if let visitingChefs = location.visitingChefs, !visitingChefs.isEmpty {
                    VStack(alignment: .leading) {
                        Text("Today's Visiting Chefs")
                            .font(.title3)
                            .fontWeight(.semibold)
                        ForEach(visitingChefs, id: \.self) { chef in
                            HStack(alignment: .top) {
                                Text(chef.name)
                                Spacer()
                                VStack(alignment: .trailing) {
                                    switch chef.status {
                                    case .hereNow:
                                        Text("Here Now")
                                            .foregroundStyle(.green)
                                    case .gone:
                                        Text("Left For Today")
                                            .foregroundStyle(.red)
                                    case .arrivingLater:
                                        Text("Arriving Later")
                                            .foregroundStyle(.red)
                                    case .arrivingSoon:
                                        Text("Arriving Soon")
                                            .foregroundStyle(.orange)
                                    case .leavingSoon:
                                        Text("Leaving Soon")
                                            .foregroundStyle(.orange)
                                    }
                                    Text("\(dateDisplay.string(from: chef.openTime)) - \(dateDisplay.string(from: chef.closeTime))")
                                        .foregroundStyle(.secondary)
                                }
                            }
                            Divider()
                        }
                    }
                    .padding(.bottom, 16)
                }
                if let dailySpecials = location.dailySpecials, !dailySpecials.isEmpty {
                    VStack(alignment: .leading) {
                        Text("Today's Daily Specials")
                            .font(.title3)
                            .fontWeight(.semibold)
                        ForEach(dailySpecials, id: \.self) { special in
                            HStack(alignment: .top) {
                                Text(special.name)
                                Spacer()
                                Text(special.type)
                                    .foregroundStyle(.secondary)
                            }
                            Divider()
                        }
                    }
                    .padding(.bottom, 16)
                }
                VStack(alignment: .leading) {
                    Text("Upcoming Hours")
                        .font(.title3)
                        .fontWeight(.semibold)
                    ForEach(weeklyHours, id: \.self) { day in
                        HStack(alignment: .top) {
                            Text(day.day)
                            Spacer()
                            VStack {
                                ForEach(day.timeStrings, id: \.self) { timeString in
                                    Text(timeString)
                                        .foregroundStyle(.secondary)
                                }
                            }
                        }
                        Divider()
                    }
                }
                .padding(.bottom, 16)
                // Ideally I'd like this text to be justified to more effectively use the screen space.
                Text(location.desc)
                    .font(.body)
            }
            .padding(.horizontal, 16)
            .toolbar {
                ToolbarItemGroup(placement: .primaryAction) {
                    // Favorites toggle button.
                    Button(action: {
                        if model.favorites.contains(location) {
                            model.favorites.remove(location)
                        } else {
                            model.favorites.add(location)
                        }
                    }) {
                        if model.favorites.contains(location) {
                            Image(systemName: "star.fill")
                                .foregroundStyle(.yellow)
                                //.font(.title3)
                        } else {
                            Image(systemName: "star")
                                .foregroundStyle(.yellow)
                                //.font(.title3)
                        }
                    }
// THIS FEATURE DISABLED AT RIT'S REQUEST FOR SECURITY REASONS.
// No hard feelings or anything though, I get it.
//                          // Open OnDemand. Unfortunately the locations use arbitrary IDs, so just open the main OnDemand page.
//                            Button(action: {
//                                openURL(URL(string: "https://ondemand.rit.edu")!)
//                            }) {
//                                Image(systemName: "cart")
//                                    .font(.title3)
//                            }
//                            .disabled(location.open == .closed || location.open == .openingSoon)
                    // Open this location on the RIT map in embedded Safari.
                    Button(action: {
                        showingSafari = true
                    }) {
                        Image(systemName: "map")
                            //.font(.title3)
                    }
                    if let fdmpIds = location.fdmpIds {
                        NavigationLink(destination: MenuView(accountId: fdmpIds.accountId, locationId: fdmpIds.locationId)) {
                            Image(systemName: "menucard")
                        }
                    }
                }
            }
        }
        .navigationTitle("Details")
        .navigationBarTitleDisplayMode(.inline)
        .sheet(isPresented: $showingSafari) {
            SafariView(url: URL(string: location.mapsUrl)!)
        }
        .refreshable {
            do {
                try await model.getHoursByDay()
            } catch {
                print(error)
            }
            await getOccupancy()
        }
    }
}
