//
//  MessageCenterViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 消息中心列表页，对齐 Android `MsgScreen` 的列表展示与未读处理。
final class MessageCenterViewController: BaseViewController, UITableViewDelegate {
    private enum Section {
        case main
    }

    private let viewModel: MessageCenterViewModel
    private let api: any MessageCenterServing
    private let tableView = UITableView(frame: .zero, style: .plain)
    private let refreshControl = UIRefreshControl()
    private let loadingIndicator = UIActivityIndicatorView(style: .medium)
    private let footerSpinner = UIActivityIndicatorView(style: .medium)
    private let emptyLabel = UILabel()
    private lazy var markAllReadButton = UIBarButtonItem(
        title: "全部已读",
        style: .plain,
        target: self,
        action: #selector(markAllReadTapped)
    )

    private var dataSource: UITableViewDiffableDataSource<Section, MessageItem>!

    /// 初始化消息中心列表页。
    init(
        viewModel: MessageCenterViewModel = MessageCenterViewModel(),
        api: (any MessageCenterServing)? = nil
    ) {
        self.viewModel = viewModel
        self.api = api ?? NetworkServices.shared.messageCenterAPI
        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        Task { @MainActor in
            await viewModel.loadInitial(api: api)
        }
    }

    override func setupNavigationBar() {
        title = "消息中心"
        navigationItem.rightBarButtonItem = markAllReadButton
    }

    override func setupUI() {
        view.backgroundColor = UIColor(hex: 0xF4F4F4)

        tableView.backgroundColor = .clear
        tableView.separatorStyle = .none
        tableView.delegate = self
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 120
        tableView.contentInset = UIEdgeInsets(top: 10, left: 0, bottom: 10, right: 0)
        tableView.refreshControl = refreshControl
        tableView.register(MessageCenterCell.self, forCellReuseIdentifier: MessageCenterCell.reuseIdentifier)

        loadingIndicator.hidesWhenStopped = true
        loadingIndicator.color = AppColor.primary

        footerSpinner.hidesWhenStopped = true
        footerSpinner.color = AppColor.primary

        emptyLabel.text = "暂无消息"
        emptyLabel.font = .app(.body)
        emptyLabel.textColor = UIColor(hex: 0x7B8EAA)
        emptyLabel.textAlignment = .center

        view.addSubview(tableView)
        view.addSubview(loadingIndicator)

        configureDataSource()
    }

    override func setupConstraints() {
        tableView.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.bottom.equalToSuperview()
        }
        loadingIndicator.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
    }

    override func bindActions() {
        refreshControl.addTarget(self, action: #selector(refreshTriggered), for: .valueChanged)
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in
                self?.applyState()
            }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in
                self?.showToast(message)
            }
        }
        viewModel.onOpenDetail = { [weak self] message in
            Task { @MainActor in
                self?.openDetail(message)
            }
        }
        viewModel.onUnreadMessageCountChange = { count in
            Task { @MainActor in
                await PushNotificationManager.shared.updateApplicationIconBadgeCount(count)
            }
        }
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        guard let item = dataSource.itemIdentifier(for: indexPath) else { return }
        Task { @MainActor in
            await viewModel.selectMessage(id: item.id, api: api)
        }
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        Task { @MainActor in
            await viewModel.loadMoreIfNeeded(lastVisibleIndex: indexPath.row, api: api)
        }
    }

    @objc private func refreshTriggered() {
        Task { @MainActor in
            await viewModel.refresh(api: api)
        }
    }

    @objc private func markAllReadTapped() {
        Task { @MainActor in
            await viewModel.markAllAsRead(api: api)
        }
    }

    private func configureDataSource() {
        dataSource = UITableViewDiffableDataSource<Section, MessageItem>(tableView: tableView) { tableView, indexPath, item in
            let cell = tableView.dequeueReusableCell(
                withIdentifier: MessageCenterCell.reuseIdentifier,
                for: indexPath
            ) as! MessageCenterCell
            cell.configure(with: item)
            return cell
        }
        applySnapshot(animated: false)
    }

    private func applyState() {
        applySnapshot(animated: true)
        if viewModel.isRefreshing {
            if !refreshControl.isRefreshing { refreshControl.beginRefreshing() }
        } else {
            refreshControl.endRefreshing()
        }

        if viewModel.isLoading {
            loadingIndicator.startAnimating()
            tableView.backgroundView = nil
        } else {
            loadingIndicator.stopAnimating()
            tableView.backgroundView = viewModel.items.isEmpty ? emptyBackgroundView() : nil
        }

        tableView.tableFooterView = footerView()
        markAllReadButton.isEnabled = !viewModel.isLoading && !viewModel.isMarkingAllAsRead
    }

    private func applySnapshot(animated: Bool) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, MessageItem>()
        snapshot.appendSections([.main])
        snapshot.appendItems(viewModel.items)
        dataSource.apply(snapshot, animatingDifferences: animated)
    }

    private func emptyBackgroundView() -> UIView {
        let container = UIView(frame: tableView.bounds)
        emptyLabel.frame = container.bounds
        emptyLabel.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        container.addSubview(emptyLabel)
        return container
    }

    private func footerView() -> UIView? {
        guard !viewModel.items.isEmpty, viewModel.isLoadingMore else { return nil }
        let container = UIView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 44))
        footerSpinner.center = CGPoint(x: container.bounds.midX, y: container.bounds.midY)
        footerSpinner.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin]
        container.addSubview(footerSpinner)
        footerSpinner.startAnimating()
        return container
    }

    private func openDetail(_ message: MessageItem) {
        let controller = MessageDetailViewController(message: message, api: api)
        controller.onDeleted = { [weak self] id in
            self?.viewModel.removeMessage(id: id)
        }
        navigationController?.pushViewController(controller, animated: true)
    }
}

