//
//  InviteRecordViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 邀请记录页面，展示邀请用户列表、奖励流水和钱包汇总金额。
final class InviteRecordViewController: BaseViewController {
    private enum Section: Hashable {
        case main
    }

    private enum Item: Hashable {
        case invite(InviteDisplayRow)
        case reward(WalletTransactionItem)
        case footer(String)
    }

    private let viewModel = InviteRecordViewModel()
    private let inviteAPI: InviteServing
    private let walletAPI: WalletServing

    private let headerView = UIView()
    private let totalAmountLabel = UILabel()
    private let withdrawableAmountLabel = UILabel()
    private let contentCard = UIView()
    private let tabStack = UIStackView()
    private let inviteTabButton = InviteRecordTabButton(title: "邀请记录")
    private let rewardTabButton = InviteRecordTabButton(title: "奖励记录")
    private let tableView = UITableView(frame: .zero, style: .plain)
    private let emptyLabel = UILabel()
    private let bottomBar = UIView()
    private let walletButton = UIButton(type: .system)

    private var dataSource: UITableViewDiffableDataSource<Section, Item>!

    /// 初始化邀请记录页面。
    init(
        inviteAPI: InviteServing? = nil,
        walletAPI: WalletServing? = nil
    ) {
        self.inviteAPI = inviteAPI ?? NetworkServices.shared.inviteAPI
        self.walletAPI = walletAPI ?? NetworkServices.shared.walletAPI
        super.init(nibName: nil, bundle: nil)
    }

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

    override func setupNavigationBar() {
        title = "邀请记录"
    }

    override func setupUI() {
        view.backgroundColor = UIColor(hex: 0xF5F6F8)
        setupHeader()
        setupContentCard()
        setupBottomBar()
        dataSource = makeDataSource()
    }

    override func setupConstraints() {
        headerView.snp.makeConstraints { make in
            make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
            make.height.equalTo(104)
        }
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        contentCard.snp.makeConstraints { make in
            make.top.equalTo(headerView.snp.bottom).offset(16)
            make.leading.trailing.equalTo(view.safeAreaLayoutGuide).inset(16)
            make.bottom.equalTo(bottomBar.snp.top).offset(-16)
        }
    }

