//
//  RegionMapSelector.swift
//  SportsTime
//
//  Interactive map for selecting travel regions using MapKit.
//

import MapKit
import SwiftUI

/// A map-based selector for choosing geographic regions.
/// Shows North America with three tappable overlay zones: West, Central, East.
///
/// Selection rules:
/// - Can select: East, Central, West, East+Central, Central+West
/// - Cannot select: East+West (must have Central between them)
struct RegionMapSelector: View {
    @Binding var selectedRegions: Set<Region>
    let onToggle: (Region) -> Void

    @Environment(\.colorScheme) private var colorScheme
    @Environment(\.isDemoMode) private var isDemoMode
    @State private var hasAppliedDemoSelection = false

    // Camera position centered on continental US
    @State private var cameraPosition: MapCameraPosition = .camera(
        MapCamera(
            centerCoordinate: CLLocationCoordinate2D(latitude: 39.5, longitude: -98.0),
            distance: 8_000_000,
            heading: 0,
            pitch: 0
        )
    )

    var body: some View {
        VStack(spacing: Theme.Spacing.sm) {
            // Map with region overlays
            ZStack {
                MapReader { proxy in
                    Map(position: $cameraPosition, interactionModes: []) {
                        // West region polygon
                        MapPolygon(coordinates: RegionCoordinates.west)
                            .foregroundStyle(fillColor(for: .west))
                            .stroke(strokeColor(for: .west), lineWidth: strokeWidth(for: .west))

                        // Central region polygon
                        MapPolygon(coordinates: RegionCoordinates.central)
                            .foregroundStyle(fillColor(for: .central))
                            .stroke(strokeColor(for: .central), lineWidth: strokeWidth(for: .central))

                        // East region polygon
                        MapPolygon(coordinates: RegionCoordinates.east)
                            .foregroundStyle(fillColor(for: .east))
                            .stroke(strokeColor(for: .east), lineWidth: strokeWidth(for: .east))
                    }
                    .mapStyle(.standard(elevation: .flat, pointsOfInterest: .excludingAll))
                    .onTapGesture { location in
                        if let coordinate = proxy.convert(location, from: .local) {
                            let tappedRegion = regionForCoordinate(coordinate)
                            onToggle(tappedRegion)
                        }
                    }
                }

                // Invisible button overlays for UI testing accessibility
                HStack(spacing: 0) {
                    Button { onToggle(.west) } label: { Color.clear }
                        .accessibilityIdentifier("wizard.regions.west")
                        .accessibilityLabel("West region")
                        .accessibilityValue(selectedRegions.contains(.west) ? "Selected" : "Not selected")
                        .accessibilityHint(
                            selectedRegions.contains(.west)
                                ? "Double-tap to deselect this region"
                                : "Double-tap to select this region"
                        )
                        .accessibilityAddTraits(selectedRegions.contains(.west) ? .isSelected : [])
                        .frame(maxWidth: .infinity)
                    Button { onToggle(.central) } label: { Color.clear }
                        .accessibilityIdentifier("wizard.regions.central")
                        .accessibilityLabel("Central region")
                        .accessibilityValue(selectedRegions.contains(.central) ? "Selected" : "Not selected")
                        .accessibilityHint(
                            selectedRegions.contains(.central)
                                ? "Double-tap to deselect this region"
                                : "Double-tap to select this region"
                        )
                        .accessibilityAddTraits(selectedRegions.contains(.central) ? .isSelected : [])
                        .frame(maxWidth: .infinity)
                    Button { onToggle(.east) } label: { Color.clear }
                        .accessibilityIdentifier("wizard.regions.east")
                        .accessibilityLabel("East region")
                        .accessibilityValue(selectedRegions.contains(.east) ? "Selected" : "Not selected")
                        .accessibilityHint(
                            selectedRegions.contains(.east)
                                ? "Double-tap to deselect this region"
                                : "Double-tap to select this region"
                        )
                        .accessibilityAddTraits(selectedRegions.contains(.east) ? .isSelected : [])
                        .frame(maxWidth: .infinity)
                }
            }
            .frame(height: 160)
            .clipShape(RoundedRectangle(cornerRadius: Theme.CornerRadius.medium))
            .overlay(
                RoundedRectangle(cornerRadius: Theme.CornerRadius.medium)
                    .stroke(Theme.textMuted(colorScheme).opacity(0.3), lineWidth: 1)
            )

            // Region legend with colors and example states
            regionLegend

            // Selection footer
            selectionFooter
        }
        .onAppear {
            if isDemoMode && !hasAppliedDemoSelection && selectedRegions.isEmpty {
                hasAppliedDemoSelection = true
                DispatchQueue.main.asyncAfter(deadline: .now() + DemoConfig.selectionDelay) {
                    onToggle(DemoConfig.demoRegion)
                }
            }
        }
    }

