import SwiftUI

/// Settings screen for the Live Flights tab. Currently just OpenSky
/// account credentials — used to bump the request quota from anonymous's
/// ~100/day to the authenticated 4000/day.
struct OpenSkySettingsView: View {
    @Environment(\.dismiss) private var dismiss

    @State private var username: String = ""
    @State private var password: String = ""
    @State private var isSaving: Bool = false
    @State private var isAuthed: Bool = false
    @State private var saveError: String?
    @State private var saveSuccess: Bool = false

    var body: some View {
        NavigationStack {
            Form {
                Section {
                    if isAuthed {
                        HStack {
                            Image(systemName: "checkmark.seal.fill")
                                .foregroundStyle(FlightTheme.onTime)
                            Text("Signed in as \(username)")
                                .font(.subheadline.weight(.semibold))
                        }
                        Button(role: .destructive) {
                            OpenSkyCredentials.shared.clear()
                            username = ""
                            password = ""
                            isAuthed = false
                            saveSuccess = false
                            saveError = nil
                        } label: {
                            Text("Sign out")
                        }
                    } else {
                        TextField("Username", text: $username)
                            .textInputAutocapitalization(.never)
                            .autocorrectionDisabled()
                        SecureField("Password", text: $password)
                        Button {
                            saveCredentials()
                        } label: {
                            HStack {
                                if isSaving { ProgressView() }
                                Text(isSaving ? "Saving…" : "Save")
                                    .fontWeight(.semibold)
                            }
                            .frame(maxWidth: .infinity)
                        }
                        .disabled(isSaving || username.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
                                  || password.isEmpty)
                    }
                } header: {
                    Text("OpenSky Network")
                } footer: {
                    Text(footerText)
                        .font(.caption)
                }

                if let saveError {
                    Section {
                        Text(saveError)
                            .font(.caption)
                            .foregroundStyle(FlightTheme.cancelled)
                    }
                }
                if saveSuccess {
                    Section {
                        HStack {
                            Image(systemName: "checkmark.circle.fill")
                                .foregroundStyle(FlightTheme.onTime)
                            Text("Credentials saved — quota raised to 4,000/day.")
                                .font(.caption)
                        }
                    }
                }
            }
            .navigationTitle("Live Flights Settings")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button { dismiss() } label: {
                        Image(systemName: "xmark")
                            .font(.subheadline.weight(.semibold))
                    }
                }
            }
            .onAppear { loadExisting() }
        }
    }

    private var footerText: String {
        if isAuthed {
            return "Quota: ~4,000 requests/day. Sign out to go back to anonymous."
        }
        return "Anonymous access is capped at ~100 requests/day per IP. Sign in to a free OpenSky account (opensky-network.org/register) to raise the cap to ~4,000/day. Credentials are stored in the iOS Keychain."
    }

    private func loadExisting() {
        if let creds = OpenSkyCredentials.shared.load() {
            username = creds.username
            password = ""  // never expose the stored password back to the UI
            isAuthed = true
        }
    }

    private func saveCredentials() {
        let u = username.trimmingCharacters(in: .whitespacesAndNewlines)
        let p = password
        guard !u.isEmpty, !p.isEmpty else { return }
        isSaving = true
        saveError = nil
        saveSuccess = false

        Task {
            // Sanity-check the credentials by hitting the /states/all
            // endpoint once and watching for HTTP 401. If they're bad,
            // we won't save them.
            let ok = await verify(username: u, password: p)
            await MainActor.run {
                isSaving = false
                if ok {
                    OpenSkyCredentials.shared.save(username: u, password: p)
                    isAuthed = true
                    saveSuccess = true
                    password = ""
                } else {
                    saveError = "Could not authenticate with OpenSky. Double-check the username and password."
                }
            }
        }
    }

    /// Send a tiny request to /states/all with the candidate creds to
    /// see whether OpenSky accepts them (401 → bad credentials).
    private func verify(username: String, password: String) async -> Bool {
        // 1° x 1° box near MSP — tiny payload.
        var comps = URLComponents(string: "https://opensky-network.org/api/states/all")!
        comps.queryItems = [
            URLQueryItem(name: "lamin", value: "44.5"),
            URLQueryItem(name: "lomin", value: "-93.5"),
            URLQueryItem(name: "lamax", value: "45.5"),
            URLQueryItem(name: "lomax", value: "-92.5")
        ]
        guard let url = comps.url else { return false }
        var req = URLRequest(url: url)
        let raw = "\(username):\(password)"
        if let data = raw.data(using: .utf8) {
            req.setValue("Basic \(data.base64EncodedString())", forHTTPHeaderField: "Authorization")
        }
        do {
            let (_, response) = try await URLSession.shared.data(for: req)
            let status = (response as? HTTPURLResponse)?.statusCode ?? -1
            return status == 200
        } catch {
            return false
        }
    }
}
