//
//  WildPhotographerReportViewModels.swift
//  suixinkan
//

import Foundation
import MapKit
import UIKit

/// 举报摄影师首页 ViewModel，持有 Mock 举报数据并供子页面共享。
final class WildPhotographerReportHomeViewModel {
    private(set) var pageState: WildReportPageState = .normal
    private(set) var reports: [WildReportRecord] = []
    private(set) var riskPoints: [WildReportRiskPoint] = []
    private(set) var supplementaryEvidenceMap: [String: [WildReportSupplementaryEvidence]] = [:]

    var onStateChange: (() -> Void)?

    private var nextSequence = 0
    private var nextSupplementSequence = 0

    init() {
        resetDemoData(notify: false)
    }

    var emptyTitle: String { "暂无举报服务" }
    var emptyMessage: String { "当前景区暂未开放举报摄影师演示入口。" }

    /// 恢复演示数据并回到正常状态。
    func restoreDemoData() {
        resetDemoData(notify: false)
        pageState = .normal
        notifyStateChange()
    }

    /// 模拟错误后重新加载。
    func retryLoadAfterError() {
        pageState = .loading
        notifyStateChange()
        Task {
            try? await Task.sleep(nanoseconds: 450_000_000)
            pageState = .normal
            notifyStateChange()
        }
    }

    /// 切换页面演示状态。
    func setPageState(_ state: WildReportPageState) {
        pageState = state
        notifyStateChange()
    }

    /// 提交举报并写入 Mock 列表，返回新记录。
    @discardableResult
    func submitReport(
        reportType: WildReportType,
        description: String,
        location: String,
        contact: String?,
        imageCount: Int,
        videoCount: Int
    ) -> WildReportRecord {
        let trimmedDescription = description.trimmingCharacters(in: .whitespacesAndNewlines)
        let parsedContact = WildPhotographerReportMockStore.parseContact(contact)
        let record = WildReportRecord(
            id: nextReportID(),
            title: "摄影师举报",
            reportType: reportType,
            status: .pending,
            location: location,
            submitTime: WildPhotographerReportMockStore.submitTimeFormatter.string(from: Date()),
            description: trimmedDescription,
            wechatID: parsedContact.wechat,
            phoneNumber: parsedContact.phone,
            imageCount: imageCount,
            videoCount: videoCount,
            handlerInfo: nil
        )
        reports.insert(record, at: 0)
        notifyStateChange()
        return record
    }

    /// 读取指定举报的补充证据列表。
    func supplementaryEvidences(for reportID: String) -> [WildReportSupplementaryEvidence] {
        supplementaryEvidenceMap[reportID] ?? []
    }

    /// 追加一条补充证据记录。
    func appendSupplementaryEvidence(
        reportID: String,
        text: String,
        imageCount: Int,
        videoCount: Int
    ) {
        let item = WildReportSupplementaryEvidence(
            id: nextSupplementID(),
            submitTime: WildPhotographerReportMockStore.submitTimeFormatter.string(from: Date()),
            text: text.trimmingCharacters(in: .whitespacesAndNewlines),
            imageCount: imageCount,
            videoCount: videoCount
        )
        var items = supplementaryEvidenceMap[reportID] ?? []
        items.insert(item, at: 0)
        supplementaryEvidenceMap[reportID] = items
        notifyStateChange()
    }

    /// 重置为种子 Mock 数据。
    func resetDemoData(notify: Bool = true) {
        reports = WildPhotographerReportMockStore.seedReports
        riskPoints = WildPhotographerReportMockStore.seedRiskPoints
        supplementaryEvidenceMap = WildPhotographerReportMockStore.seedSupplementaryEvidences
        nextSequence = WildPhotographerReportMockStore.maxSequence(from: WildPhotographerReportMockStore.seedReports) + 1
        nextSupplementSequence = 100
        if notify { notifyStateChange() }
    }

    private func nextSupplementID() -> String {
        defer { nextSupplementSequence += 1 }
        return String(format: "SE%03d", nextSupplementSequence)
    }