    // MARK: - Coordinate to Region

    /// Determines which region a coordinate falls into based on state groupings.
    /// West: States west of ~-102° (WA, OR, CA, NV, ID, UT, AZ, MT, WY, CO, NM)
    /// Central: States between ~-102° and ~-89° (ND, SD, NE, KS, OK, TX, MN, IA, MO, AR, LA, WI, IL)
    /// East: States east of ~-89°
    private func regionForCoordinate(_ coordinate: CLLocationCoordinate2D) -> Region {
        let longitude = coordinate.longitude
        if longitude < -102 {
            return .west
        } else if longitude > -89 {
            return .east
        } else {
            return .central
        }
    }

    // MARK: - Styling

    private func fillColor(for region: Region) -> Color {
        let isSelected = selectedRegions.contains(region)
        if isSelected {
            return regionColor(region).opacity(0.6)
        }
        return Color.gray.opacity(0.15)
    }

    private func strokeColor(for region: Region) -> Color {
        let isSelected = selectedRegions.contains(region)
        if isSelected {
            return regionColor(region)
        }
        return Color.white.opacity(0.4)
    }

    private func strokeWidth(for region: Region) -> CGFloat {
        selectedRegions.contains(region) ? 3 : 1
    }

    private func regionColor(_ region: Region) -> Color {
        switch region {
        case .west: return Color(hex: "f97316") // Orange
        case .central: return Color(hex: "3b82f6") // Blue
        case .east: return Color(hex: "22c55e") // Green
        case .crossCountry: return .purple
        }
    }

    // MARK: - Legend

    private var regionLegend: some View {
        HStack(spacing: Theme.Spacing.md) {
            legendItem(.west, states: "CA, WA, OR, AZ")
            legendItem(.central, states: "TX, IL, CO, MN")
            legendItem(.east, states: "NY, FL, MA, GA")
        }
    }

