import Combine
import SwiftUI

enum SessionViewMode: String {
    case list
    case calendar
}

struct SessionsView: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @State private var showingAddSession = false
    @AppStorage("sessionViewMode") private var viewMode: SessionViewMode = .list
    @State private var selectedMonth = Date()
    @State private var selectedDate: Date? = nil
    @State private var selectedSessionId: UUID? = nil

    private var completedSessions: [ClimbSession] {
        dataManager.sessions
            .filter { $0.status == .completed }
            .sorted { $0.date > $1.date }
    }

    var body: some View {
        NavigationStack {
            Group {
                if dataManager.sessions.isEmpty && dataManager.activeSession == nil {
                    EmptySessionsView()
                } else {
                    if viewMode == .list {
                        SessionsList()
                    } else {
                        CalendarView(
                            sessions: completedSessions,
                            selectedMonth: $selectedMonth,
                            selectedDate: $selectedDate,
                            onNavigateToSession: { sessionId in
                                selectedSessionId = sessionId
                            }
                        )
                    }
                }
            }
            .navigationTitle("Sessions")
            .navigationBarTitleDisplayMode(.automatic)
            .toolbar {
                ToolbarItemGroup(placement: .navigationBarTrailing) {
                    if dataManager.isSyncing {
                        HStack(spacing: 2) {
                            ProgressView()
                                .progressViewStyle(CircularProgressViewStyle(tint: .blue))
                                .scaleEffect(0.6)
                        }
                        .padding(.horizontal, 6)
                        .padding(.vertical, 3)
                        .background(
                            Circle()
                                .fill(.regularMaterial)
                        )
                        .transition(.scale.combined(with: .opacity))
                        .animation(
                            .easeInOut(duration: 0.2), value: dataManager.isSyncing
                        )
                    }

                    if !dataManager.sessions.isEmpty || dataManager.activeSession != nil {
                        Button(action: {
                            withAnimation(.easeInOut(duration: 0.2)) {
                                viewMode = viewMode == .list ? .calendar : .list
                                selectedDate = nil
                            }
                        }) {
                            Image(systemName: viewMode == .list ? "calendar" : "list.bullet")
                                .font(.body)
                                .fontWeight(.semibold)
                        }
                    }

                    if dataManager.gyms.isEmpty {
                        EmptyView()
                    } else if dataManager.activeSession == nil {
                        Button("Start Session") {
                            if dataManager.gyms.count == 1 {
                                dataManager.startSession(gymId: dataManager.gyms.first!.id)
                            } else {
                                showingAddSession = true
                            }
                        }
                    }
                }
            }
            .sheet(isPresented: $showingAddSession) {
                AddEditSessionView()
            }
            .navigationDestination(isPresented: .constant(selectedSessionId != nil)) {
                if let sessionId = selectedSessionId {
                    SessionDetailView(sessionId: sessionId)
                        .onDisappear {
                            selectedSessionId = nil
                        }
                }
            }
        }
    }
}

struct SessionsList: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @State private var sessionToDelete: ClimbSession?

    private var completedSessions: [ClimbSession] {
        dataManager.sessions
            .filter { $0.status == .completed }
            .sorted { $0.date > $1.date }
    }

    var body: some View {
        List {
            if let activeSession = dataManager.activeSession,
                let gym = dataManager.gym(withId: activeSession.gymId)
            {
                Section {
                    ActiveSessionBanner(session: activeSession, gym: gym)
                        .environmentObject(MusicService.shared)
                        .padding(.horizontal, 16)
                        .listRowInsets(EdgeInsets(top: 16, leading: 0, bottom: 24, trailing: 0))
                        .listRowBackground(Color.clear)
                        .listRowSeparator(.hidden)
                }
            }

            if !completedSessions.isEmpty {
                Section {
                    ForEach(completedSessions) { session in
                        NavigationLink(destination: SessionDetailView(sessionId: session.id)) {
                            SessionRow(session: session)
                        }
                        .swipeActions(edge: .trailing, allowsFullSwipe: false) {
                            Button(role: .destructive) {
                                sessionToDelete = session
                            } label: {
                                Label("Delete", systemImage: "trash")
                            }
                            .tint(.red)
                        }
                    }
                } header: {
                    if dataManager.activeSession != nil {
                        Text("Previous Sessions")
                            .font(.headline)
                            .fontWeight(.semibold)
                    }
                }
            }
        }
        .listStyle(.insetGrouped)
        .confirmationDialog(
            "Delete Session",
            isPresented: .init(
                get: { sessionToDelete != nil },
                set: { if !$0 { sessionToDelete = nil } }
            ),
            titleVisibility: .visible
        ) {
            Button("Delete", role: .destructive) {
                if let session = sessionToDelete {
                    dataManager.deleteSession(session)
                    sessionToDelete = nil
                }
            }
            Button("Cancel", role: .cancel) {
                sessionToDelete = nil
            }
        } message: {
            Text(
                "Are you sure you want to delete this session? This will also delete all attempts associated with this session."
            )
        }
    }
}

