import SwiftUI

struct CSVMappingView: View {
    let csvContent: String
    let onComplete: (ImportService.CSVMappingConfig) -> Void

    @Environment(\.dismiss) private var dismiss
    @State private var config = ImportService.CSVMappingConfig()
    @State private var preview: ImportService.CSVPreview?

    var body: some View {
        NavigationStack {
            Form {
                // CSV Preview section
                if let preview, let sample = preview.sampleRow(hasHeaderRow: config.hasHeaderRow) {
                    Section(String(localized: "csv_preview_section")) {
                        Toggle("Has Header Row", isOn: $config.hasHeaderRow)
                            .onChange(of: config.hasHeaderRow) { _, _ in resetMappings() }

                        ScrollView(.horizontal, showsIndicators: false) {
                            HStack(alignment: .top, spacing: 16) {
                                ForEach(
                                    Array(zip(
                                        preview.headers(hasHeaderRow: config.hasHeaderRow),
                                        sample
                                    ).enumerated()),
                                    id: \.offset
                                ) { _, pair in
                                    VStack(alignment: .leading, spacing: 2) {
                                        Text(pair.0)
                                            .font(.caption2.weight(.semibold))
                                            .foregroundColor(.secondary)
                                        Text(pair.1.isEmpty ? "—" : pair.1)
                                            .font(.caption)
                                            .lineLimit(2)
                                    }
                                    .frame(minWidth: 60, alignment: .leading)
                                }
                            }
                            .padding(.vertical, 4)
                        }
                    }
                }

                // Required fields
                Section(String(localized: "csv_required_section")) {
                    MappingRow(
                        label: String(localized: "csv_field_source"),
                        index: $config.sourceIndex,
                        constant: $config.sourceConstant,
                        headers: currentHeaders,
                        supportsConstant: true,
                        supportsUseToday: false,
                        canSkip: false
                    )

                    MappingRow(
                        label: String(localized: "csv_field_value"),
                        index: $config.valueIndex,
                        constant: .constant(""),
                        headers: currentHeaders,
                        supportsConstant: false,
                        supportsUseToday: false,
                        canSkip: false
                    )
                }

                // Date section
                Section {
                    MappingRow(
                        label: String(localized: "csv_field_date"),
                        index: $config.dateIndex,
                        constant: .constant(""),
                        headers: currentHeaders,
                        supportsConstant: false,
                        supportsUseToday: true,
                        canSkip: false
                    )
                } header: {
                    Text("Date")
                } footer: {
                    if config.dateIndex == ImportService.CSVMappingConfig.useToday {
                        Text(String(localized: "csv_no_date_hint"))
                    }
                }

                // Optional fields
                Section(String(localized: "csv_optional_section")) {
                    MappingRowWithConstant(
                        label: String(localized: "csv_field_category"),
                        index: $config.categoryIndex,
                        constant: $config.categoryConstant,
                        headers: currentHeaders
                    )

                    MappingRow(
                        label: String(localized: "csv_field_contribution"),
                        index: $config.contributionIndex,
                        constant: .constant(""),
                        headers: currentHeaders,
                        supportsConstant: false,
                        supportsUseToday: false,
                        canSkip: true
                    )

                    MappingRow(
                        label: String(localized: "csv_field_notes"),
                        index: $config.notesIndex,
                        constant: .constant(""),
                        headers: currentHeaders,
                        supportsConstant: false,
                        supportsUseToday: false,
                        canSkip: true
                    )
                }
            }
            .navigationTitle("Map Columns")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button("Import") {
                        onComplete(config)
                        dismiss()
                    }
                    .fontWeight(.semibold)
                    .disabled(!config.isValid)
                }
            }
            .onAppear {
                let p = ImportService.shared.previewCSV(csvContent)
                self.preview = p
                autoDetectColumns(from: p)
            }
        }
        .presentationDetents([.large])
    }

    private var currentHeaders: [String] {
        preview?.headers(hasHeaderRow: config.hasHeaderRow) ?? []
    }

    private func resetMappings() {
        guard let preview else { return }
        autoDetectColumns(from: preview)
    }

    /// Try to auto-detect columns by matching common header names
    private func autoDetectColumns(from preview: ImportService.CSVPreview) {
        guard config.hasHeaderRow else { return }
        let headers = preview.headers(hasHeaderRow: true)
        let lower = headers.map { $0.lowercased().trimmingCharacters(in: .whitespaces) }

        for (i, h) in lower.enumerated() {
            if config.sourceIndex == ImportService.CSVMappingConfig.notMapped &&
               (h == "source" || h == "name" || h == "fuente" || h == "nombre") {
                config.sourceIndex = i
            }
            if config.valueIndex == ImportService.CSVMappingConfig.notMapped &&
               (h.hasPrefix("value") || h == "amount" || h == "valor" || h == "importe") {
                config.valueIndex = i
            }
            if config.dateIndex == ImportService.CSVMappingConfig.useToday &&
               (h == "date" || h == "fecha" || h.hasPrefix("date")) {
                config.dateIndex = i
            }
            if config.categoryIndex == ImportService.CSVMappingConfig.constant &&
               (h == "category" || h == "categoría" || h == "categoria" || h == "type") {
                config.categoryIndex = i
            }
            if config.contributionIndex == ImportService.CSVMappingConfig.notMapped &&
               (h.hasPrefix("contribution") || h == "aportación" || h == "aportacion") {
                config.contributionIndex = i
            }
            if config.notesIndex == ImportService.CSVMappingConfig.notMapped &&
               (h == "notes" || h == "notas" || h == "note" || h == "comments") {
                config.notesIndex = i
            }
        }
    }
}

