//
//  WithdrawViewController.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 提现申请页面，对齐 Android `WithdrawScreen`。
final class WithdrawViewController: BaseViewController {
    var onSubmitSuccess: (() -> Void)?

    private let viewModel: WithdrawViewModel
    private let walletAPI: any WalletPageServing

    private let scrollView = UIScrollView()
    private let contentStack = UIStackView()
    private let bottomBar = UIView()
    private let submitButton = AppButton(title: "立即提现")
    private let amountField = UITextField()
    private let codeField = UITextField()
    private let codeButton = UIButton(type: .system)
    private let withdrawableLabel = UILabel()
    private let limitLabel = UILabel()
    private let phoneLabel = UILabel()
    private let bankCardLabel = UILabel()
    private let bankHolderLabel = UILabel()
    private let settlementLabel = UILabel()
    private let infoStack = UIStackView()

    private var countdownTimer: Timer?
    private var lastShownMessage: String?

    /// 初始化提现申请页面。
    init(
        viewModel: WithdrawViewModel = WithdrawViewModel(),
        walletAPI: (any WalletPageServing)? = nil
    ) {
        self.viewModel = viewModel
        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")
    }

    deinit {
        countdownTimer?.invalidate()
    }

    override func setupNavigationBar() {
        let titleLabel = UILabel()
        titleLabel.text = "提现设置"
        titleLabel.textColor = WalletTokens.text333
        titleLabel.font = UIFont.systemFont(ofSize: 18)
        navigationItem.titleView = titleLabel
    }

    override func setupUI() {
        view.backgroundColor = WalletTokens.withdrawPageBackground
        contentStack.axis = .vertical
        contentStack.spacing = WalletTokens.cardGap
        contentStack.backgroundColor = .white
        contentStack.layer.cornerRadius = WalletTokens.cardRadius
        contentStack.clipsToBounds = true
        bottomBar.backgroundColor = .white
        bottomBar.isHidden = true

        view.addSubview(scrollView)
        scrollView.addSubview(contentStack)
        view.addSubview(bottomBar)
        bottomBar.addSubview(submitButton)

        contentStack.addArrangedSubview(makeAmountCard())
        contentStack.addArrangedSubview(makeBankCard())
        contentStack.addArrangedSubview(makeSettlementCard())
        contentStack.addArrangedSubview(makeInfoCard())
    }