struct ActiveSessionBanner: View {
    let session: ClimbSession
    let gym: Gym
    @EnvironmentObject var dataManager: ClimbingDataManager
    @EnvironmentObject var musicService: MusicService
    @State private var navigateToDetail = false

    var body: some View {
        HStack {
            VStack(alignment: .leading, spacing: 4) {
                HStack {
                    Image(systemName: "play.fill")
                        .foregroundColor(.green)
                        .font(.caption)
                    Text("Active Session")
                        .font(.headline)
                        .fontWeight(.bold)
                }

                Text(gym.name)
                    .font(.subheadline)
                    .foregroundColor(.secondary)

                if let startTime = session.startTime {
                    Text(timerInterval: startTime...Date.distantFuture, countsDown: false)
                        .font(.caption)
                        .foregroundColor(.secondary)
                        .monospacedDigit()
                }

                if musicService.isMusicEnabled && musicService.isAuthorized {
                    Button(action: {
                        musicService.togglePlayback()
                    }) {
                        HStack(spacing: 4) {
                            Image(systemName: musicService.isPlaying ? "pause.fill" : "play.fill")
                                .font(.caption)
                        }
                        .foregroundColor(.pink)
                        .padding(.top, 2)
                    }
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .contentShape(Rectangle())
            .onTapGesture {
                navigateToDetail = true
            }

            Button(action: {
                dataManager.endSession(session.id)
            }) {
                Image(systemName: "stop.fill")
                    .font(.system(size: 16, weight: .bold))
                    .foregroundColor(.white)
                    .frame(width: 32, height: 32)
                    .background(Color.red)
                    .clipShape(Circle())
            }
            .buttonStyle(PlainButtonStyle())
        }
        .padding()
        .background(
            RoundedRectangle(cornerRadius: 12)
                .fill(.green.opacity(0.1))
                .stroke(.green.opacity(0.3), lineWidth: 1)
        )
        .navigationDestination(isPresented: $navigateToDetail) {
            SessionDetailView(sessionId: session.id)
        }
    }
}

struct SessionRow: View {
    let session: ClimbSession
    @EnvironmentObject var dataManager: ClimbingDataManager

    private static let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateStyle = .medium
        return formatter
    }()

    private var gym: Gym? {
        dataManager.gym(withId: session.gymId)
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            HStack {
                Text(gym?.name ?? "Unknown Gym")
                    .font(.headline)
                    .fontWeight(.semibold)

                Spacer()

                Text(Self.dateFormatter.string(from: session.date))
                    .font(.caption)
                    .foregroundColor(.secondary)
            }

            if let duration = session.duration {
                Text("Duration: \(duration) minutes")
                    .font(.subheadline)
                    .foregroundColor(.secondary)
            }

            if let notes = session.notes, !notes.isEmpty {
                Text(notes)
                    .font(.caption)
                    .foregroundColor(.secondary)
                    .lineLimit(2)
            }
        }
        .padding(.vertical, 8)
    }
}

struct EmptySessionsView: View {
    @EnvironmentObject var dataManager: ClimbingDataManager
    @State private var showingAddSession = false

    var body: some View {
        VStack(spacing: 20) {
            Spacer()

            Image(systemName: "figure.climbing")
                .font(.system(size: 60))
                .foregroundColor(.secondary)

            VStack(spacing: 8) {
                Text(dataManager.gyms.isEmpty ? "No Gyms Available" : "No Sessions Yet")
                    .font(.title2)
                    .fontWeight(.bold)

                Text(
                    dataManager.gyms.isEmpty
                        ? "Add a gym first to start tracking your climbing sessions!"
                        : "Start your first climbing session!"
                )
                .font(.body)
                .foregroundColor(.secondary)
                .multilineTextAlignment(.center)
                .padding(.horizontal)
            }

            if !dataManager.gyms.isEmpty {
                Button("Start Session") {
                    if dataManager.gyms.count == 1 {
                        dataManager.startSession(gymId: dataManager.gyms.first!.id)
                    } else {
                        showingAddSession = true
                    }
                }
                .buttonStyle(.borderedProminent)
                .controlSize(.large)
            }

            Spacer()
        }
        .sheet(isPresented: $showingAddSession) {
            AddEditSessionView()
        }
    }
}

#Preview {
    SessionsView()
        .environmentObject(ClimbingDataManager.preview)
}
