import SwiftUI
import ComposeApp

struct DocumentDetailView: View {
    let documentId: Int32
    @StateObject private var viewModel: DocumentViewModelWrapper
    @Environment(\.dismiss) private var dismiss
    @State private var showDeleteAlert = false
    @State private var navigateToEdit = false
    @State private var showImageViewer = false
    @State private var selectedImageIndex = 0
    @State private var deleteSucceeded = false
    @State private var isDownloading = false
    @State private var downloadProgress: Double = 0
    @State private var downloadError: String?
    @State private var downloadedFileURL: URL?

    /// Default init used by the app. The VM is created with no
    /// pre-seeded detail state; `onAppear` calls `loadDocumentDetail(id:)`.
    init(documentId: Int32) {
        self.documentId = documentId
        self._viewModel = StateObject(wrappedValue: DocumentViewModelWrapper())
    }

    /// Snapshot-test / preview init that accepts a pre-seeded VM.
    /// Passing a VM built with `initialDocument: <fixture>` lets the
    /// view render populated state on the first composition frame,
    /// bypassing the APILayer round-trip that fails hermetically.
    init(documentId: Int32, viewModel: DocumentViewModelWrapper) {
        self.documentId = documentId
        self._viewModel = StateObject(wrappedValue: viewModel)
    }