    override func bindActions() {
        inviteTabButton.addTarget(self, action: #selector(inviteTabTapped), for: .touchUpInside)
        rewardTabButton.addTarget(self, action: #selector(rewardTabTapped), for: .touchUpInside)
        walletButton.addTarget(self, action: #selector(walletTapped), for: .touchUpInside)
        tableView.refreshControl?.addTarget(self, action: #selector(refreshPulled), for: .valueChanged)
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in
                self?.applyViewModel(animated: true)
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        Task { await viewModel.loadInitial(inviteAPI: inviteAPI, walletAPI: walletAPI) }
    }

    private func setupHeader() {
        headerView.backgroundColor = AppColor.primary
        view.addSubview(headerView)

        let divider = UIView()
        divider.backgroundColor = UIColor.white.withAlphaComponent(0.8)

        let totalMetric = makeMetricView(title: "累计奖励金额", valueLabel: totalAmountLabel)
        let withdrawMetric = makeMetricView(title: "可提现金额", valueLabel: withdrawableAmountLabel)

        headerView.addSubview(totalMetric)
        headerView.addSubview(divider)
        headerView.addSubview(withdrawMetric)
        totalMetric.snp.makeConstraints { make in
            make.leading.top.bottom.equalToSuperview()
            make.trailing.equalTo(divider.snp.leading)
            make.width.equalTo(withdrawMetric)
        }
        divider.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.centerY.equalToSuperview()
            make.width.equalTo(1)
            make.height.equalTo(56)
        }
        withdrawMetric.snp.makeConstraints { make in
            make.leading.equalTo(divider.snp.trailing)
            make.trailing.top.bottom.equalToSuperview()
        }
    }

    private func setupContentCard() {
        contentCard.backgroundColor = .white
        contentCard.layer.cornerRadius = 12
        contentCard.clipsToBounds = true
        view.addSubview(contentCard)

        tabStack.axis = .horizontal
        tabStack.distribution = .fillEqually
        tabStack.addArrangedSubview(inviteTabButton)
        tabStack.addArrangedSubview(rewardTabButton)
        contentCard.addSubview(tabStack)

        tableView.backgroundColor = .white
        tableView.separatorStyle = .none
        tableView.delegate = self
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 72
        tableView.refreshControl = UIRefreshControl()
        tableView.register(InviteUserCell.self, forCellReuseIdentifier: InviteUserCell.reuseIdentifier)
        tableView.register(InviteRewardCell.self, forCellReuseIdentifier: InviteRewardCell.reuseIdentifier)
        tableView.register(InviteFooterCell.self, forCellReuseIdentifier: InviteFooterCell.reuseIdentifier)
        contentCard.addSubview(tableView)

        emptyLabel.textColor = AppColor.textSecondary
        emptyLabel.font = .app(.body)
        emptyLabel.textAlignment = .center
        emptyLabel.isHidden = true
        contentCard.addSubview(emptyLabel)

        tabStack.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(44)
        }
        tableView.snp.makeConstraints { make in
            make.top.equalTo(tabStack.snp.bottom).offset(8)
            make.leading.trailing.bottom.equalToSuperview().inset(16)
        }
        emptyLabel.snp.makeConstraints { make in
            make.center.equalTo(tableView)
        }
    }

    private func setupBottomBar() {
        bottomBar.backgroundColor = .white
        view.addSubview(bottomBar)

        walletButton.backgroundColor = AppColor.primary
        walletButton.layer.cornerRadius = 12
        walletButton.setTitle("去钱包提现", for: .normal)
        walletButton.setTitleColor(.white, for: .normal)
        walletButton.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        bottomBar.addSubview(walletButton)

        walletButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(16)
            make.leading.trailing.equalTo(bottomBar.safeAreaLayoutGuide).inset(16)
            make.height.equalTo(48)
            make.bottom.equalTo(bottomBar.safeAreaLayoutGuide).inset(22)
        }
    }

    private func makeMetricView(title: String, valueLabel: UILabel) -> UIView {
        let titleLabel = UILabel()
        titleLabel.text = title
        titleLabel.font = .app(.body)
        titleLabel.textColor = UIColor.white.withAlphaComponent(0.8)
        titleLabel.textAlignment = .center

        valueLabel.font = .systemFont(ofSize: 24, weight: .medium)
        valueLabel.textColor = .white
        valueLabel.textAlignment = .center
        valueLabel.adjustsFontSizeToFitWidth = true
        valueLabel.minimumScaleFactor = 0.7

        let stack = UIStackView(arrangedSubviews: [titleLabel, valueLabel])
        stack.axis = .vertical
        stack.alignment = .fill
        stack.spacing = 4

        let container = UIView()
        container.addSubview(stack)
        stack.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(12)
        }
        return container
    }

    private func makeDataSource() -> UITableViewDiffableDataSource<Section, Item> {
        UITableViewDiffableDataSource<Section, Item>(tableView: tableView) { tableView, indexPath, item in
            switch item {
            case .invite(let row):
                let cell = tableView.dequeueReusableCell(withIdentifier: InviteUserCell.reuseIdentifier, for: indexPath) as! InviteUserCell
                cell.apply(row)
                return cell
            case .reward(let row):
                let cell = tableView.dequeueReusableCell(withIdentifier: InviteRewardCell.reuseIdentifier, for: indexPath) as! InviteRewardCell
                cell.apply(row)
                return cell
            case .footer(let text):
                let cell = tableView.dequeueReusableCell(withIdentifier: InviteFooterCell.reuseIdentifier, for: indexPath) as! InviteFooterCell
                cell.apply(text: text)
                return cell
            }
        }
    }

    @MainActor
    private func applyViewModel(animated: Bool) {
        totalAmountLabel.text = "¥ \(viewModel.totalRewardText)"
        withdrawableAmountLabel.text = "¥ \(viewModel.withdrawableText)"
        inviteTabButton.isSelected = viewModel.selectedTab == .invite
        rewardTabButton.isSelected = viewModel.selectedTab == .reward

        var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
        snapshot.appendSections([.main])
        switch viewModel.selectedTab {
        case .invite:
            snapshot.appendItems([.footer("已邀请摄影师")], toSection: .main)
            snapshot.appendItems(viewModel.inviteRows.map(Item.invite), toSection: .main)
            if !viewModel.inviteRows.isEmpty {
                snapshot.appendItems([.footer(viewModel.canLoadMoreInvite ? "加载中..." : "没有更多")], toSection: .main)
            }
            emptyLabel.text = "暂无邀请记录"
            emptyLabel.isHidden = !viewModel.inviteRows.isEmpty || viewModel.isInviteRefreshing
        case .reward:
            snapshot.appendItems([.footer("奖励记录")], toSection: .main)
            snapshot.appendItems(viewModel.rewardRows.map(Item.reward), toSection: .main)
            if !viewModel.rewardRows.isEmpty {
                snapshot.appendItems([.footer(viewModel.canLoadMoreReward ? "加载中..." : "没有更多")], toSection: .main)
            }
            emptyLabel.text = "暂无数据"
            emptyLabel.isHidden = !viewModel.rewardRows.isEmpty || viewModel.isRewardRefreshing
        }
        dataSource.apply(snapshot, animatingDifferences: animated)
        tableView.refreshControl?.endRefreshing()

        if let message = viewModel.errorMessage {
            showToast(message)
        }
    }