    private func nextReportID() -> String {
        let datePart = WildPhotographerReportMockStore.reportDateFormatter.string(from: Date())
        defer { nextSequence += 1 }
        return String(format: "JB\(datePart)%03d", nextSequence)
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}

/// 提交举报页 ViewModel，负责表单校验和前台定位。
final class WildPhotographerReportSubmitViewModel {
    private(set) var pageState: WildReportPageState = .normal
    private(set) var images: [WildReportAttachment]
    private(set) var videos: [WildReportAttachment]
    private(set) var paymentImages: [WildReportAttachment] = []
    private(set) var selectedReportType: WildReportType = .suspectedWild
    private(set) var description = ""
    private(set) var contact = ""
    private(set) var reportLocation = ""
    private(set) var isUpdatingLocation = false
    private(set) var locationConfirmed = false
    private(set) var submitResult: WildReportSubmitResult?
    private(set) var validationMessage: String?

    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?
    var onSubmitSuccess: ((WildReportSubmitResult) -> Void)?

    private let homeViewModel: WildPhotographerReportHomeViewModel
    private let locationProvider: any LocationProviding
    private var hasRequestedInitialLocation = false

    var locationTitleText: String {
        if reportLocation.isEmpty || isUpdatingLocation {
            return "正在获取当前位置..."
        }
        return "当前定位：\(reportLocation)"
    }

    var locationSubtitleText: String {
        if isUpdatingLocation {
            return "正在更新定位，请稍候"
        }
        if locationConfirmed {
            return "已获取最新定位，如不准确请点击更新定位"
        }
        return "如位置不准确，请点击更新定位"
    }

    init(
        homeViewModel: WildPhotographerReportHomeViewModel,
        locationProvider: any LocationProviding = LocationProvider.shared
    ) {
        self.homeViewModel = homeViewModel
        self.locationProvider = locationProvider
        self.images = WildPhotographerReportMockStore.initialImages
        self.videos = WildPhotographerReportMockStore.initialVideos
    }

    /// 首次进入页面时自动请求定位。
    func loadInitialLocationIfNeeded() {
        guard !hasRequestedInitialLocation else { return }
        hasRequestedInitialLocation = true
        refreshCurrentLocation()
    }

    /// 选择举报类型。
    func selectReportType(_ type: WildReportType) {
        selectedReportType = type
        notifyStateChange()
    }

    /// 限制举报说明最多 500 字。
    func updateDescription(_ newValue: String) {
        description = String(newValue.prefix(500))
        notifyStateChange()
    }

    /// 更新联系方式。
    func updateContact(_ value: String) {
        contact = String(value.prefix(80))
        notifyStateChange()
    }

    /// 添加演示用现场图片。
    func addImage() {
        images.append(WildReportAttachment(kind: .image, title: "现场图片\(images.count + 1)"))
        notifyStateChange()
    }

    /// 添加演示用现场视频。
    func addVideo() {
        videos.append(WildReportAttachment(kind: .video, title: "现场视频\(videos.count + 1)"))
        notifyStateChange()
    }

    /// 添加演示用支付截图。
    func addPaymentImage() {
        guard paymentImages.count < 3 else {
            onShowMessage?("支付截图最多上传3张")
            return
        }
        paymentImages.append(WildReportAttachment(kind: .payment, title: "支付截图\(paymentImages.count + 1)"))
        notifyStateChange()
    }

    /// 删除指定附件。
    func removeAttachment(_ attachment: WildReportAttachment) {
        images.removeAll { $0.id == attachment.id }
        videos.removeAll { $0.id == attachment.id }
        paymentImages.removeAll { $0.id == attachment.id }
        notifyStateChange()
    }

    /// 使用前台定位 Provider 刷新当前位置。
    func refreshCurrentLocation() {
        guard !isUpdatingLocation else { return }
        isUpdatingLocation = true
        locationConfirmed = false
        reportLocation = "正在获取当前位置..."
        notifyStateChange()

        Task {
            do {
                let snapshot = try await locationProvider.requestSnapshot()
                let address = snapshot.address.isEmpty
                    ? String(format: "%.5f, %.5f", snapshot.latitude, snapshot.longitude)
                    : snapshot.address
                applyResolvedLocation(address)
            } catch {
                applyResolvedLocation(WildPhotographerReportMockStore.fallbackLocation)
            }
        }
    }

    /// 清除提交结果，用于导航返回。
    func clearSubmitResult() {
        submitResult = nil
        notifyStateChange()
    }