    var body: some View {
        ZStack {
            // Prefer cached success state over loading so a pre-seeded
            // VM (snapshot tests/previews) renders content on the first
            // composition frame, and live views don't flash a spinner
            // over already-visible content during a background refresh.
            if let successState = viewModel.documentDetailState as? DocumentDetailStateSuccess {
                documentDetailContent(document: successState.document)
            } else if viewModel.documentDetailState is DocumentDetailStateLoading {
                ProgressView(L10n.Documents.loadingDocument)
            } else if let errorState = viewModel.documentDetailState as? DocumentDetailStateError {
                VStack(spacing: 16) {
                    Image(systemName: "exclamationmark.triangle")
                        .font(.system(size: 48))
                        .foregroundColor(Color.appError)
                    Text(errorState.message)
                        .foregroundColor(Color.appTextSecondary)
                    Button(L10n.Common.retry) {
                        viewModel.loadDocumentDetail(id: documentId)
                    }
                    .buttonStyle(.borderedProminent)
                }
            } else {
                EmptyView()
            }
        }
        .accessibilityIdentifier(AccessibilityIdentifiers.Document.detailView)
        .navigationTitle(L10n.Documents.documentDetails)
        .navigationBarTitleDisplayMode(.inline)
        .navigationDestination(isPresented: $navigateToEdit) {
            if let successState = viewModel.documentDetailState as? DocumentDetailStateSuccess {
                EditDocumentView(document: successState.document)
            } else {
                Color.clear.onAppear { navigateToEdit = false }
            }
        }
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                if viewModel.documentDetailState is DocumentDetailStateSuccess {
                    Menu {
                        Button {
                            navigateToEdit = true
                        } label: {
                            Label(L10n.Common.edit, systemImage: "pencil")
                        }
                        .accessibilityIdentifier(AccessibilityIdentifiers.Document.editButton)

                        Button(role: .destructive) {
                            showDeleteAlert = true
                        } label: {
                            Label(L10n.Common.delete, systemImage: "trash")
                        }
                        .accessibilityIdentifier(AccessibilityIdentifiers.Document.deleteButton)
                    } label: {
                        Image(systemName: "ellipsis.circle")
                            .accessibilityIdentifier(AccessibilityIdentifiers.Document.menuButton)
                    }
                    .accessibilityLabel("Document actions")
                }
            }
        }
        .onAppear {
            viewModel.loadDocumentDetail(id: documentId)
        }
        .alert(L10n.Documents.deleteDocument, isPresented: $showDeleteAlert) {
            Button(L10n.Common.cancel, role: .cancel) { }
            Button(L10n.Common.delete, role: .destructive) {
                viewModel.deleteDocument(id: documentId)
            }
        } message: {
            Text(L10n.Documents.deleteConfirmMessage)
        }
        .onReceive(viewModel.$deleteState) { newState in
            if newState is DeleteStateSuccess {
                deleteSucceeded = true
            }
        }
        .onChange(of: deleteSucceeded) { _, succeeded in
            if succeeded {
                dismiss()
            }
        }
        .fullScreenCover(isPresented: $showImageViewer) {
            if let successState = viewModel.documentDetailState as? DocumentDetailStateSuccess, !successState.document.images.isEmpty {
                ImageViewerSheet(
                    images: successState.document.images,
                    selectedIndex: $selectedImageIndex,
                    onDismiss: { showImageViewer = false }
                )
            } else {
                Color.clear.onAppear { showImageViewer = false }
            }
        }
        .sheet(isPresented: Binding(
            get: { downloadedFileURL != nil },
            set: { if !$0 { downloadedFileURL = nil } }
        )) {
            if let fileURL = downloadedFileURL {
                ShareSheet(activityItems: [fileURL])
            }
        }
    }

    // MARK: - Download File

    // FIX_SKIPPED: LE-4 — downloadFile() is an 80-line method performing direct URLSession
    // networking inside the view. Fixing requires extracting a dedicated DownloadViewModel
    // or DocumentDownloadManager — architectural refactor deferred.
    private func downloadFile(document: Document) {
        guard let fileUrl = document.fileUrl else {
            downloadError = "No file URL available"
            return
        }

        guard let token = TokenStorage.shared.getToken() else {
            downloadError = "Not authenticated"
            return
        }

        isDownloading = true
        downloadError = nil

        Task {
            do {
                // Build full URL
                let baseURL = ApiClient.shared.getMediaBaseUrl()
                let fullURLString = baseURL + fileUrl

                guard let url = URL(string: fullURLString) else {
                    await MainActor.run {
                        downloadError = "Invalid URL"
                        isDownloading = false
                    }
                    return
                }

                // Create authenticated request
                var request = URLRequest(url: url)
                request.setValue("Token \(token)", forHTTPHeaderField: "Authorization")

                // Download the file
                let (tempURL, response) = try await URLSession.shared.download(for: request)

                // Check response status
                if let httpResponse = response as? HTTPURLResponse {
                    guard (200...299).contains(httpResponse.statusCode) else {
                        await MainActor.run {
                            downloadError = "Download failed: HTTP \(httpResponse.statusCode)"
                            isDownloading = false
                        }
                        return
                    }
                }

                // Determine filename
                // Extract extension from fileName (e.g., "doc.pdf" -> "pdf") or mimeType (e.g., "application/pdf" -> "pdf")
                let ext: String = {
                    if let fn = document.fileName, let dotIndex = fn.lastIndex(of: ".") {
                        return String(fn[fn.index(after: dotIndex)...])
                    }
                    if let mime = document.mimeType, let slashIndex = mime.lastIndex(of: "/") {
                        return String(mime[mime.index(after: slashIndex)...])
                    }
                    return "file"
                }()
                let filename = document.title.replacingOccurrences(of: " ", with: "_") + "." + ext

                // Move to a permanent location
                let documentsPath = FileManager.default.temporaryDirectory
                let destinationURL = documentsPath.appendingPathComponent(filename)

                // Remove existing file if present
                try? FileManager.default.removeItem(at: destinationURL)

                // Move downloaded file
                try FileManager.default.moveItem(at: tempURL, to: destinationURL)

                await MainActor.run {
                    downloadedFileURL = destinationURL
                    isDownloading = false
                }

            } catch {
                await MainActor.run {
                    downloadError = "Download failed: \(error.localizedDescription)"
                    isDownloading = false
                }
            }
        }
    }

    @ViewBuilder
    private func documentDetailContent(document: Document) -> some View {
        ScrollView {
            VStack(spacing: OrganicSpacing.comfortable) {
                // Status Badge (for warranties)
                if document.documentType == "warranty" {
                    warrantyStatusCard(document: document)
                }

                // Basic Information
                VStack(alignment: .leading, spacing: 12) {
                    sectionHeader(L10n.Documents.basicInformation)

                    detailRow(label: L10n.Documents.titleField, value: document.title)
                    detailRow(label: L10n.Documents.documentType, value: DocumentTypeHelper.displayName(for: document.documentType))

                    if let category = document.category {
                        detailRow(label: L10n.Documents.category, value: DocumentCategoryHelper.displayName(for: category))
                    }

                    if let description = document.description_, !description.isEmpty {
                        detailRow(label: L10n.Documents.description, value: description)
                    }
                }
                .padding()
                .background(Color.appBackgroundSecondary)
                .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                .naturalShadow(.subtle)

                // Warranty/Item Details
                if document.documentType == "warranty" {
                    if document.itemName != nil || document.modelNumber != nil ||
                       document.serialNumber != nil || document.provider != nil {
                        VStack(alignment: .leading, spacing: 12) {
                            sectionHeader(L10n.Documents.itemDetails)

                            if let itemName = document.itemName {
                                detailRow(label: L10n.Documents.itemName, value: itemName)
                            }
                            if let modelNumber = document.modelNumber {
                                detailRow(label: L10n.Documents.modelNumber, value: modelNumber)
                            }
                            if let serialNumber = document.serialNumber {
                                detailRow(label: L10n.Documents.serialNumber, value: serialNumber)
                            }
                            if let provider = document.provider {
                                detailRow(label: L10n.Documents.provider, value: provider)
                            }
                            if let providerContact = document.providerContact {
                                detailRow(label: L10n.Documents.providerContact, value: providerContact)
                            }
                        }
                        .padding()
                        .background(Color.appBackgroundSecondary)
                        .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                        .naturalShadow(.subtle)
                    }

                    // Claim Information
                    if document.claimPhone != nil || document.claimEmail != nil ||
                       document.claimWebsite != nil {
                        VStack(alignment: .leading, spacing: 12) {
                            sectionHeader(L10n.Documents.claimInformation)

                            if let claimPhone = document.claimPhone {
                                detailRow(label: L10n.Documents.claimPhone, value: claimPhone)
                            }
                            if let claimEmail = document.claimEmail {
                                detailRow(label: L10n.Documents.claimEmail, value: claimEmail)
                            }
                            if let claimWebsite = document.claimWebsite {
                                detailRow(label: L10n.Documents.claimWebsite, value: claimWebsite)
                            }
                        }
                        .padding()
                        .background(Color.appBackgroundSecondary)
                        .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                        .naturalShadow(.subtle)
                    }

                    // Dates
                    if document.purchaseDate != nil || document.startDate != nil ||
                       document.endDate != nil {
                        VStack(alignment: .leading, spacing: 12) {
                            sectionHeader(L10n.Documents.importantDates)

                            if let purchaseDate = document.purchaseDate {
                                detailRow(label: L10n.Documents.purchaseDate, value: DateUtils.formatDateMedium(purchaseDate))
                            }
                            if let startDate = document.startDate {
                                detailRow(label: L10n.Documents.startDate, value: DateUtils.formatDateMedium(startDate))
                            }
                            if let endDate = document.endDate {
                                detailRow(label: L10n.Documents.endDate, value: DateUtils.formatDateMedium(endDate))
                            }
                        }
                        .padding()
                        .background(Color.appBackgroundSecondary)
                        .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                        .naturalShadow(.subtle)
                    }
                }

                // Images
                if !document.images.isEmpty {
                    VStack(alignment: .leading, spacing: 12) {
                        sectionHeader("\(L10n.Documents.images) (\(document.images.count))")

                        LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())], spacing: 8) {
                            ForEach(Array(document.images.prefix(6).enumerated()), id: \.element.id) { index, image in
                                ZStack(alignment: .center) {
                                    AuthenticatedImage(mediaURL: image.mediaUrl, contentMode: .fill)
                                        .frame(height: 100)
                                        .clipped()
                                        .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
                                        .onTapGesture {
                                            selectedImageIndex = index
                                            showImageViewer = true
                                        }

                                    if index == 5 && document.images.count > 6 {
                                        RoundedRectangle(cornerRadius: 12, style: .continuous)
                                            .fill(Color.black.opacity(0.6))
                                        Text("+\(document.images.count - 6)")
                                            .foregroundColor(.white)
                                            .font(.title2)
                                            .fontWeight(.bold)
                                    }
                                }
                            }
                        }
                    }
                    .padding()
                    .background(Color.appBackgroundSecondary)
                    .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                    .naturalShadow(.subtle)
                }

                // Associations
                VStack(alignment: .leading, spacing: 12) {
                    sectionHeader(L10n.Documents.associations)

                    if let residenceId = document.residenceId {
                        detailRow(label: L10n.Documents.residence, value: "Residence #\(residenceId)")
                    }
                    if let taskId = document.taskId {
                        detailRow(label: "Task", value: "Task #\(taskId)")
                    }
                }
                .padding()
                .background(Color.appBackgroundSecondary)
                .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                .naturalShadow(.subtle)

                // Additional Information
                if document.tags != nil || document.notes != nil {
                    VStack(alignment: .leading, spacing: 12) {
                        sectionHeader(L10n.Documents.additionalInformation)

                        if let tags = document.tags, !tags.isEmpty {
                            detailRow(label: L10n.Documents.tags, value: tags)
                        }
                        if let notes = document.notes, !notes.isEmpty {
                            detailRow(label: L10n.Documents.notes, value: notes)
                        }
                    }
                    .padding()
                    .background(Color.appBackgroundSecondary)
                    .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                    .naturalShadow(.subtle)
                }

                // File Information
                if document.fileUrl != nil {
                    VStack(alignment: .leading, spacing: 12) {
                        sectionHeader(L10n.Documents.attachedFile)

                        if let mimeType = document.mimeType {
                            detailRow(label: L10n.Documents.fileType, value: mimeType)
                        }
                        if let fileSize = document.fileSize {
                            detailRow(label: L10n.Documents.fileSize, value: formatFileSize(bytes: Int(fileSize)))
                        }

                        Button(action: {
                            downloadFile(document: document)
                        }) {
                            HStack {
                                if isDownloading {
                                    ProgressView()
                                        .tint(Color.appTextOnPrimary)
                                        .scaleEffect(0.8)
                                    Text("Downloading...")
                                } else {
                                    Image(systemName: "arrow.down.circle")
                                    Text(L10n.Documents.downloadFile)
                                }
                            }
                            .frame(maxWidth: .infinity)
                            .padding()
                            .background(isDownloading ? Color.appPrimary.opacity(0.7) : Color.appPrimary)
                            .foregroundColor(Color.appTextOnPrimary)
                            .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
                        }
                        .disabled(isDownloading)

                        if let error = downloadError {
                            Text(error)
                                .font(.caption)
                                .foregroundColor(Color.appError)
                        }
                    }
                    .padding()
                    .background(Color.appBackgroundSecondary)
                    .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                    .naturalShadow(.subtle)
                }

                // Metadata
                VStack(alignment: .leading, spacing: 12) {
                    sectionHeader(L10n.Documents.metadata)

                    if let createdBy = document.createdBy {
                        let name = [createdBy.firstName, createdBy.lastName].filter { !$0.isEmpty }.joined(separator: " ")
                        detailRow(label: L10n.Documents.uploadedBy, value: name.isEmpty ? createdBy.username : name)
                    }
                    if let createdAt = document.createdAt {
                        detailRow(label: L10n.Documents.created, value: DateUtils.formatDateTime(createdAt))
                    }
                    if let updatedAt = document.updatedAt {
                        detailRow(label: L10n.Documents.updated, value: DateUtils.formatDateTime(updatedAt))
                    }
                }
                .padding()
                .background(Color.appBackgroundSecondary)
                .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
                .naturalShadow(.subtle)
            }
            .padding()
        }
        .background(WarmGradientBackground())
    }

    @ViewBuilder
    private func warrantyStatusCard(document: Document) -> some View {
        let daysUntilExpiration = document.daysUntilExpiration?.int32Value ?? 0
        let statusColor = getStatusColor(isActive: document.isActive, daysUntilExpiration: daysUntilExpiration)
        let statusText = getStatusText(isActive: document.isActive, daysUntilExpiration: daysUntilExpiration)

        HStack {
            VStack(alignment: .leading, spacing: 4) {
                Text(L10n.Documents.status)
                    .font(.system(size: 12, weight: .medium))
                    .foregroundColor(Color.appTextSecondary)
                Text(statusText)
                    .font(.system(size: 20, weight: .bold, design: .rounded))
                    .foregroundColor(statusColor)
            }

            Spacer()

            if document.isActive && daysUntilExpiration >= 0 {
                VStack(alignment: .trailing, spacing: 4) {
                    Text(L10n.Documents.daysRemaining)
                        .font(.system(size: 12, weight: .medium))
                        .foregroundColor(Color.appTextSecondary)
                    Text("\(daysUntilExpiration)")
                        .font(.system(size: 20, weight: .bold, design: .rounded))
                        .foregroundColor(statusColor)
                }
            }
        }
        .padding()
        .background(statusColor.opacity(0.12))
        .clipShape(RoundedRectangle(cornerRadius: 16, style: .continuous))
    }

    @ViewBuilder
    private func sectionHeader(_ title: String) -> some View {
        Text(title)
            .font(.system(size: 16, weight: .bold, design: .rounded))
            .foregroundColor(Color.appTextPrimary)
            .accessibilityAddTraits(.isHeader)
    }

    @ViewBuilder
    private func detailRow(label: String, value: String) -> some View {
        VStack(alignment: .leading, spacing: 4) {
            Text(label)
                .font(.system(size: 12, weight: .medium))
                .foregroundColor(Color.appTextSecondary)
            Text(value)
                .font(.system(size: 15, weight: .medium))
                .foregroundColor(Color.appTextPrimary)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(14)
        .background(Color.appBackgroundPrimary.opacity(0.5))
        .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
    }

    private func getStatusColor(isActive: Bool, daysUntilExpiration: Int32) -> Color {
        if !isActive {
            return Color.appTextSecondary
        } else if daysUntilExpiration < 0 {
            return Color.appError
        } else if daysUntilExpiration < 30 {
            return Color.appAccent
        } else if daysUntilExpiration < 90 {
            return Color.appAccent.opacity(0.8)
        } else {
            return Color.appPrimary
        }
    }

    private func getStatusText(isActive: Bool, daysUntilExpiration: Int32) -> String {
        if !isActive {
            return L10n.Documents.inactive
        } else if daysUntilExpiration < 0 {
            return L10n.Documents.expired
        } else if daysUntilExpiration < 30 {
            return L10n.Documents.expiringSoon
        } else {
            return L10n.Documents.activeStatus
        }
    }

    private func formatFileSize(bytes: Int) -> String {
        let formatter = ByteCountFormatter()
        formatter.allowedUnits = [.useAll]
        formatter.countStyle = .file
        return formatter.string(fromByteCount: Int64(bytes))
    }
}

// MARK: - Share Sheet

struct ShareSheet: UIViewControllerRepresentable {
    let activityItems: [Any]
    var applicationActivities: [UIActivity]? = nil

    func makeUIViewController(context: Context) -> UIActivityViewController {
        UIActivityViewController(
            activityItems: activityItems,
            applicationActivities: applicationActivities
        )
    }

    func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {}
}