    @objc private func inviteTabTapped() {
        Task { await viewModel.selectTab(.invite, inviteAPI: inviteAPI, walletAPI: walletAPI) }
    }

    @objc private func rewardTabTapped() {
        Task { await viewModel.selectTab(.reward, inviteAPI: inviteAPI, walletAPI: walletAPI) }
    }

    @objc private func refreshPulled() {
        Task {
            switch viewModel.selectedTab {
            case .invite:
                await viewModel.refreshInvite(inviteAPI: inviteAPI, walletAPI: walletAPI)
            case .reward:
                await viewModel.refreshReward(walletAPI: walletAPI)
            }
        }
    }

    @objc private func walletTapped() {
        HomeRouteHandler.open(uri: "wallet", from: self, storeItem: nil)
    }

    private func loadMoreIfNeeded() {
        Task {
            switch viewModel.selectedTab {
            case .invite:
                await viewModel.loadMoreInvite(inviteAPI: inviteAPI)
            case .reward:
                await viewModel.loadMoreReward(walletAPI: walletAPI)
            }
        }
    }
}

extension InviteRecordViewController: UITableViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let distanceToBottom = scrollView.contentSize.height - scrollView.bounds.height - scrollView.contentOffset.y
        guard distanceToBottom < 160, scrollView.contentSize.height > scrollView.bounds.height else { return }
        loadMoreIfNeeded()
    }
}

/// 邀请记录 Tab 按钮。
private final class InviteRecordTabButton: UIButton {
    override var isSelected: Bool {
        didSet {
            setTitleColor(isSelected ? AppColor.primary : UIColor(hex: 0xB6BECA), for: .normal)
            titleLabel?.font = .systemFont(ofSize: 16, weight: isSelected ? .medium : .regular)
        }
    }

    /// 初始化 Tab 按钮。
    init(title: String) {
        super.init(frame: .zero)
        setTitle(title, for: .normal)
        setTitleColor(UIColor(hex: 0xB6BECA), for: .normal)
        titleLabel?.font = .systemFont(ofSize: 16)
    }

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

/// 邀请用户列表单元格。
private final class InviteUserCell: UITableViewCell {
    static let reuseIdentifier = "InviteUserCell"

    private let avatarImageView = UIImageView()
    private let avatarLabel = UILabel()
    private let nameLabel = UILabel()
    private let levelLabel = UILabel()
    private let phoneLabel = UILabel()
    private let timeLabel = UILabel()

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

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

    /// 应用邀请用户行数据。
    func apply(_ row: InviteDisplayRow) {
        avatarLabel.text = row.avatarPlaceholder
        avatarImageView.loadRemoteImage(urlString: row.avatar, placeholderColor: UIColor(hex: 0xE0F2FF))
        avatarLabel.isHidden = !row.avatar.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
        nameLabel.text = row.title
        phoneLabel.text = row.phone
        timeLabel.text = row.time
        levelLabel.text = row.levelText
        levelLabel.textColor = row.isPrimaryLevel ? UIColor(hex: 0x22C55E) : AppColor.warning
        levelLabel.backgroundColor = row.isPrimaryLevel ? AppColor.successBackground : AppColor.warningBackground
    }