/// 消息列表卡片 Cell，对齐 Android `MsgItem`。
final class MessageCenterCell: UITableViewCell {
    static let reuseIdentifier = "MessageCenterCell"

    private let cardView = UIView()
    private let typeImageView = UIImageView()
    private let titleLabel = UILabel()
    private let timeLabel = UILabel()
    private let unreadDot = UIView()
    private let contentLabel = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupUI()
        setupConstraints()
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    /// 配置消息卡片内容。
    func configure(with item: MessageItem) {
        typeImageView.image = UIImage(named: MessageTypeIcon.assetName(for: item.type))
        titleLabel.text = item.displayTitle
        timeLabel.text = item.displayTime
        contentLabel.text = item.content
        unreadDot.isHidden = item.isRead
    }

    private func setupUI() {
        backgroundColor = .clear
        contentView.backgroundColor = .clear
        selectionStyle = .none

        cardView.backgroundColor = .white
        cardView.layer.cornerRadius = 12
        cardView.clipsToBounds = true

        typeImageView.contentMode = .scaleAspectFit

        titleLabel.font = .systemFont(ofSize: 14, weight: .medium)
        titleLabel.textColor = UIColor(hex: 0x333333)
        titleLabel.numberOfLines = 1
        titleLabel.lineBreakMode = .byTruncatingTail

        timeLabel.font = .systemFont(ofSize: 12, weight: .thin)
        timeLabel.textColor = UIColor(hex: 0x7B8EAA)
        timeLabel.numberOfLines = 1

        unreadDot.backgroundColor = UIColor(hex: 0xEF4444)
        unreadDot.layer.cornerRadius = 4
        unreadDot.clipsToBounds = true

        contentLabel.font = .systemFont(ofSize: 14)
        contentLabel.textColor = UIColor(hex: 0x2E3746)
        contentLabel.numberOfLines = 2
        contentLabel.lineBreakMode = .byTruncatingTail

        contentView.addSubview(cardView)
        [typeImageView, titleLabel, timeLabel, unreadDot, contentLabel].forEach(cardView.addSubview)
    }

    private func setupConstraints() {
        cardView.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview().inset(6)
            make.leading.trailing.equalToSuperview().inset(16)
        }
        typeImageView.snp.makeConstraints { make in
            make.top.leading.equalToSuperview().offset(16)
            make.size.equalTo(50)
        }
        unreadDot.snp.makeConstraints { make in
            make.top.equalTo(typeImageView.snp.top).offset(2)
            make.trailing.equalToSuperview().inset(16)
            make.size.equalTo(8)
        }
        titleLabel.snp.makeConstraints { make in
            make.top.equalTo(typeImageView.snp.top).offset(1)
            make.leading.equalTo(typeImageView.snp.trailing).offset(8)
            make.trailing.lessThanOrEqualTo(unreadDot.snp.leading).offset(-8)
        }
        timeLabel.snp.makeConstraints { make in
            make.top.equalTo(titleLabel.snp.bottom).offset(1)
            make.leading.equalTo(titleLabel)
            make.trailing.equalToSuperview().inset(16)
        }
        contentLabel.snp.makeConstraints { make in
            make.top.equalTo(typeImageView.snp.bottom).offset(8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.bottom.equalToSuperview().inset(16)
        }
    }
}

/// 消息类型图标映射，对齐 Android `getMessageTypeIcon`。
enum MessageTypeIcon {
    static func assetName(for type: Int) -> String {
        switch type {
        case 1, 7:
            return "ic_msg1"
        case 2:
            return "ic_msg2"
        case 3:
            return "ic_msg3"
        case 4:
            return "ic_msg4"
        case 5:
            return "ic_msg5"
        case 8:
            return "ic_msg8"
        default:
            return "ic_msg999"
        }
    }
}
