import SwiftUI
import ComposeApp

struct ContractorDetailView: View {
    @Environment(\.dismiss) private var dismiss
    @Environment(\.openURL) private var openURL
    @StateObject private var viewModel: ContractorViewModel
    @StateObject private var residenceViewModel = ResidenceViewModel()

    let contractorId: Int32

    @State private var showingEditSheet = false
    @State private var showingDeleteAlert = false
    @State private var shareFileURL: URL?
    @State private var showingUpgradePrompt = false
    @StateObject private var subscriptionCache = SubscriptionCacheWrapper.shared

    /// Default init used by the app. The ViewModel is created with no
    /// pre-seeded detail state; `onAppear` calls `loadContractorDetail(id:)`
    /// which populates `selectedContractor` via APILayer.
    init(contractorId: Int32) {
        self.contractorId = contractorId
        self._viewModel = StateObject(wrappedValue: ContractorViewModel())
    }

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

    var body: some View {
        ZStack {
            WarmGradientBackground()
            contentStateView
        }
        .accessibilityIdentifier(AccessibilityIdentifiers.Contractor.detailView)
        .onAppear {
            residenceViewModel.loadMyResidences()
        }
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .navigationBarTrailing) {
                if let contractor = viewModel.selectedContractor {
                    Menu {
                        Button(action: {
                            if subscriptionCache.canShareContractor() {
                                shareContractor(contractor)
                            } else {
                                showingUpgradePrompt = true
                            }
                        }) {
                            Label(L10n.Common.share, systemImage: "square.and.arrow.up")
                        }

                        Button(action: { viewModel.toggleFavorite(id: contractorId) { _ in
                            viewModel.loadContractorDetail(id: contractorId)
                        }}) {
                            Label(
                                contractor.isFavorite ? L10n.Contractors.removeFromFavorites : L10n.Contractors.addToFavorites,
                                systemImage: contractor.isFavorite ? "star.slash" : "star"
                            )
                        }

                        Button(action: { showingEditSheet = true }) {
                            Label(L10n.Common.edit, systemImage: "pencil")
                        }
                        .accessibilityIdentifier(AccessibilityIdentifiers.Contractor.editButton)

                        Divider()

                        Button(role: .destructive, action: { showingDeleteAlert = true }) {
                            Label(L10n.Common.delete, systemImage: "trash")
                        }
                        .accessibilityIdentifier(AccessibilityIdentifiers.Contractor.deleteButton)
                    } label: {
                        Image(systemName: "ellipsis.circle")
                            .foregroundColor(Color.appPrimary)
                            .accessibilityIdentifier(AccessibilityIdentifiers.Contractor.menuButton)
                    }
                    .accessibilityLabel("Contractor actions")
                }
            }
        }
        .sheet(isPresented: Binding(
            get: { shareFileURL != nil },
            set: { if !$0 { shareFileURL = nil } }
        )) {
            if let url = shareFileURL {
                ShareSheet(activityItems: [url])
            }
        }
        .sheet(isPresented: $showingUpgradePrompt) {
            UpgradePromptView(triggerKey: "share_contractor", isPresented: $showingUpgradePrompt)
        }
        .sheet(isPresented: $showingEditSheet) {
            ContractorFormSheet(
                contractor: viewModel.selectedContractor,
                onSave: {
                    viewModel.loadContractorDetail(id: contractorId)
                }
            )
            .presentationDetents([.large])
        }
        .alert(L10n.Contractors.deleteConfirm, isPresented: $showingDeleteAlert) {
            Button(L10n.Common.cancel, role: .cancel) {}
            Button(L10n.Common.delete, role: .destructive) {
                deleteContractor()
            }
        } message: {
            Text(L10n.Contractors.deleteMessage)
        }
        .onAppear {
            viewModel.loadContractorDetail(id: contractorId)
        }
        .handleErrors(
            error: viewModel.errorMessage,
            onRetry: { viewModel.loadContractorDetail(id: contractorId) }
        )
    }

    private func deleteContractor() {
        viewModel.deleteContractor(id: contractorId) { success in
            if success {
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                    dismiss()
                }
            }
        }
    }

    private func shareContractor(_ contractor: Contractor) {
        if let url = ContractorSharingManager.shared.createShareableFile(contractor: contractor) {
            shareFileURL = url
        }
    }

    // MARK: - Content State View

    @ViewBuilder
    private var contentStateView: some View {
        // Prefer showing the cached contractor over the loading/error
        // states: if `selectedContractor` is populated (including from a
        // pre-seeded ViewModel in snapshot tests/previews), render it
        // even while a background refresh is in flight. This avoids
        // briefly flashing a spinner over existing content when the
        // view reappears, and makes the pre-seeded test path render
        // populated on the first composition frame.
        if let contractor = viewModel.selectedContractor {
            contractorScrollView(contractor: contractor)
        } else if viewModel.isLoading {
            ProgressView()
                .scaleEffect(1.2)
        } else if let error = viewModel.errorMessage {
            ErrorView(message: error) {
                viewModel.loadContractorDetail(id: contractorId)
            }
        }
    }

    // MARK: - Main Scroll View

    @ViewBuilder
    private func contractorScrollView(contractor: Contractor) -> some View {
        ScrollView {
            VStack(spacing: AppSpacing.lg) {
                headerCard(contractor: contractor)
                quickActionsView(contractor: contractor)
                contactInfoSection(contractor: contractor)
                addressSection(contractor: contractor)
                residenceSection(residenceId: (contractor.residenceId as? Int32))
                notesSection(notes: contractor.notes)
                statisticsSection(contractor: contractor)
                metadataSection(contractor: contractor)
            }
            .padding(AppSpacing.md)
        }
    }

    // MARK: - Header Card

    @ViewBuilder
    private func headerCard(contractor: Contractor) -> some View {
        VStack(spacing: AppSpacing.md) {
            // Avatar
            ZStack {
                Circle()
                    .fill(Color.appPrimary.opacity(0.1))
                    .frame(width: 80, height: 80)

                Image(systemName: "person.fill")
                    .font(.system(size: 40))
                    .foregroundColor(Color.appPrimary)
            }

            // Name
            Text(contractor.name)
                .font(.title3.weight(.semibold))
                .foregroundColor(Color.appTextPrimary)
                .accessibilityAddTraits(.isHeader)

            // Company
            if let company = contractor.company {
                Text(company)
                    .font(.title3.weight(.semibold))
                    .foregroundColor(Color.appTextSecondary)
            }

            // Specialties Badges
            specialtiesBadges(contractor: contractor)

            // Rating
            ratingView(contractor: contractor)
        }
        .padding(AppSpacing.lg)
        .frame(maxWidth: .infinity)
        .background(Color.appBackgroundSecondary)
        .cornerRadius(AppRadius.lg)
        .shadow(color: AppShadow.sm.color, radius: AppShadow.sm.radius, x: AppShadow.sm.x, y: AppShadow.sm.y)
    }

    @ViewBuilder
    private func specialtiesBadges(contractor: Contractor) -> some View {
        if !contractor.specialties.isEmpty {
            FlowLayout(spacing: AppSpacing.xs) {
                ForEach(contractor.specialties, id: \.id) { specialty in
                    HStack(spacing: AppSpacing.xxs) {
                        Image(systemName: "wrench.and.screwdriver")
                            .font(.caption)
                        Text(specialty.name)
                            .font(.body)
                    }
                    .padding(.horizontal, AppSpacing.sm)
                    .padding(.vertical, AppSpacing.xxs)
                    .background(Color.appPrimary.opacity(0.1))
                    .foregroundColor(Color.appPrimary)
                    .cornerRadius(AppRadius.full)
                }
            }
        }
    }

    @ViewBuilder
    private func ratingView(contractor: Contractor) -> some View {
        if let rating = contractor.rating, rating.doubleValue > 0 {
            HStack(spacing: AppSpacing.xxs) {
                ForEach(0..<5) { index in
                    Image(systemName: index < Int(rating.doubleValue) ? "star.fill" : "star")
                        .foregroundColor(Color.appAccent)
                        .font(.caption)
                }
                Text(String(format: "%.1f", rating.doubleValue))
                    .font(.title3.weight(.semibold))
                    .foregroundColor(Color.appTextPrimary)
            }

            if contractor.taskCount > 0 {
                Text(String(format: L10n.Contractors.completedTasks, contractor.taskCount))
                    .font(.callout)
                    .foregroundColor(Color.appTextSecondary)
            }
        }
    }

    // MARK: - Quick Actions

    @ViewBuilder
    private func quickActionsView(contractor: Contractor) -> some View {
        let hasPhone = !(contractor.phone?.isEmpty ?? true)
        let hasEmail = !(contractor.email?.isEmpty ?? true)
        let hasWebsite = !(contractor.website?.isEmpty ?? true)
        let hasAddress = !(contractor.streetAddress?.isEmpty ?? true) ||
                         !(contractor.city?.isEmpty ?? true)

        if hasPhone || hasEmail || hasWebsite || hasAddress {
            HStack(spacing: AppSpacing.sm) {
                phoneQuickAction(phone: contractor.phone)
                emailQuickAction(email: contractor.email)
                websiteQuickAction(website: contractor.website)
                directionsQuickAction(contractor: contractor)
            }
        }
    }

    @ViewBuilder
    private func phoneQuickAction(phone: String?) -> some View {
        if let phone = phone, !phone.isEmpty {
            QuickActionButton(
                icon: "phone.fill",
                label: L10n.Contractors.callAction,
                color: Color.appPrimary
            ) {
                if let url = URL(string: "tel:\(phone.replacingOccurrences(of: " ", with: ""))") {
                    openURL(url)
                }
            }
        }
    }

    @ViewBuilder
    private func emailQuickAction(email: String?) -> some View {
        if let email = email, !email.isEmpty {
            QuickActionButton(
                icon: "envelope.fill",
                label: L10n.Contractors.emailAction,
                color: Color.appSecondary
            ) {
                if let url = URL(string: "mailto:\(email)") {
                    openURL(url)
                }
            }
        }
    }

    @ViewBuilder
    private func websiteQuickAction(website: String?) -> some View {
        if let website = website, !website.isEmpty {
            QuickActionButton(
                icon: "safari.fill",
                label: L10n.Contractors.websiteAction,
                color: Color.appAccent
            ) {
                var urlString = website
                if !urlString.hasPrefix("http://") && !urlString.hasPrefix("https://") {
                    urlString = "https://\(urlString)"
                }
                if let url = URL(string: urlString) {
                    openURL(url)
                }
            }
        }
    }

    @ViewBuilder
    private func directionsQuickAction(contractor: Contractor) -> some View {
        let hasAddress = !(contractor.streetAddress?.isEmpty ?? true) ||
                         !(contractor.city?.isEmpty ?? true)
        if hasAddress {
            QuickActionButton(
                icon: "map.fill",
                label: L10n.Contractors.directionsAction,
                color: Color.appError
            ) {
                let address = [
                    contractor.streetAddress,
                    contractor.city,
                    contractor.stateProvince,
                    contractor.postalCode
                ].compactMap { $0 }.filter { !$0.isEmpty }.joined(separator: ", ")

                if let encoded = address.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
                   let url = URL(string: "maps://?address=\(encoded)") {
                    openURL(url)
                }
            }
        }
    }

    // MARK: - Contact Information Section

    @ViewBuilder
    private func contactInfoSection(contractor: Contractor) -> some View {
        let hasPhone = !(contractor.phone?.isEmpty ?? true)
        let hasEmail = !(contractor.email?.isEmpty ?? true)
        let hasWebsite = !(contractor.website?.isEmpty ?? true)

        if hasPhone || hasEmail || hasWebsite {
            DetailSection(title: L10n.Contractors.contactInfoSection) {
                phoneContactRow(phone: contractor.phone)
                emailContactRow(email: contractor.email)
                websiteContactRow(website: contractor.website)
            }
        }
    }

    @ViewBuilder
    private func phoneContactRow(phone: String?) -> some View {
        if let phone = phone, !phone.isEmpty {
            ContactDetailRow(
                icon: "phone.fill",
                label: L10n.Contractors.phoneLabel,
                value: phone,
                iconColor: Color.appPrimary
            ) {
                if let url = URL(string: "tel:\(phone.replacingOccurrences(of: " ", with: ""))") {
                    openURL(url)
                }
            }
        }
    }

    @ViewBuilder
    private func emailContactRow(email: String?) -> some View {
        if let email = email, !email.isEmpty {
            ContactDetailRow(
                icon: "envelope.fill",
                label: L10n.Contractors.emailLabel,
                value: email,
                iconColor: Color.appSecondary
            ) {
                if let url = URL(string: "mailto:\(email)") {
                    openURL(url)
                }
            }
        }
    }

    @ViewBuilder
    private func websiteContactRow(website: String?) -> some View {
        if let website = website, !website.isEmpty {
            ContactDetailRow(
                icon: "safari.fill",
                label: L10n.Contractors.websiteLabel,
                value: website,
                iconColor: Color.appAccent
            ) {
                var urlString = website
                if !urlString.hasPrefix("http://") && !urlString.hasPrefix("https://") {
                    urlString = "https://\(urlString)"
                }
                if let url = URL(string: urlString) {
                    openURL(url)
                }
            }
        }
    }

    // MARK: - Address Section

    @ViewBuilder
    private func addressSection(contractor: Contractor) -> some View {
        let hasStreet = !(contractor.streetAddress?.isEmpty ?? true)
        let hasCity = !(contractor.city?.isEmpty ?? true)

        if hasStreet || hasCity {
            let addressComponents = [
                contractor.streetAddress,
                [contractor.city, contractor.stateProvince].compactMap { $0 }.filter { !$0.isEmpty }.joined(separator: ", "),
                contractor.postalCode
            ].compactMap { $0 }.filter { !$0.isEmpty }

            if !addressComponents.isEmpty {
                DetailSection(title: L10n.Contractors.addressSection) {
                    addressButton(contractor: contractor, addressComponents: addressComponents)
                }
            }
        }
    }

    @ViewBuilder
    private func addressButton(contractor: Contractor, addressComponents: [String]) -> some View {
        let fullAddress = addressComponents.joined(separator: "\n")
        Button {
            let address = [
                contractor.streetAddress,
                contractor.city,
                contractor.stateProvince,
                contractor.postalCode
            ].compactMap { $0 }.filter { !$0.isEmpty }.joined(separator: ", ")

            if let encoded = address.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
               let url = URL(string: "maps://?address=\(encoded)") {
                openURL(url)
            }
        } label: {
            HStack(alignment: .top, spacing: AppSpacing.sm) {
                Image(systemName: "mappin.circle.fill")
                    .foregroundColor(Color.appError)
                    .frame(width: 20)

                VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                    Text(L10n.Contractors.locationLabel)
                        .font(.caption.weight(.medium))
                        .foregroundColor(Color.appTextSecondary)

                    Text(fullAddress)
                        .font(.body)
                        .foregroundColor(Color.appTextPrimary)
                        .multilineTextAlignment(.leading)
                }

                Spacer()

                Image(systemName: "arrow.up.right.square")
                    .font(.caption)
                    .foregroundColor(Color.appTextSecondary)
            }
            .padding(AppSpacing.md)
        }
    }

    // MARK: - Residence Section

    @ViewBuilder
    private func residenceSection(residenceId: Int32?) -> some View {
        if let residenceId = residenceId {
            DetailSection(title: L10n.Contractors.associatedPropertySection) {
                HStack(spacing: AppSpacing.sm) {
                    Image("outline")
                        .renderingMode(.template)
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 18, height: 18)
                        .foregroundColor(Color.appPrimary)

                    VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                        Text(L10n.Contractors.propertyLabel)
                            .font(.caption.weight(.medium))
                            .foregroundColor(Color.appTextSecondary)

                        if let residence = residenceViewModel.myResidences?.residences.first(where: { $0.id == residenceId }) {
                            Text(residence.name)
                                .font(.body)
                                .foregroundColor(Color.appTextPrimary)
                        } else {
                            Text("Property #\(residenceId)")
                                .font(.body)
                                .foregroundColor(Color.appTextPrimary)
                        }
                    }

                    Spacer()
                }
                .padding(AppSpacing.md)
            }
        }
    }

    // MARK: - Notes Section

    @ViewBuilder
    private func notesSection(notes: String?) -> some View {
        if let notes = notes, !notes.isEmpty {
            DetailSection(title: L10n.Contractors.notesSection) {
                HStack(alignment: .top, spacing: AppSpacing.sm) {
                    Image(systemName: "note.text")
                        .foregroundColor(Color.appAccent)
                        .frame(width: 20)

                    Text(notes)
                        .font(.body)
                        .foregroundColor(Color.appTextPrimary)
                        .frame(maxWidth: .infinity, alignment: .leading)
                }
                .padding(AppSpacing.md)
            }
        }
    }

    // MARK: - Statistics Section

    @ViewBuilder
    private func statisticsSection(contractor: Contractor) -> some View {
        DetailSection(title: L10n.Contractors.statisticsSection) {
            HStack(spacing: AppSpacing.lg) {
                StatCard(
                    icon: "checkmark.circle.fill",
                    value: "\(contractor.taskCount)",
                    label: L10n.Contractors.tasksCompletedLabel,
                    color: Color.appPrimary
                )

                if let rating = contractor.rating, rating.doubleValue > 0 {
                    StatCard(
                        icon: "star.fill",
                        value: String(format: "%.1f", rating.doubleValue),
                        label: L10n.Contractors.averageRatingLabel,
                        color: Color.appAccent
                    )
                }
            }
            .padding(AppSpacing.md)
        }
    }

    // MARK: - Metadata Section

    @ViewBuilder
    private func metadataSection(contractor: Contractor) -> some View {
        DetailSection(title: L10n.Contractors.infoSection) {
            VStack(spacing: 0) {
                createdByRow(createdBy: contractor.createdBy)
                memberSinceRow(createdAt: contractor.createdAt)
            }
        }
    }

    @ViewBuilder
    private func createdByRow(createdBy: ContractorUser?) -> some View {
        if let createdBy = createdBy {
            HStack(spacing: AppSpacing.sm) {
                Image(systemName: "person.badge.plus")
                    .foregroundColor(Color.appTextSecondary)
                    .frame(width: 20)

                VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                    Text(L10n.Contractors.addedByLabel)
                        .font(.caption.weight(.medium))
                        .foregroundColor(Color.appTextSecondary)

                    Text(createdBy.username)
                        .font(.body)
                        .foregroundColor(Color.appTextPrimary)
                }

                Spacer()
            }
            .padding(AppSpacing.md)

            Divider()
                .padding(.horizontal, AppSpacing.md)
        }
    }

    @ViewBuilder
    private func memberSinceRow(createdAt: String) -> some View {
        HStack(spacing: AppSpacing.sm) {
            Image(systemName: "calendar.badge.plus")
                .foregroundColor(Color.appTextSecondary)
                .frame(width: 20)

            VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                Text(L10n.Contractors.memberSinceLabel)
                    .font(.caption.weight(.medium))
                    .foregroundColor(Color.appTextSecondary)

                Text(DateUtils.formatDateMedium(createdAt))
                    .font(.body)
                    .foregroundColor(Color.appTextPrimary)
            }

            Spacer()
        }
        .padding(AppSpacing.md)
    }
}

