//
//  InviteViewModels.swift
//  suixinkan
//
//  Created by Codex on 2026/6/24.
//

import CoreImage.CIFilterBuiltins
import Foundation
import Combine
import UIKit

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

    private let qrContext = CIContext()
    private let qrFilter = CIFilter.qrCodeGenerator()

    /// 重新加载邀请信息。
    func reload(api: any InviteServing) async {
        loading = true
        errorMessage = nil
        defer { loading = false }
        do {
            let response = try await api.inviteInfo()
            inviteCode = response.inviteCode
            inviteUrl = response.inviteUrl
            rules = response.description
            qrImage = makeQrImage(from: response.inviteUrl)
        } catch {
            clear()
            errorMessage = error.localizedDescription
        }
    }

    /// 复制邀请码。
    func copyInviteCode() {
        UIPasteboard.general.string = inviteCode
    }

    /// 复制邀请链接。
    func copyInviteUrl() {
        UIPasteboard.general.string = inviteUrl
    }

    /// 根据文本生成二维码图片。
    func makeQrImage(from text: String) -> UIImage? {
        guard !text.isEmpty else { return nil }
        qrFilter.setValue(Data(text.utf8), forKey: "inputMessage")
        qrFilter.setValue("M", forKey: "inputCorrectionLevel")
        guard let output = qrFilter.outputImage else { return nil }
        let scaled = output.transformed(by: CGAffineTransform(scaleX: 12, y: 12))
        guard let cgImage = qrContext.createCGImage(scaled, from: scaled.extent) else { return nil }
        return UIImage(cgImage: cgImage)
    }

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

/// 邀请记录 ViewModel，负责邀请用户、奖励明细和钱包汇总分页。
@MainActor
final class InviteRecordViewModel: ObservableObject {
    @Published var tab: InviteRecordTab = .invite
    @Published private(set) var totalRewardText = "¥ 0.00"
    @Published private(set) var withdrawableText = "¥ 0.00"
    @Published private(set) var displayRows: [InviteDisplayRow] = []
    @Published private(set) var loading = false
    @Published private(set) var loadingMore = false
    @Published private(set) var hasMore = false
    @Published var errorMessage: String?

    @Published private var inviteRows: [InviteDisplayRow] = []
    @Published private var rewardRows: [InviteDisplayRow] = []
    @Published private var invitePage = 1
    @Published private var rewardPage = 1
    private let invitePageSize = 20
    private let rewardPageSize = 10

    /// 重新加载或追加邀请记录数据。
    func reload(inviteAPI: any InviteServing, walletAPI: any WalletServing, refresh: Bool) async {
        if refresh {
            loading = true
        } else {
            guard hasMore else { return }
            loadingMore = true
        }
        errorMessage = nil
        defer {
            loading = false
            loadingMore = false
        }

        do {
            async let summary = walletAPI.walletSummary(type: 2)
            if tab == .invite {
                try await loadInviteRows(api: inviteAPI, refresh: refresh)
            } else {
                try await loadRewardRows(api: walletAPI, refresh: refresh)
            }
            let summaryValue = try await summary
            totalRewardText = "¥ \(summaryValue.amountTotal)"
            withdrawableText = "¥ \(summaryValue.amountWithdrawable)"
            displayRows = tab == .invite ? inviteRows : rewardRows
        } catch {
            if refresh {
                clear()
            }
            errorMessage = error.localizedDescription
        }
    }

    /// 切换邀请记录分段并刷新。
    func selectTab(_ newTab: InviteRecordTab, inviteAPI: any InviteServing, walletAPI: any WalletServing) async {
        tab = newTab
        await reload(inviteAPI: inviteAPI, walletAPI: walletAPI, refresh: true)
    }

    private func loadInviteRows(api: any InviteServing, refresh: Bool) async throws {
        let users = try await api.inviteUserList(page: refresh ? 1 : invitePage, pageSize: invitePageSize)
        let mapped = users.map {
            InviteDisplayRow(
                id: "invite_\($0.id)",
                title: $0.realName.isEmpty ? "**\($0.phone.suffix(4))" : $0.realName,
                subtitle: "",
                amount: "",
                time: $0.createdAt,
                phone: $0.phone,
                avatar: $0.avatar,
                inviteLevel: $0.inviteLevel
            )
        }
        if refresh {
            inviteRows = mapped
            invitePage = 2
        } else {
            inviteRows.append(contentsOf: mapped)
            invitePage += 1
        }
        hasMore = users.count >= invitePageSize
    }

    private func loadRewardRows(api: any WalletServing, refresh: Bool) async throws {
        let response = try await api.walletEarningDetail(
            startDate: "2025-01-01",
            endDate: Self.dayFormatter.string(from: Date()),
            page: refresh ? 1 : rewardPage,
            pageSize: rewardPageSize
        )
        let mapped = response.list.flatMap { group in
            group.items.map {
                InviteDisplayRow(
                    id: "reward_\($0.id)",
                    title: $0.typeLabel.isEmpty ? "奖励记录" : $0.typeLabel,
                    subtitle: $0.withdrawLabel ?? "订单尾号：\($0.orderNumberSuffix.isEmpty ? "--" : $0.orderNumberSuffix)",
                    amount: $0.amount.isEmpty ? "--" : $0.amount,
                    time: $0.createdAt.isEmpty ? group.date : $0.createdAt,
                    phone: "",
                    avatar: "",
                    inviteLevel: 0
                )
            }
        }
        if refresh {
            rewardRows = mapped
            rewardPage = 2
        } else {
            rewardRows.append(contentsOf: mapped)
            rewardPage += 1
        }
        hasMore = rewardRows.count < response.total && !mapped.isEmpty
    }

    private func clear() {
        totalRewardText = "¥ 0.00"
        withdrawableText = "¥ 0.00"
        displayRows = []
        inviteRows = []
        rewardRows = []
        invitePage = 1
        rewardPage = 1
        hasMore = false
    }

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