// MARK: - Mapping Row (column or constant/useToday/skip)

private struct MappingRow: View {
    let label: String
    @Binding var index: Int
    @Binding var constant: String
    let headers: [String]
    let supportsConstant: Bool
    let supportsUseToday: Bool
    let canSkip: Bool

    private var selectionLabel: String {
        if index == ImportService.CSVMappingConfig.useToday {
            return String(localized: "csv_use_today")
        }
        if index == ImportService.CSVMappingConfig.constant {
            return constant.isEmpty ? String(localized: "csv_enter_value") : constant
        }
        if index == ImportService.CSVMappingConfig.notMapped {
            return String(localized: "csv_no_column")
        }
        return headers[safe: index] ?? "Column \(index + 1)"
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 4) {
            HStack {
                Text(label)
                    .font(.subheadline)

                Spacer()

                Menu {
                    // Column options
                    if !headers.isEmpty {
                        ForEach(Array(headers.enumerated()), id: \.offset) { i, h in
                            Button { index = i } label: {
                                Label(h, systemImage: index == i ? "checkmark" : "")
                            }
                        }
                        Divider()
                    }

                    if supportsUseToday {
                        Button {
                            index = ImportService.CSVMappingConfig.useToday
                        } label: {
                            Label(
                                String(localized: "csv_use_today"),
                                systemImage: index == ImportService.CSVMappingConfig.useToday ? "checkmark" : ""
                            )
                        }
                    }

                    if supportsConstant {
                        Button {
                            index = ImportService.CSVMappingConfig.constant
                        } label: {
                            Label(
                                String(localized: "csv_enter_value"),
                                systemImage: index == ImportService.CSVMappingConfig.constant ? "checkmark" : ""
                            )
                        }
                    }

                    if canSkip {
                        Button {
                            index = ImportService.CSVMappingConfig.notMapped
                        } label: {
                            Label(
                                String(localized: "csv_no_column"),
                                systemImage: index == ImportService.CSVMappingConfig.notMapped ? "checkmark" : ""
                            )
                        }
                    }
                } label: {
                    HStack(spacing: 4) {
                        Text(selectionLabel)
                            .font(.subheadline)
                            .foregroundColor(index == ImportService.CSVMappingConfig.notMapped ? .secondary : .appPrimary)
                        Image(systemName: "chevron.up.chevron.down")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                }
            }

            if index == ImportService.CSVMappingConfig.constant && supportsConstant {
                TextField(String(localized: "csv_enter_value"), text: $constant)
                    .textFieldStyle(.roundedBorder)
                    .font(.subheadline)
            }
        }
        .padding(.vertical, 2)
    }
}

// MARK: - Mapping Row With Constant (column, constant value, or skip)

private struct MappingRowWithConstant: View {
    let label: String
    @Binding var index: Int
    @Binding var constant: String
    let headers: [String]

    private var selectionLabel: String {
        if index == ImportService.CSVMappingConfig.constant {
            return constant.isEmpty ? String(localized: "csv_enter_value") : constant
        }
        if index == ImportService.CSVMappingConfig.notMapped {
            return String(localized: "csv_no_column")
        }
        return headers[safe: index] ?? "Column \(index + 1)"
    }

    var body: some View {
        VStack(alignment: .leading, spacing: 4) {
            HStack {
                Text(label)
                    .font(.subheadline)

                Spacer()

                Menu {
                    ForEach(Array(headers.enumerated()), id: \.offset) { i, h in
                        Button { index = i } label: {
                            Label(h, systemImage: index == i ? "checkmark" : "")
                        }
                    }
                    Divider()
                    Button {
                        index = ImportService.CSVMappingConfig.constant
                    } label: {
                        Label(
                            String(localized: "csv_enter_value"),
                            systemImage: index == ImportService.CSVMappingConfig.constant ? "checkmark" : ""
                        )
                    }
                    Button {
                        index = ImportService.CSVMappingConfig.notMapped
                    } label: {
                        Label(
                            String(localized: "csv_no_column"),
                            systemImage: index == ImportService.CSVMappingConfig.notMapped ? "checkmark" : ""
                        )
                    }
                } label: {
                    HStack(spacing: 4) {
                        Text(selectionLabel)
                            .font(.subheadline)
                            .foregroundColor(index == ImportService.CSVMappingConfig.notMapped ? .secondary : .appPrimary)
                        Image(systemName: "chevron.up.chevron.down")
                            .font(.caption2)
                            .foregroundColor(.secondary)
                    }
                }
            }

            if index == ImportService.CSVMappingConfig.constant {
                TextField(String(localized: "csv_enter_value"), text: $constant)
                    .textFieldStyle(.roundedBorder)
                    .font(.subheadline)
            }
        }
        .padding(.vertical, 2)
    }
}

// MARK: - Array safe subscript

private extension Array {
    subscript(safe index: Int) -> Element? {
        guard index >= 0, index < count else { return nil }
        return self[index]
    }
}