    /// 校验表单并提交举报。
    func submitReport() {
        validationMessage = nil
        guard !images.isEmpty || !videos.isEmpty else {
            setValidationMessage("请至少上传一项现场证据。")
            return
        }
        guard !description.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
            setValidationMessage("请填写举报说明。")
            return
        }
        guard !isUpdatingLocation else {
            setValidationMessage("正在获取定位，请稍后再提交。")
            return
        }
        guard locationConfirmed, !reportLocation.isEmpty, reportLocation != "正在获取当前位置..." else {
            setValidationMessage("请先更新举报位置后再提交举报。")
            return
        }

        let record = homeViewModel.submitReport(
            reportType: selectedReportType,
            description: description,
            location: reportLocation,
            contact: contact.isEmpty ? nil : contact,
            imageCount: images.count,
            videoCount: videos.count
        )
        let result = WildReportSubmitResult(
            record: record,
            imageCount: images.count,
            videoCount: videos.count
        )
        submitResult = result
        notifyStateChange()
        onSubmitSuccess?(result)
    }

    /// 重置表单到初始状态。
    func resetForm() {
        images = WildPhotographerReportMockStore.initialImages
        videos = WildPhotographerReportMockStore.initialVideos
        paymentImages = []
        selectedReportType = .suspectedWild
        description = ""
        contact = ""
        reportLocation = ""
        locationConfirmed = false
        isUpdatingLocation = false
        hasRequestedInitialLocation = false
        submitResult = nil
        validationMessage = nil
        notifyStateChange()
    }

    func applyResolvedLocation(_ location: String) {
        reportLocation = location
        locationConfirmed = true
        isUpdatingLocation = false
        notifyStateChange()
    }

    private func setValidationMessage(_ message: String) {
        validationMessage = message
        notifyStateChange()
        onShowMessage?(message)
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}

/// 举报成功页 ViewModel。
final class WildPhotographerReportSuccessViewModel {
    let result: WildReportSubmitResult
    let progressSteps = ["已提交", "现场核查中", "处理结果反馈"]

    init(result: WildReportSubmitResult) {
        self.result = result
    }

    var uploadSummary: String {
        var parts: [String] = []
        if result.imageCount > 0 { parts.append("\(result.imageCount)张图片") }
        if result.videoCount > 0 { parts.append("\(result.videoCount)段视频") }
        return parts.isEmpty ? "暂无" : parts.joined(separator: " ")
    }

    /// 复制举报编号到剪贴板。
    @MainActor
    func copyReportID() -> String {
        UIPasteboard.general.string = result.record.id
        return result.record.id
    }
}

/// 举报详情页 ViewModel。
final class WildPhotographerReportDetailViewModel {
    let record: WildReportRecord
    private let homeViewModel: WildPhotographerReportHomeViewModel?

    private(set) var actionMessage: String?
    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?

    init(record: WildReportRecord, homeViewModel: WildPhotographerReportHomeViewModel? = nil) {
        self.record = record
        self.homeViewModel = homeViewModel
    }

    var heroTitle: String { record.title.isEmpty ? "摄影师举报" : record.title }
    var scenicAreaName: String { WildReportLocationParser.split(record.location).scenic }
    var detailAddress: String {
        let detail = WildReportLocationParser.split(record.location).detail
        return detail.contains("附近") ? detail : "\(detail)附近"
    }

    var displayStatusText: String { record.status.rawValue }
    var descriptionText: String { record.description }
    var contactText: String { record.contactDisplayText }
    var supplementaryEvidences: [WildReportSupplementaryEvidence] {
        homeViewModel?.supplementaryEvidences(for: record.id) ?? []
    }
    var reporterMediaItems: [WildReportReporterMediaItem] {
        let images = (0..<record.imageCount).map { WildReportReporterMediaItem.image(index: $0) }
        let videos = (0..<record.videoCount).map { WildReportReporterMediaItem.video(index: $0) }
        return images + videos
    }
    var imageCountText: String { "\(record.imageCount)张" }
    var videoCountText: String { "\(record.videoCount)段" }
    var reporterMediaSummary: String {
        switch (record.imageCount, record.videoCount) {
        case (0, 0): return "0项"
        case (_, 0): return "\(record.imageCount)张"
        case (0, _): return "\(record.videoCount)段"
        default: return "\(record.imageCount)张 \(record.videoCount)段"
        }
    }
    var progressSteps: [WildReportProgressStep] { Self.buildProgressSteps(for: record) }
    var showHandlerInfo: Bool { record.status == .processed && record.handlerInfo != nil }
    var handlerInfo: WildReportHandlerInfo? { record.handlerInfo }

