//
//  InviteViewModels.swift
//  suixinkan
//

import Foundation
import UIKit

/// 邀请页 ViewModel，负责加载邀请信息、生成二维码和暴露复制内容。
final class PhotographerInviteViewModel {
    private(set) var isLoading = false
    private(set) var inviteCode = ""
    private(set) var inviteUrl = ""
    private(set) var rules: [String] = []
    private(set) var qrImage: UIImage?
    private(set) var errorMessage: String?

    var onStateChange: (() -> Void)?

    /// 重新加载邀请信息。
    func reload(api: any InviteServing) async {
        isLoading = true
        errorMessage = nil
        notifyStateChange()

        do {
            let response = try await api.inviteInfo()
            inviteCode = response.inviteCode
            inviteUrl = response.inviteUrl
            rules = response.description
            qrImage = QRCodeGenerator.generateStyledQRCode(
                content: response.inviteUrl,
                pixelSize: 560,
                backgroundColor: .white,
                cornerRadius: 0
            )
        } catch {
            clear()
            errorMessage = error.localizedDescription
        }

        isLoading = false
        notifyStateChange()
    }

    /// 返回待复制的邀请码。
    func inviteCodeForCopy() -> String {
        inviteCode
    }

    /// 返回待复制的邀请链接。
    func inviteUrlForCopy() -> String {
        inviteUrl
    }

    private func clear() {
        inviteCode = ""
        inviteUrl = ""
        rules = []
        qrImage = nil
    }

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

/// 邀请记录 ViewModel，负责邀请用户、奖励流水和钱包汇总分页。
final class InviteRecordViewModel {
    private(set) var selectedTab: InviteRecordTab = .invite
    private(set) var totalRewardText = "0.00"
    private(set) var withdrawableText = "0.00"
    private(set) var inviteRows: [InviteDisplayRow] = []
    private(set) var rewardRows: [WalletTransactionItem] = []
    private(set) var isInviteRefreshing = false
    private(set) var isRewardRefreshing = false
    private(set) var canLoadMoreInvite = false
    private(set) var canLoadMoreReward = false
    private(set) var errorMessage: String?

    var onStateChange: (() -> Void)?

    private var invitePage = 1
    private let invitePageSize = 20
    private var rewardPage = 1
    private let rewardPageSize = 10
    private var isLoadingInvite = false
    private var isLoadingReward = false

    /// 初次加载邀请记录和钱包汇总。
    func loadInitial(inviteAPI: any InviteServing, walletAPI: any WalletServing) async {
        await refreshInvite(inviteAPI: inviteAPI, walletAPI: walletAPI)
    }

    /// 切换分段并在需要时加载奖励记录。
    func selectTab(_ tab: InviteRecordTab, inviteAPI: any InviteServing, walletAPI: any WalletServing) async {
        guard tab != selectedTab else { return }
        selectedTab = tab
        notifyStateChange()
        if tab == .reward, rewardRows.isEmpty {
            await refreshReward(walletAPI: walletAPI)
        }
    }

    /// 刷新邀请记录和钱包汇总。
    func refreshInvite(inviteAPI: any InviteServing, walletAPI: any WalletServing) async {
        await loadSummary(walletAPI: walletAPI)
        await loadInviteRows(inviteAPI: inviteAPI, refresh: true)
    }

    /// 加载下一页邀请记录。
    func loadMoreInvite(inviteAPI: any InviteServing) async {
        guard canLoadMoreInvite, !isInviteRefreshing else { return }
        await loadInviteRows(inviteAPI: inviteAPI, refresh: false)
    }

    /// 刷新奖励记录和钱包汇总。
    func refreshReward(walletAPI: any WalletServing) async {
        await loadSummary(walletAPI: walletAPI)
        await loadRewardRows(walletAPI: walletAPI, refresh: true)
    }

    /// 加载下一页奖励记录。
    func loadMoreReward(walletAPI: any WalletServing) async {
        guard canLoadMoreReward, !isRewardRefreshing else { return }
        await loadRewardRows(walletAPI: walletAPI, refresh: false)
    }

    private func loadSummary(walletAPI: any WalletServing) async {
        do {
            let summary = try await walletAPI.walletSummary(type: 2)
            totalRewardText = summary.amountTotal.isEmpty ? "0.00" : summary.amountTotal
            withdrawableText = summary.amountWithdrawable.isEmpty ? "0.00" : summary.amountWithdrawable
        } catch {
            errorMessage = error.localizedDescription
        }
        notifyStateChange()
    }

    private func loadInviteRows(inviteAPI: any InviteServing, refresh: Bool) async {
        if isLoadingInvite && !refresh { return }
        if refresh { invitePage = 1 }
        isLoadingInvite = true
        isInviteRefreshing = refresh
        errorMessage = nil
        notifyStateChange()

        do {
            let users = try await inviteAPI.inviteUserList(page: invitePage, pageSize: invitePageSize)
            let mapped = users.map { user in
                InviteDisplayRow(
                    id: "invite_\(user.id)",
                    title: user.realName.isEmpty ? "**\(user.phone.suffix(4))" : user.realName,
                    phone: user.phone,
                    avatar: user.avatar,
                    time: user.createdAt,
                    inviteLevel: user.inviteLevel
                )
            }
            inviteRows = refresh ? mapped : inviteRows + mapped
            invitePage += 1
            canLoadMoreInvite = users.count >= invitePageSize
        } catch {
            if refresh {
                inviteRows = []
                canLoadMoreInvite = false
            }
            errorMessage = error.localizedDescription
        }

        isLoadingInvite = false
        isInviteRefreshing = false
        notifyStateChange()
    }

    private func loadRewardRows(walletAPI: any WalletServing, refresh: Bool) async {
        if isLoadingReward && !refresh { return }
        if refresh { rewardPage = 1 }
        isLoadingReward = true
        isRewardRefreshing = refresh
        errorMessage = nil
        notifyStateChange()

        do {
            let response = try await walletAPI.walletTransactionList(
                startDate: "2025-01-01",
                endDate: Self.dayFormatter.string(from: Date()),
                page: rewardPage,
                pageSize: rewardPageSize,
                type: 2
            )
            rewardRows = refresh ? response.list : rewardRows + response.list
            rewardPage += 1
            canLoadMoreReward = response.list.count >= rewardPageSize && rewardRows.count < response.total
        } catch {
            if refresh {
                rewardRows = []
                canLoadMoreReward = false
            }
            errorMessage = error.localizedDescription
        }

        isLoadingReward = false
        isRewardRefreshing = false
        notifyStateChange()
    }

    private func notifyStateChange() {
        onStateChange?()
    }

    private static let dayFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
}