// MARK: - Detail Section
struct DetailSection<Content: View>: View {
    let title: String
    @ViewBuilder let content: () -> Content

    var body: some View {
        VStack(alignment: .leading, spacing: AppSpacing.sm) {
            Text(title)
                .font(.headline)
                .foregroundColor(Color.appTextPrimary)
                .padding(.horizontal, AppSpacing.md)

            VStack(spacing: 0) {
                content()
            }
            .background(Color.appBackgroundSecondary)
            .cornerRadius(AppRadius.lg)
            .shadow(color: AppShadow.sm.color, radius: AppShadow.sm.radius, x: AppShadow.sm.x, y: AppShadow.sm.y)
        }
    }
}

// MARK: - Detail Row
struct DetailRow: View {
    let icon: String
    let label: String
    let value: String
    var iconColor: Color = Color(.secondaryLabel)

    var body: some View {
        HStack(alignment: .top, spacing: AppSpacing.sm) {
            Image(systemName: icon)
                .foregroundColor(iconColor)
                .frame(width: 20)

            VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                Text(label)
                    .font(.caption.weight(.medium))
                    .foregroundColor(Color.appTextSecondary)

                Text(value)
                    .font(.body)
                    .foregroundColor(Color.appTextPrimary)
            }

            Spacer()
        }
        .padding(AppSpacing.md)
    }
}