    /// 展示媒体预览提示。
    func showMediaPreview(kind: String) {
        showActionMessage("演示环境暂不支持预览\(kind)，可在提交页查看上传内容。")
    }

    /// 展示位置预览提示。
    func showLocationPreview() {
        showActionMessage("举报位置：\(record.location)")
    }

    /// 生成分享提示文案。
    func shareReport() {
        showActionMessage("已生成举报 \(record.id) 的分享信息，可发送给景区处理人员查看进度。")
    }

    private func showActionMessage(_ message: String) {
        actionMessage = message
        onShowMessage?(message)
        notifyStateChange()
    }

    private static func buildProgressSteps(for record: WildReportRecord) -> [WildReportProgressStep] {
        let baseDate = submitDate(from: record.submitTime) ?? Date()
        let expectedFeedback = formatDate(baseDate.addingTimeInterval(8 * 3_600))

        switch record.status {
        case .pending, .processing:
            return [
                makeStep(id: "1", title: "已提交", date: baseDate, state: .completed),
                makeStep(id: "2", title: "已派工作人员前往", date: baseDate.addingTimeInterval(22 * 60), state: .completed),
                makeStep(id: "3", title: "现场核查中", date: baseDate.addingTimeInterval(57 * 60), state: .current),
                makeStep(id: "4", title: "待结果反馈", date: nil, state: .pending, pendingText: "预计 \(expectedFeedback) 前")
            ]
        case .processed:
            return [
                makeStep(id: "1", title: "已提交", date: baseDate, state: .completed),
                makeStep(id: "2", title: "已派工作人员前往", date: baseDate.addingTimeInterval(22 * 60), state: .completed),
                makeStep(id: "3", title: "现场核查中", date: baseDate.addingTimeInterval(57 * 60), state: .completed),
                makeStep(id: "4", title: "已反馈核查结果", date: baseDate.addingTimeInterval(3 * 3_600), state: .completed)
            ]
        }
    }

    private static func makeStep(
        id: String,
        title: String,
        date: Date?,
        state: WildReportProgressStepState,
        pendingText: String? = nil
    ) -> WildReportProgressStep {
        WildReportProgressStep(
            id: id,
            title: title,
            timeText: pendingText ?? (date.map(formatDate) ?? ""),
            state: state
        )
    }

    private static func submitDate(from text: String) -> Date? {
        WildPhotographerReportMockStore.submitTimeFormatter.date(from: text)
    }

    private static func formatDate(_ date: Date) -> String {
        WildPhotographerReportMockStore.submitTimeFormatter.string(from: date)
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}

/// 我的举报列表 ViewModel。
final class WildPhotographerReportListViewModel {
    private(set) var selectedFilter: WildReportListFilter = .all
    private(set) var shareMessage: String?

    let homeViewModel: WildPhotographerReportHomeViewModel
    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?

    init(homeViewModel: WildPhotographerReportHomeViewModel) {
        self.homeViewModel = homeViewModel
    }

    var filteredReports: [WildReportRecord] {
        let reports = homeViewModel.reports
        switch selectedFilter {
        case .all: return reports
        case .pending: return reports.filter { $0.status == .pending }
        case .processing: return reports.filter { $0.status == .processing }
        case .processed: return reports.filter { $0.status == .processed }
        }
    }

    var footerTip: String { "温馨提示：为保障处理效率，请如实举报并提供有效证据" }

    /// 切换列表筛选标签。
    func selectFilter(_ filter: WildReportListFilter) {
        selectedFilter = filter
        notifyStateChange()
    }

    /// 生成分享提示文案。
    func shareReport(_ record: WildReportRecord) {
        shareMessage = "已生成举报 \(record.id) 的分享信息，可发送给景区处理人员查看进度。"
        onShowMessage?(shareMessage ?? "")
        notifyStateChange()
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}

/// 补充证据页 ViewModel。
final class WildReportSupplementEvidenceViewModel {
    private(set) var text = ""
    private(set) var images: [WildReportAttachment] = []
    private(set) var videos: [WildReportAttachment] = []
    private(set) var validationMessage: String?
    private(set) var didSubmit = false

    let reportID: String
    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?
    var onSubmitSuccess: (() -> Void)?

    private let homeViewModel: WildPhotographerReportHomeViewModel

    init(reportID: String, homeViewModel: WildPhotographerReportHomeViewModel) {
        self.reportID = reportID
        self.homeViewModel = homeViewModel
    }