    private func setupUI() {
        let divider = UIView()
        divider.backgroundColor = UIColor(hex: 0xF3F4F6)
        contentView.addSubview(divider)

        avatarImageView.layer.cornerRadius = 24
        avatarImageView.clipsToBounds = true
        avatarImageView.contentMode = .scaleAspectFill
        contentView.addSubview(avatarImageView)

        avatarLabel.font = .systemFont(ofSize: 18, weight: .medium)
        avatarLabel.textColor = AppColor.primary
        avatarLabel.textAlignment = .center
        avatarImageView.addSubview(avatarLabel)

        nameLabel.font = .systemFont(ofSize: 16, weight: .medium)
        nameLabel.textColor = .black
        levelLabel.font = .app(.caption)
        levelLabel.textAlignment = .center
        levelLabel.layer.cornerRadius = 4
        levelLabel.clipsToBounds = true

        let nameRow = UIStackView(arrangedSubviews: [nameLabel, levelLabel])
        nameRow.axis = .horizontal
        nameRow.alignment = .center
        nameRow.spacing = 4

        phoneLabel.font = .app(.body)
        phoneLabel.textColor = UIColor(hex: 0x7B8EAA)
        timeLabel.font = .app(.body)
        timeLabel.textColor = UIColor(hex: 0xB6BECA)
        timeLabel.textAlignment = .right
        let infoRow = UIStackView(arrangedSubviews: [phoneLabel, timeLabel])
        infoRow.axis = .horizontal
        infoRow.spacing = 8
        infoRow.distribution = .fillEqually

        let textStack = UIStackView(arrangedSubviews: [nameRow, infoRow])
        textStack.axis = .vertical
        textStack.spacing = 4
        contentView.addSubview(textStack)

        divider.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.equalTo(1)
        }
        avatarImageView.snp.makeConstraints { make in
            make.leading.equalToSuperview()
            make.top.equalToSuperview().offset(13)
            make.size.equalTo(48)
            make.bottom.lessThanOrEqualToSuperview().inset(13)
        }
        avatarLabel.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        levelLabel.snp.makeConstraints { make in
            make.width.greaterThanOrEqualTo(40)
            make.height.equalTo(20)
        }
        textStack.snp.makeConstraints { make in
            make.leading.equalTo(avatarImageView.snp.trailing).offset(12)
            make.trailing.equalToSuperview()
            make.centerY.equalTo(avatarImageView)
            make.top.greaterThanOrEqualToSuperview().offset(12)
            make.bottom.lessThanOrEqualToSuperview().inset(12)
        }
    }
}

/// 奖励流水列表单元格。
private final class InviteRewardCell: UITableViewCell {
    static let reuseIdentifier = "InviteRewardCell"

    private let amountLabel = UILabel()
    private let timeLabel = UILabel()
    private let statusLabel = UILabel()

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

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

    /// 应用奖励流水数据。
    func apply(_ item: WalletTransactionItem) {
        amountLabel.text = "¥ \(item.amount)"
        timeLabel.text = item.createdAt
        let label = item.withdrawLabel.isEmpty ? "--" : item.withdrawLabel
        statusLabel.text = label
        let isWithdrawable = label == "可提现"
        statusLabel.textColor = isWithdrawable ? UIColor(hex: 0x22C55E) : UIColor(hex: 0x7B8EAA)
        statusLabel.backgroundColor = isWithdrawable ? AppColor.successBackground : UIColor(hex: 0xF4F4F4)
    }

    private func setupUI() {
        let divider = UIView()
        divider.backgroundColor = UIColor(hex: 0xF3F4F6)
        contentView.addSubview(divider)

        amountLabel.font = .systemFont(ofSize: 16, weight: .medium)
        amountLabel.textColor = .black
        timeLabel.font = .app(.body)
        timeLabel.textColor = UIColor(hex: 0x7B8EAA)
        let textStack = UIStackView(arrangedSubviews: [amountLabel, timeLabel])
        textStack.axis = .vertical
        textStack.spacing = 4
        contentView.addSubview(textStack)

        statusLabel.font = .app(.caption)
        statusLabel.textAlignment = .center
        statusLabel.layer.cornerRadius = 4
        statusLabel.clipsToBounds = true
        contentView.addSubview(statusLabel)

        divider.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.height.equalTo(1)
        }
        textStack.snp.makeConstraints { make in
            make.leading.equalToSuperview()
            make.top.bottom.equalToSuperview().inset(12)
            make.trailing.lessThanOrEqualTo(statusLabel.snp.leading).offset(-12)
        }
        statusLabel.snp.makeConstraints { make in
            make.trailing.equalToSuperview()
            make.centerY.equalToSuperview()
            make.height.equalTo(22)
            make.width.greaterThanOrEqualTo(48)
        }
    }
}

/// 邀请记录列表标题与底部提示单元格。
private final class InviteFooterCell: UITableViewCell {
    static let reuseIdentifier = "InviteFooterCell"

    private let label = UILabel()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        selectionStyle = .none
        label.textAlignment = .center
        contentView.addSubview(label)
        label.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0))
        }
    }

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

    /// 应用标题或底部提示文字。
    func apply(text: String) {
        label.text = text
        if text == "已邀请摄影师" || text == "奖励记录" {
            label.textAlignment = .left
            label.font = .systemFont(ofSize: 16, weight: .medium)
            label.textColor = .black
        } else {
            label.textAlignment = .center
            label.font = .app(.body)
            label.textColor = AppColor.textSecondary
        }
    }
}