    private func legendItem(_ region: Region, states: String) -> some View {
        let isSelected = selectedRegions.contains(region)
        return HStack(spacing: 6) {
            Circle()
                .fill(regionColor(region))
                .frame(width: 10, height: 10)
                .overlay(
                    Circle()
                        .stroke(Color.white.opacity(0.5), lineWidth: isSelected ? 2 : 0)
                )
                .accessibilityHidden(true)

            VStack(alignment: .leading, spacing: 1) {
                Text(region.shortName)
                    .font(.caption2)
                    .foregroundStyle(isSelected ? regionColor(region) : Theme.textPrimary(colorScheme))

                Text(states)
                    .font(.caption2)
                    .foregroundStyle(Theme.textMuted(colorScheme))
            }
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    private var selectionFooter: some View {
        HStack(spacing: Theme.Spacing.md) {
            if selectedRegions.isEmpty {
                Text("Tap map to select regions")
                    .font(.caption)
                    .foregroundStyle(Theme.textMuted(colorScheme))
            } else {
                Spacer()

                Button {
                    selectedRegions.removeAll()
                } label: {
                    Text("Clear")
                        .font(.caption)
                        .foregroundStyle(Theme.warmOrange)
                }
            }
        }
    }
}

// MARK: - Region Coordinates

/// Geographic coordinates tracing actual state borders.
/// West: WA, OR, CA, NV, ID, UT, AZ, MT, WY, CO, NM
/// Central: ND, SD, NE, KS, OK, TX, MN, IA, MO, AR, LA, WI, IL
/// East: All remaining states
private enum RegionCoordinates {

    // MARK: - West Region
    // Outer boundary of: WA, OR, CA, NV, ID, UT, AZ, MT, WY, CO, NM
    static let west: [CLLocationCoordinate2D] = [
        // Start: Canada/WA border, Pacific
        CLLocationCoordinate2D(latitude: 49.0, longitude: -123.3),
        // WA coast south
        CLLocationCoordinate2D(latitude: 46.3, longitude: -124.0),
        // OR coast
        CLLocationCoordinate2D(latitude: 42.0, longitude: -124.2),
        // CA coast
        CLLocationCoordinate2D(latitude: 39.0, longitude: -123.7),
        CLLocationCoordinate2D(latitude: 34.5, longitude: -120.5),
        CLLocationCoordinate2D(latitude: 32.5, longitude: -117.1),
        // CA/Mexico border
        CLLocationCoordinate2D(latitude: 32.7, longitude: -114.7),
        // AZ/Mexico border
        CLLocationCoordinate2D(latitude: 31.3, longitude: -111.1),
        // NM/Mexico border to TX border
        CLLocationCoordinate2D(latitude: 31.8, longitude: -108.2),
        CLLocationCoordinate2D(latitude: 32.0, longitude: -106.6),
        // NM/TX border north
        CLLocationCoordinate2D(latitude: 32.0, longitude: -103.0),
        // NM/OK/TX corner, then CO/OK border
        CLLocationCoordinate2D(latitude: 36.5, longitude: -103.0),
        // CO/KS border
        CLLocationCoordinate2D(latitude: 37.0, longitude: -102.0),
        CLLocationCoordinate2D(latitude: 40.0, longitude: -102.0),
        // CO/NE border to WY
        CLLocationCoordinate2D(latitude: 41.0, longitude: -102.0),
        // WY/NE/SD corner
        CLLocationCoordinate2D(latitude: 43.0, longitude: -104.0),
        // WY/SD border
        CLLocationCoordinate2D(latitude: 45.0, longitude: -104.0),
        // MT/ND border
        CLLocationCoordinate2D(latitude: 49.0, longitude: -104.0),
        // Canada border west
        CLLocationCoordinate2D(latitude: 49.0, longitude: -117.0),
    ]

    // MARK: - Central Region
    // Outer boundary of: ND, SD, NE, KS, OK, TX, MN, IA, MO, AR, LA, WI, IL
    static let central: [CLLocationCoordinate2D] = [
        // Start: Canada/ND border at MT
        CLLocationCoordinate2D(latitude: 49.0, longitude: -104.0),
        // MT/ND border south to SD
        CLLocationCoordinate2D(latitude: 45.9, longitude: -104.0),
        // WY/SD border
        CLLocationCoordinate2D(latitude: 45.0, longitude: -104.0),
        CLLocationCoordinate2D(latitude: 43.0, longitude: -104.0),
        // NE/WY border
        CLLocationCoordinate2D(latitude: 41.0, longitude: -104.0),
        // CO/NE border
        CLLocationCoordinate2D(latitude: 41.0, longitude: -102.0),
        // KS/CO border
        CLLocationCoordinate2D(latitude: 40.0, longitude: -102.0),
        CLLocationCoordinate2D(latitude: 37.0, longitude: -102.0),
        // OK/CO/NM corner
        CLLocationCoordinate2D(latitude: 36.5, longitude: -103.0),
        // TX/NM border
        CLLocationCoordinate2D(latitude: 32.0, longitude: -103.0),
        CLLocationCoordinate2D(latitude: 32.0, longitude: -106.6),
        // TX/Mexico border (Rio Grande)
        CLLocationCoordinate2D(latitude: 31.8, longitude: -106.4),
        CLLocationCoordinate2D(latitude: 29.5, longitude: -103.4),
        CLLocationCoordinate2D(latitude: 26.0, longitude: -97.4),
        // TX Gulf coast
        CLLocationCoordinate2D(latitude: 26.1, longitude: -97.2),
        CLLocationCoordinate2D(latitude: 29.4, longitude: -94.7),
        // LA Gulf coast
        CLLocationCoordinate2D(latitude: 29.5, longitude: -93.8),
        CLLocationCoordinate2D(latitude: 29.1, longitude: -89.0),
        // LA/MS border at Gulf
        CLLocationCoordinate2D(latitude: 30.2, longitude: -89.1),
        // MS/LA/AR corner, up to TN
        CLLocationCoordinate2D(latitude: 33.0, longitude: -91.0),
        // AR/TN border
        CLLocationCoordinate2D(latitude: 35.0, longitude: -90.3),
        CLLocationCoordinate2D(latitude: 36.5, longitude: -89.5),
        // IL eastern border (up to WI)
        CLLocationCoordinate2D(latitude: 37.0, longitude: -89.1),
        CLLocationCoordinate2D(latitude: 39.0, longitude: -87.5),
        CLLocationCoordinate2D(latitude: 41.7, longitude: -87.5),
        CLLocationCoordinate2D(latitude: 42.5, longitude: -87.5),
        // WI/MI border at Lake Michigan, north to Lake Superior
        CLLocationCoordinate2D(latitude: 45.0, longitude: -87.0),
        CLLocationCoordinate2D(latitude: 46.8, longitude: -87.5),
        CLLocationCoordinate2D(latitude: 46.5, longitude: -85.0),
        // Lake Superior north shore
        CLLocationCoordinate2D(latitude: 48.0, longitude: -89.5),
        // MN/Canada
        CLLocationCoordinate2D(latitude: 49.0, longitude: -89.5),
        // Canada border west to ND
        CLLocationCoordinate2D(latitude: 49.0, longitude: -97.2),
    ]

    // MARK: - East Region
    // Outer boundary of: MI, IN, OH, KY, TN, MS, AL, GA, FL, SC, NC, VA, WV, MD, DE, PA, NJ, NY, CT, RI, MA, VT, NH, ME
    static let east: [CLLocationCoordinate2D] = [
        // Start at western border (IL/IN, TN/AR, MS/LA line) going south
        CLLocationCoordinate2D(latitude: 42.5, longitude: -87.5),   // WI/IL/IN corner (Lake Michigan)
        CLLocationCoordinate2D(latitude: 41.7, longitude: -87.5),   // IL/IN border
        CLLocationCoordinate2D(latitude: 39.0, longitude: -87.5),   // IN/IL border
        CLLocationCoordinate2D(latitude: 37.0, longitude: -89.1),   // KY/IL/MO corner
        CLLocationCoordinate2D(latitude: 36.5, longitude: -89.5),   // TN/AR/MO corner
        CLLocationCoordinate2D(latitude: 35.0, longitude: -90.3),   // TN/AR/MS corner
        CLLocationCoordinate2D(latitude: 33.0, longitude: -91.0),   // MS/LA/AR corner
        CLLocationCoordinate2D(latitude: 31.0, longitude: -89.7),   // MS/LA border south
        CLLocationCoordinate2D(latitude: 30.2, longitude: -89.1),   // MS Gulf coast
        // AL/FL Gulf coast
        CLLocationCoordinate2D(latitude: 30.2, longitude: -87.5),   // AL coast
        CLLocationCoordinate2D(latitude: 30.0, longitude: -85.0),   // FL panhandle
        // FL peninsula
        CLLocationCoordinate2D(latitude: 29.0, longitude: -83.0),   // FL Gulf
        CLLocationCoordinate2D(latitude: 26.0, longitude: -82.0),   // SW FL
        CLLocationCoordinate2D(latitude: 25.0, longitude: -80.5),   // Miami
        // Atlantic coast north
        CLLocationCoordinate2D(latitude: 27.0, longitude: -80.0),   // FL Atlantic
        CLLocationCoordinate2D(latitude: 30.5, longitude: -81.2),   // Jacksonville
        CLLocationCoordinate2D(latitude: 32.0, longitude: -80.8),   // Savannah
        CLLocationCoordinate2D(latitude: 34.0, longitude: -78.0),   // NC coast
        CLLocationCoordinate2D(latitude: 36.5, longitude: -76.0),   // VA coast
        CLLocationCoordinate2D(latitude: 38.5, longitude: -75.0),   // DE coast
        CLLocationCoordinate2D(latitude: 40.0, longitude: -74.0),   // NJ coast
        CLLocationCoordinate2D(latitude: 41.0, longitude: -72.0),   // CT coast
        CLLocationCoordinate2D(latitude: 42.0, longitude: -70.5),   // MA coast
        CLLocationCoordinate2D(latitude: 43.5, longitude: -70.0),   // ME south
        CLLocationCoordinate2D(latitude: 45.0, longitude: -67.0),   // ME coast
        CLLocationCoordinate2D(latitude: 47.2, longitude: -68.5),   // ME north
        // Canada border west to Great Lakes
        CLLocationCoordinate2D(latitude: 47.0, longitude: -69.5),   // ME/Canada
        CLLocationCoordinate2D(latitude: 45.0, longitude: -71.5),   // VT/Canada
        CLLocationCoordinate2D(latitude: 45.0, longitude: -75.0),   // NY/Canada
        CLLocationCoordinate2D(latitude: 43.5, longitude: -79.0),   // Lake Ontario
        CLLocationCoordinate2D(latitude: 42.5, longitude: -79.0),   // Lake Erie west
        CLLocationCoordinate2D(latitude: 41.5, longitude: -83.0),   // OH/MI
        CLLocationCoordinate2D(latitude: 43.0, longitude: -82.5),   // MI east
        CLLocationCoordinate2D(latitude: 46.0, longitude: -84.0),   // Upper MI
        CLLocationCoordinate2D(latitude: 46.5, longitude: -85.0),   // Lake Superior
        CLLocationCoordinate2D(latitude: 46.8, longitude: -87.5),   // Upper MI west
        CLLocationCoordinate2D(latitude: 45.0, longitude: -87.0),   // WI/MI (Green Bay)
    ]
}

// MARK: - Preview

#Preview {
    struct PreviewWrapper: View {
        @State private var selected: Set<Region> = [.central]

        var body: some View {
            VStack(spacing: 20) {
                RegionMapSelector(selectedRegions: $selected) { region in
                    if selected.contains(region) {
                        selected.remove(region)
                    } else {
                        // Adjacency rule: can't select both East and West
                        if region == .east {
                            selected.remove(.west)
                        } else if region == .west {
                            selected.remove(.east)
                        }
                        selected.insert(region)
                    }
                }
                .padding()

                Text("Selected: \(selected.map { $0.shortName }.joined(separator: ", "))")
            }
            .padding()
        }
    }

    return PreviewWrapper()
}

#Preview("Dark Mode") {
    struct PreviewWrapper: View {
        @State private var selected: Set<Region> = [.west, .central]

        var body: some View {
            VStack(spacing: 20) {
                RegionMapSelector(selectedRegions: $selected) { region in
                    if selected.contains(region) {
                        selected.remove(region)
                    } else {
                        if region == .east {
                            selected.remove(.west)
                        } else if region == .west {
                            selected.remove(.east)
                        }
                        selected.insert(region)
                    }
                }
                .padding()

                Text("Selected: \(selected.map { $0.shortName }.joined(separator: ", "))")
                    .foregroundStyle(.white)
            }
            .padding()
            .background(Color(hex: "1a1a2e"))
        }
    }

    return PreviewWrapper()
        .preferredColorScheme(.dark)
}