    /// 限制补充说明最多 500 字。
    func updateText(_ newValue: String) {
        text = String(newValue.prefix(500))
        notifyStateChange()
    }

    /// 添加演示用补充图片。
    func addImage() {
        guard images.count < 9 else {
            onShowMessage?("补充图片最多上传9张")
            return
        }
        images.append(WildReportAttachment(kind: .image, title: "补充图片\(images.count + 1)"))
        notifyStateChange()
    }

    /// 添加演示用补充视频。
    func addVideo() {
        guard videos.count < 3 else {
            onShowMessage?("补充视频最多上传3段")
            return
        }
        videos.append(WildReportAttachment(kind: .video, title: "补充视频\(videos.count + 1)"))
        notifyStateChange()
    }

    /// 删除指定附件。
    func removeAttachment(_ attachment: WildReportAttachment) {
        images.removeAll { $0.id == attachment.id }
        videos.removeAll { $0.id == attachment.id }
        notifyStateChange()
    }

    /// 校验并提交补充证据。
    func submit() {
        validationMessage = nil
        let trimmedText = text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !trimmedText.isEmpty || !images.isEmpty || !videos.isEmpty else {
            validationMessage = "请至少填写补充说明或上传一项证据。"
            onShowMessage?(validationMessage ?? "")
            notifyStateChange()
            return
        }

        homeViewModel.appendSupplementaryEvidence(
            reportID: reportID,
            text: trimmedText,
            imageCount: images.count,
            videoCount: videos.count
        )
        didSubmit = true
        notifyStateChange()
        onSubmitSuccess?()
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}

/// 附近风险地图 ViewModel。
final class WildReportRiskMapViewModel {
    private(set) var region: MKCoordinateRegion
    private(set) var markers: [WildReportMapMarker]
    let scenicAreaName: String
    private(set) var selectedMarkerID: String?
    private(set) var toastMessage: String?

    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?

    init(record: WildReportRecord, riskPoints: [WildReportRiskPoint]) {
        let markers = WildPhotographerReportMockStore.buildMarkers(record: record, riskPoints: riskPoints)
        self.markers = markers
        self.region = WildPhotographerReportMockStore.region(for: markers)
        self.scenicAreaName = "那拉提景区"
        self.selectedMarkerID = markers.first(where: { $0.kind == .selfLocation })?.id
    }

    var selectedMarker: WildReportMapMarker? {
        guard let selectedMarkerID else { return nil }
        return markers.first { $0.id == selectedMarkerID }
    }

    var selectedClue: WildReportRadarActiveClue? {
        guard let marker = selectedMarker,
              case .activeClue(let clue) = marker.detail else { return nil }
        return clue
    }

    /// 选中地图标记。
    func selectMarker(_ marker: WildReportMapMarker) {
        selectedMarkerID = marker.id
        notifyStateChange()
    }

    /// 导航到选中标记或刷新蓝点定位。
    func navigateToSelectedMarker() {
        guard let marker = selectedMarker,
              case .activeClue(let clue) = marker.detail else { return }

        if clue.type == .blue {
            refreshLocation()
            return
        }

        showToast("已切换到该点位")
        region = MKCoordinateRegion(
            center: marker.coordinate,
            span: MKCoordinateSpan(latitudeDelta: 0.018, longitudeDelta: 0.018)
        )
        notifyStateChange()
    }

    /// 将地图居中到当前位置标记。
    func refreshLocation() {
        guard let blueMarker = markers.first(where: { $0.kind == .selfLocation }) else { return }
        selectedMarkerID = blueMarker.id
        region = MKCoordinateRegion(
            center: blueMarker.coordinate,
            span: MKCoordinateSpan(latitudeDelta: 0.018, longitudeDelta: 0.018)
        )
        showToast("已定位到当前位置")
        notifyStateChange()
    }

    /// 生成线索分享提示。
    func shareSelectedClue() {
        guard let clue = selectedClue else { return }
        let title = clue.type == .red ? "线索 ID：\(clue.id)" : clue.displayTitle
        showToast("已生成\(title)的分享信息，可发送给他人查看。")
    }

    /// 生成图片预览提示。
    func showImagePreview(_ url: String) {
        _ = url
        showToast("演示环境暂不支持预览图片")
    }

    private func showToast(_ message: String) {
        toastMessage = message
        onShowMessage?(message)
        notifyStateChange()
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}