    override func setupConstraints() {
        bottomBar.snp.makeConstraints { make in
            make.leading.trailing.bottom.equalToSuperview()
        }
        submitButton.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(WalletTokens.screenInset)
            make.leading.trailing.equalToSuperview().inset(WalletTokens.screenInset)
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(WalletTokens.screenInset)
        }
        scrollView.snp.makeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            make.bottom.equalTo(bottomBar.snp.top)
        }
        contentStack.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(WalletTokens.screenInset)
            make.width.equalTo(scrollView).offset(-32)
        }
    }

    override func bindActions() {
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyState() }
        }
        amountField.addTarget(self, action: #selector(amountChanged), for: .editingChanged)
        codeField.addTarget(self, action: #selector(codeChanged), for: .editingChanged)
        codeButton.addTarget(self, action: #selector(sendCodeTapped), for: .touchUpInside)
        submitButton.addTarget(self, action: #selector(submitTapped), for: .touchUpInside)
        Task {
            showLoading()
            await viewModel.load(api: walletAPI)
            hideLoading()
            if viewModel.withdrawInfo == nil, let message = viewModel.errorMessage {
                navigationController?.popViewController(animated: true)
                (navigationController?.topViewController as? BaseViewController)?.showToast(message)
            }
        }
    }

    private func applyState() {
        amountField.text = viewModel.amount
        codeField.text = viewModel.verificationCode
        if let info = viewModel.withdrawInfo {
            withdrawableLabel.text = WalletViewModel.formatAmount(info.amountWithdrawable)
            limitLabel.text = "单笔最高提现 \(WalletViewModel.formatAmount(info.maxSingleWithdrawAmount)), 单日最高提现 \(WalletViewModel.formatAmount(info.maxDailyWithdrawAmount))"
            phoneLabel.text = "验证码将发送至: \(maskPhone(info.userPhone))"
            bankCardLabel.text = "\(info.bankCard.bankName) (尾号\(lastFour(info.bankCard.cardNumber)))"
            bankHolderLabel.text = info.bankCard.realName
            settlementLabel.text = info.settlement
            applyInfoLines(info.withdrawInfo)
        }
        codeButton.setTitle(viewModel.countdown > 0 ? "\(viewModel.countdown)s" : "获取验证码", for: .normal)
        codeButton.isEnabled = viewModel.countdown == 0
        submitButton.isEnabled = viewModel.canSubmit
        updateBottomBarVisibility(hasContent: viewModel.withdrawInfo != nil && !viewModel.loading)
        if viewModel.countdown > 0 { startCountdownTimerIfNeeded() }
        showMessageIfNeeded(viewModel.statusMessage)
        if viewModel.withdrawInfo != nil {
            showMessageIfNeeded(viewModel.errorMessage)
        }
    }

    private func updateBottomBarVisibility(hasContent: Bool) {
        bottomBar.isHidden = !hasContent
        scrollView.snp.remakeConstraints { make in
            make.top.leading.trailing.equalToSuperview()
            if hasContent {
                make.bottom.equalTo(bottomBar.snp.top)
            } else {
                make.bottom.equalToSuperview()
            }
        }
    }

    private func makeAmountCard() -> UIView {
        let card = makeCard()
        let title = makeTitle("提现金额")
        let row = UIStackView()
        row.axis = .horizontal
        row.alignment = .center
        row.spacing = 16
        let withdrawableTitle = makeBodyLabel("可提现金额", color: .black, weight: .medium)
        withdrawableLabel.font = WalletTokens.bodyMediumFont
        withdrawableLabel.textColor = WalletTokens.primary
        row.addArrangedSubview(withdrawableTitle)
        row.addArrangedSubview(withdrawableLabel)

        let amountContainer = borderedInputContainer()
        amountField.placeholder = "请输入金额"
        amountField.keyboardType = .decimalPad
        amountField.font = WalletTokens.bodyFont
        let allButton = UIButton(type: .system)
        allButton.setTitle("全部提现", for: .normal)
        allButton.setTitleColor(WalletTokens.primary, for: .normal)
        allButton.titleLabel?.font = WalletTokens.bodyFont
        allButton.addTarget(self, action: #selector(withdrawAllTapped), for: .touchUpInside)
        amountContainer.addSubview(amountField)
        amountContainer.addSubview(allButton)
        amountField.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(12)
            make.top.bottom.equalToSuperview()
            make.trailing.equalTo(allButton.snp.leading).offset(-8)
        }
        allButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(12)
            make.centerY.equalToSuperview()
        }

        limitLabel.font = WalletTokens.captionFont
        limitLabel.textColor = WalletTokens.textTertiary
        phoneLabel.font = WalletTokens.captionFont
        phoneLabel.textColor = WalletTokens.textSecondary

        let codeRow = UIStackView()
        codeRow.axis = .horizontal
        codeRow.spacing = 12
        let codeContainer = borderedInputContainer()
        codeField.placeholder = "请输入验证码"
        codeField.keyboardType = .numberPad
        codeField.font = WalletTokens.bodyFont
        codeContainer.addSubview(codeField)
        codeField.snp.makeConstraints { make in make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 12, bottom: 0, right: 12)) }
        codeButton.setTitle("获取验证码", for: .normal)
        codeButton.setTitleColor(WalletTokens.primary, for: .normal)
        codeButton.setTitleColor(WalletTokens.textDisabled, for: .disabled)
        codeButton.titleLabel?.font = WalletTokens.bodyMediumFont
        codeButton.layer.borderWidth = 1
        codeButton.layer.borderColor = WalletTokens.border.cgColor
        codeButton.layer.cornerRadius = WalletTokens.chipRadius
        codeRow.addArrangedSubview(codeContainer)
        codeRow.addArrangedSubview(codeButton)
        codeContainer.snp.makeConstraints { make in make.height.equalTo(WalletTokens.inputHeight) }
        codeButton.snp.makeConstraints { make in make.width.equalTo(100) }

        let stack = UIStackView(arrangedSubviews: [title, row, amountContainer, limitLabel, phoneLabel, codeRow])
        stack.axis = .vertical
        stack.spacing = 12
        card.addSubview(stack)
        stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(16) }
        amountContainer.snp.makeConstraints { make in make.height.equalTo(WalletTokens.inputHeight) }
        return card
    }

    private func makeBankCard() -> UIView {
        let card = makeCard()
        let title = makeTitle("银行卡信息", size: 16)
        let inner = makeInnerPanel()
        bankCardLabel.font = WalletTokens.bodyMediumFont
        bankCardLabel.textColor = WalletTokens.text333
        bankHolderLabel.font = WalletTokens.bodyFont
        bankHolderLabel.textColor = WalletTokens.textSecondary
        let innerStack = UIStackView(arrangedSubviews: [bankCardLabel, bankHolderLabel])
        innerStack.axis = .vertical
        innerStack.spacing = 12
        inner.addSubview(innerStack)
        innerStack.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview().inset(WalletTokens.compactGap)
            make.leading.trailing.equalToSuperview().inset(WalletTokens.cardPadding)
        }
        let stack = UIStackView(arrangedSubviews: [title, inner])
        stack.axis = .vertical
        stack.spacing = 8
        card.addSubview(stack)
        stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(16) }
        return card
    }

    private func makeSettlementCard() -> UIView {
        let card = makeCard()
        let title = makeTitle("预计到账时间", size: 16)
        let inner = makeInnerPanel()
        settlementLabel.font = WalletTokens.bodyFont
        settlementLabel.textColor = WalletTokens.textSecondary
        settlementLabel.numberOfLines = 0
        inner.addSubview(settlementLabel)
        settlementLabel.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview().inset(WalletTokens.compactGap)
            make.leading.trailing.equalToSuperview().inset(WalletTokens.cardPadding)
        }
        let stack = UIStackView(arrangedSubviews: [title, inner])
        stack.axis = .vertical
        stack.spacing = WalletTokens.tinyGap
        card.addSubview(stack)
        stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(16) }
        return card
    }

    private func makeInfoCard() -> UIView {
        let card = makeCard()
        let title = makeTitle("提现说明", size: 16)
        let inner = makeInnerPanel()
        infoStack.axis = .vertical
        infoStack.spacing = 4
        inner.addSubview(infoStack)
        infoStack.snp.makeConstraints { make in
            make.top.bottom.equalToSuperview().inset(WalletTokens.compactGap)
            make.leading.trailing.equalToSuperview().inset(WalletTokens.cardPadding)
        }
        let stack = UIStackView(arrangedSubviews: [title, inner])
        stack.axis = .vertical
        stack.spacing = WalletTokens.rowGap
        card.addSubview(stack)
        stack.snp.makeConstraints { make in make.edges.equalToSuperview().inset(16) }
        return card
    }

    private func makeCard() -> UIView {
        let view = UIView()
        view.backgroundColor = .white
        view.layer.cornerRadius = WalletTokens.cardRadius
        view.clipsToBounds = true
        return view
    }

    private func makeInnerPanel() -> UIView {
        let view = UIView()
        view.backgroundColor = WalletTokens.inputBackground
        view.layer.cornerRadius = WalletTokens.innerRadius
        view.layer.borderWidth = 1
        view.layer.borderColor = WalletTokens.border.cgColor
        return view
    }

    private func borderedInputContainer() -> UIView {
        let view = UIView()
        view.layer.cornerRadius = WalletTokens.chipRadius
        view.layer.borderWidth = 1
        view.layer.borderColor = WalletTokens.border.cgColor
        return view
    }

    private func makeTitle(_ text: String, size: CGFloat = 18) -> UILabel {
        let label = UILabel()
        label.text = text
        label.font = .systemFont(ofSize: size, weight: .medium)
        label.textColor = .black
        return label
    }

    private func makeBodyLabel(_ text: String, color: UIColor, weight: UIFont.Weight = .regular) -> UILabel {
        let label = UILabel()
        label.text = text
        label.font = .systemFont(ofSize: 14, weight: weight)
        label.textColor = color
        return label
    }

    private func applyInfoLines(_ lines: [String]) {
        infoStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
        lines.forEach { text in
            let label = makeBodyLabel(text, color: WalletTokens.textSecondary)
            label.numberOfLines = 0
            infoStack.addArrangedSubview(label)
        }
    }

    private func showMessageIfNeeded(_ message: String?) {
        guard let message, !message.isEmpty, message != lastShownMessage else { return }
        lastShownMessage = message
        showToast(message)
    }

    private func startCountdownTimerIfNeeded() {
        guard countdownTimer == nil else { return }
        countdownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
            guard let self else { return }
            self.viewModel.decrementCountdown()
            if self.viewModel.countdown == 0 {
                timer.invalidate()
                self.countdownTimer = nil
            }
        }
    }

    private func maskPhone(_ phone: String) -> String {
        guard phone.count >= 7 else { return phone }
        let prefix = phone.prefix(3)
        let suffix = phone.suffix(4)
        return "\(prefix)****\(suffix)"
    }

    private func lastFour(_ cardNumber: String) -> String {
        String(cardNumber.suffix(4))
    }

    @objc private func amountChanged() {
        viewModel.updateAmount(amountField.text ?? "")
    }

    @objc private func codeChanged() {
        viewModel.updateVerificationCode(codeField.text ?? "")
    }

    @objc private func withdrawAllTapped() {
        viewModel.withdrawAll()
    }

    @objc private func sendCodeTapped() {
        Task { await viewModel.requestVerificationCode(api: walletAPI) }
    }

    @objc private func submitTapped() {
        Task {
            showLoading()
            let success = await viewModel.submit(api: walletAPI)
            hideLoading()
            if success {
                onSubmitSuccess?()
                navigationController?.popViewController(animated: true)
            }
        }
    }
}
