import SwiftUI

struct RootView: View {
    @EnvironmentObject private var session: SessionStore

    var body: some View {
        Group {
            if !session.isLoggedIn {
                LoginView()
            } else if session.teamRole == "customer" {
                CustomerHomeView()
            } else {
                StaffHomeView()
            }
        }
    }
}

struct LoginView: View {
    @EnvironmentObject private var session: SessionStore
    @State private var email = ""
    @State private var password = ""
    @State private var error: String?
    @State private var loading = false

    var body: some View {
        NavigationStack {
            Form {
                Section("ServDiary") {
                    TextField("Email", text: $email)
                        .textInputAutocapitalization(.never)
                        .keyboardType(.emailAddress)
                    SecureField("Password", text: $password)
                }
                if let error {
                    Text(error).foregroundStyle(.red)
                }
                Button(loading ? "Signing in…" : "Sign in") {
                    Task {
                        loading = true
                        error = nil
                        defer { loading = false }
                        do {
                            let response = try await APIClient.shared.login(email: email, password: password)
                            session.applyLogin(response)
                        } catch {
                            self.error = error.localizedDescription
                        }
                    }
                }
                .disabled(loading)
            }
            .navigationTitle("Sign in")
        }
    }
}

struct StaffHomeView: View {
    @EnvironmentObject private var session: SessionStore
    @State private var appointments: [AppointmentDTO] = []
    @State private var error: String?

    var body: some View {
        NavigationStack {
            List(appointments) { appointment in
                NavigationLink {
                    AppointmentDetailView(appointment: appointment)
                } label: {
                    VStack(alignment: .leading) {
                        Text(appointment.job?.title ?? "Job #\(appointment.job_id)")
                        Text(appointment.starts_at).font(.caption)
                        Text(appointment.status).font(.caption2)
                    }
                }
            }
            .navigationTitle("Appointments")
            .toolbar {
                Button("Log out") { session.logout() }
            }
            .task { await load() }
            .refreshable { await load() }
            .overlay {
                if let error { Text(error).foregroundStyle(.red) }
            }
        }
    }

    private func load() async {
        error = nil
        do {
            let from = ISO8601DateFormatter.stringDate(daysFromNow: -1)
            let to = ISO8601DateFormatter.stringDate(daysFromNow: 14)
            appointments = try await APIClient.shared.appointments(from: from, to: to)
        } catch {
            self.error = error.localizedDescription
        }
    }
}

struct AppointmentDetailView: View {
    @State var appointment: AppointmentDTO
    @StateObject private var location = LocationProvider()
    @State private var message: String?

    var body: some View {
        Form {
            Section {
                Text(appointment.job?.title ?? "Appointment")
                Text(appointment.starts_at)
                Text("Status: \(appointment.status)")
            }
            if let message {
                Text(message)
            }
            Button("Check in") {
                Task {
                    do {
                        location.requestPermission()
                        let loc = try await location.currentLocation()
                        let response = try await APIClient.shared.checkIn(
                            jobId: appointment.job_id,
                            appointmentId: appointment.id,
                            latitude: loc.coordinate.latitude,
                            longitude: loc.coordinate.longitude
                        )
                        if let updated = response.appointment {
                            appointment = updated
                        }
                        message = "Checked in"
                    } catch {
                        message = error.localizedDescription
                    }
                }
            }
            Button("Complete") {
                Task {
                    do {
                        appointment = try await APIClient.shared.complete(
                            jobId: appointment.job_id,
                            appointmentId: appointment.id
                        )
                        message = "Completed"
                    } catch {
                        message = error.localizedDescription
                    }
                }
            }
        }
        .navigationTitle("Detail")
    }
}

struct CustomerHomeView: View {
    @EnvironmentObject private var session: SessionStore
    @State private var jobs: [JobDTO] = []
    @State private var error: String?

    var body: some View {
        NavigationStack {
            List(jobs) { job in
                NavigationLink(job.title) {
                    BookSlotsView(job: job)
                }
            }
            .navigationTitle("Your jobs")
            .toolbar {
                Button("Log out") { session.logout() }
            }
            .task {
                do {
                    jobs = try await APIClient.shared.jobs()
                } catch {
                    self.error = error.localizedDescription
                }
            }
            .overlay {
                if let error { Text(error).foregroundStyle(.red) }
            }
        }
    }
}

struct BookSlotsView: View {
    let job: JobDTO
    @State private var date = ISO8601DateFormatter.stringDate(daysFromNow: 1)
    @State private var slots: [SlotDTO] = []
    @State private var message: String?

    var body: some View {
        Form {
            Section(job.title) {
                TextField("Date YYYY-MM-DD", text: $date)
                Button("Load slots") {
                    Task {
                        do {
                            slots = try await APIClient.shared.availableSlots(jobId: job.id, date: date)
                            if slots.isEmpty { message = "No slots for this date" }
                        } catch {
                            message = error.localizedDescription
                        }
                    }
                }
            }
            if let message {
                Text(message)
            }
            Section("Slots") {
                ForEach(slots) { slot in
                    Button(slot.starts_at) {
                        Task {
                            do {
                                _ = try await APIClient.shared.book(jobId: job.id, startsAt: slot.starts_at)
                                message = "Booked \(slot.starts_at)"
                            } catch {
                                message = error.localizedDescription
                            }
                        }
                    }
                }
            }
        }
        .navigationTitle("Book")
    }
}

private extension ISO8601DateFormatter {
    static func stringDate(daysFromNow: Int) -> String {
        let date = Calendar.current.date(byAdding: .day, value: daysFromNow, to: Date()) ?? Date()
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .gregorian)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter.string(from: date)
    }
}