// MARK: - Quick Action Button
struct QuickActionButton: View {
    let icon: String
    let label: String
    let color: Color
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            VStack(spacing: AppSpacing.xs) {
                ZStack {
                    Circle()
                        .fill(color.opacity(0.1))
                        .frame(width: 50, height: 50)

                    Image(systemName: icon)
                        .font(.system(size: 20, weight: .semibold))
                        .foregroundColor(color)
                }

                Text(label)
                    .font(.caption.weight(.medium))
                    .foregroundColor(Color.appTextSecondary)
            }
            .frame(maxWidth: .infinity)
            .padding(.vertical, AppSpacing.sm)
            .background(Color.appBackgroundSecondary)
            .cornerRadius(AppRadius.md)
        }
    }
}

// MARK: - Contact Detail Row (Clickable)
struct ContactDetailRow: View {
    let icon: String
    let label: String
    let value: String
    var iconColor: Color = Color(.secondaryLabel)
    let action: () -> Void

    var body: some View {
        Button(action: action) {
            HStack(alignment: .top, spacing: AppSpacing.sm) {
                Image(systemName: icon)
                    .foregroundColor(iconColor)
                    .frame(width: 20)

                VStack(alignment: .leading, spacing: AppSpacing.xxs) {
                    Text(label)
                        .font(.caption.weight(.medium))
                        .foregroundColor(Color.appTextSecondary)

                    Text(value)
                        .font(.body)
                        .foregroundColor(Color.appPrimary)
                }

                Spacer()

                Image(systemName: "arrow.up.right.square")
                    .font(.caption)
                    .foregroundColor(Color.appTextSecondary)
            }
            .padding(AppSpacing.md)
        }
    }
}

// MARK: - Stat Card
struct StatCard: View {
    let icon: String
    let value: String
    let label: String
    let color: Color

    var body: some View {
        VStack(spacing: AppSpacing.xs) {
            ZStack {
                Circle()
                    .fill(color.opacity(0.1))
                    .frame(width: 44, height: 44)

                Image(systemName: icon)
                    .font(.system(size: 20))
                    .foregroundColor(color)
            }

            Text(value)
                .font(.title2.weight(.bold))
                .foregroundColor(Color.appTextPrimary)

            Text(label)
                .font(.caption)
                .foregroundColor(Color.appTextSecondary)
                .multilineTextAlignment(.center)
        }
        .frame(maxWidth: .infinity)
    }
}
