//
//  StatisticsView.swift
//  suixinkan
//
//  Created by Codex on 2026/6/22.
//

import SwiftUI

/// 数据 Tab 根视图，展示订单统计汇总和每日明细。
struct StatisticsView: View {
    @Environment(AccountContext.self) private var accountContext
    @Environment(PermissionContext.self) private var permissionContext
    @Environment(StatisticsAPI.self) private var statisticsAPI
    @Environment(ToastCenter.self) private var toastCenter
    @Environment(\.globalLoading) private var globalLoading
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass

    @State private var viewModel = StatisticsViewModel()

    private var currentScenicId: Int? {
        accountContext.currentScenic?.id
    }

    private var currentRoleId: Int? {
        permissionContext.currentRole?.id
    }

    private var contentMaxWidth: CGFloat {
        horizontalSizeClass == .regular ? 900 : .infinity
    }

    var body: some View {
        Group {
            if currentScenicId == nil {
                ContentUnavailableView(
                    "缺少经营上下文",
                    systemImage: "chart.bar.doc.horizontal",
                    description: Text("请先在首页选择景区后查看数据看板。")
                )
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
            } else {
                ScrollView {
                    VStack(spacing: AppMetrics.Spacing.medium) {
                        overviewCard
                        detailCard
                    }
                    .frame(maxWidth: contentMaxWidth)
                    .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
                    .padding(.top, AppMetrics.Spacing.medium)
                    .padding(.bottom, AppMetrics.Spacing.pageVertical)
                    .frame(maxWidth: .infinity)
                }
                .refreshable { await reload(showLoading: false) }
                .background(Color(hex: 0xF5F5F5).ignoresSafeArea())
            }
        }
        .navigationTitle("数据")
        .navigationBarTitleDisplayMode(.inline)
        .task { await reload() }
        .onChange(of: accountContext.currentScenic?.id) { _, _ in
            Task { await reload() }
        }
        .onChange(of: permissionContext.currentRole?.id) { _, _ in
            Task { await reload() }
        }
    }

    private var overviewCard: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack(spacing: 0) {
                Text("已选日期：")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.textPrimary)
                Text(viewModel.selectedPeriod.selectedTimeText)
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.primary)
                    .lineLimit(1)
                    .minimumScaleFactor(0.8)
            }

            HStack(spacing: AppMetrics.Spacing.small) {
                ForEach(StatisticsPeriod.allCases) { period in
                    periodButton(period)
                }
            }

            VStack(spacing: AppMetrics.Spacing.small) {
                statCard(
                    title: "订单总金额",
                    value: amountText(viewModel.summary.orderAmountValue),
                    textColor: Color(hex: 0x22C55E),
                    backgroundColor: Color(hex: 0xF0FDF4),
                    icon: "doc.text.fill"
                )

                HStack(spacing: AppMetrics.Spacing.small) {
                    statCard(
                        title: "订单总数",
                        value: "\(viewModel.summary.orderCount)单",
                        textColor: Color(hex: 0x7F00FF),
                        backgroundColor: Color(hex: 0xEBD8FF),
                        icon: "chart.bar.fill"
                    )
                    statCard(
                        title: "实收金额",
                        value: amountText(viewModel.summary.receivedAmountValue),
                        textColor: Color(hex: 0x22C55E),
                        backgroundColor: Color(hex: 0xFFF0E2),
                        icon: "yensign.circle.fill"
                    )
                }

                HStack(spacing: AppMetrics.Spacing.small) {
                    statCard(
                        title: "客单价",
                        value: amountText(viewModel.summary.orderPriceAverageValue),
                        textColor: AppDesign.primary,
                        backgroundColor: Color(hex: 0xEFF6FF),
                        icon: "tag.fill"
                    )
                    statCard(
                        title: "退款金额",
                        value: amountText(viewModel.summary.refundAmountValue),
                        textColor: Color(hex: 0xEF4444),
                        backgroundColor: Color(hex: 0xFFE7E7),
                        icon: "arrow.down.doc.fill"
                    )
                }
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: 8))
    }

    private var detailCard: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text("时间范围")
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .bold))
                    .foregroundStyle(.black)
                Spacer()
                Menu {
                    ForEach(StatisticsPeriod.allCases) { period in
                        Button(period.rawValue) {
                            Task { await selectPeriod(period) }
                        }
                    }
                } label: {
                    HStack(spacing: AppMetrics.Spacing.xSmall) {
                        Text(viewModel.selectedPeriod.rawValue)
                            .font(.system(size: AppMetrics.FontSize.subheadline))
                            .foregroundStyle(Color(hex: 0x4B5563))
                        Spacer(minLength: AppMetrics.Spacing.small)
                        Image(systemName: "chevron.down")
                            .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                            .foregroundStyle(Color(hex: 0x4B5563))
                    }
                    .padding(.horizontal, AppMetrics.Spacing.small)
                    .frame(width: 166, height: 36)
                    .background(Color(hex: 0xF4F4F4), in: RoundedRectangle(cornerRadius: 6))
                }
                .buttonStyle(.plain)
            }

            Divider()

            if viewModel.loading && viewModel.dailyItems.isEmpty {
                Color.clear
                    .frame(maxWidth: .infinity)
                    .frame(minHeight: 280)
            } else if viewModel.dailyItems.isEmpty {
                ContentUnavailableView("暂无数据", systemImage: "tray", description: Text("可切换时间范围或下拉刷新。"))
                    .frame(minHeight: 280)
            } else {
                VStack(spacing: 0) {
                    ForEach(viewModel.dailyItems) { item in
                        dailyDataRow(item)
                            .onAppear {
                                guard item.id == viewModel.dailyItems.last?.id else { return }
                                Task { await loadMore() }
                            }
                        if item.id != viewModel.dailyItems.last?.id {
                            Divider()
                        }
                    }
                    if viewModel.loadingMore {
                        ProgressView()
                            .frame(maxWidth: .infinity)
                            .padding(.vertical, AppMetrics.Spacing.small)
                    }
                }
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .frame(minHeight: 420, alignment: .top)
        .background(.white, in: RoundedRectangle(cornerRadius: 8))
    }

    private func periodButton(_ period: StatisticsPeriod) -> some View {
        let isSelected = period == viewModel.selectedPeriod
        return Button {
            Task { await selectPeriod(period) }
        } label: {
            Text(period.rawValue)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: isSelected ? .semibold : .medium))
                .foregroundStyle(isSelected ? .white : Color(hex: 0x4B5563))
                .frame(maxWidth: .infinity)
                .frame(height: 34)
                .background(isSelected ? AppDesign.primary : Color(hex: 0xF3F4F6), in: RoundedRectangle(cornerRadius: 17))
        }
        .buttonStyle(.plain)
    }

    private func statCard(title: String, value: String, textColor: Color, backgroundColor: Color, icon: String) -> some View {
        HStack(spacing: AppMetrics.Spacing.xSmall) {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxxSmall) {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(.black.opacity(0.6))
                    .lineLimit(1)
                Text(value)
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .bold))
                    .foregroundStyle(textColor)
                    .lineLimit(1)
                    .minimumScaleFactor(0.72)
            }
            Spacer(minLength: AppMetrics.Spacing.xxSmall)
            statisticIcon(symbol: icon, color: textColor)
        }
        .padding(.horizontal, AppMetrics.Spacing.small)
        .padding(.vertical, AppMetrics.Spacing.small)
        .frame(maxWidth: .infinity)
        .background(backgroundColor, in: RoundedRectangle(cornerRadius: 8))
    }

    private func statisticIcon(symbol: String, color: Color) -> some View {
        ZStack {
            RoundedRectangle(cornerRadius: 7)
                .fill(color.opacity(0.22))
                .frame(width: 30, height: 30)
                .offset(x: 6, y: 6)
            RoundedRectangle(cornerRadius: 7)
                .fill(color.opacity(0.9))
                .frame(width: 30, height: 30)
                .offset(x: -6, y: -6)
            Image(systemName: symbol)
                .font(.system(size: AppMetrics.FontSize.title3, weight: .bold))
                .foregroundStyle(.white)
        }
        .frame(width: 46, height: 46)
    }

    private func dailyDataRow(_ item: StatisticsDailyItem) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            Text(item.date)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(.black)

            HStack(alignment: .top) {
                dataColumn("订单数", "\(item.orderCount)", .black)
                dataColumn("客单价", amountText(item.orderPriceValue), .black)
                dataColumn("退款", amountText(item.refundValue), Color(hex: 0xEF4444))
                dataColumn("实收", amountText(item.receivedValue), Color(hex: 0x22C55E))
            }
        }
        .padding(.vertical, AppMetrics.Spacing.small)
    }

    private func dataColumn(_ title: String, _ value: String, _ color: Color) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxSmall) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(Color(hex: 0x4B5563))
            Text(value)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(color)
                .lineLimit(1)
                .minimumScaleFactor(0.65)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    private func amountText(_ value: Double) -> String {
        "¥\(String(format: "%.2f", value))"
    }

    private func selectPeriod(_ period: StatisticsPeriod) async {
        do {
            try await globalLoading.withLoading(message: "加载中...") {
                try await viewModel.selectPeriod(period, api: statisticsAPI, scenicId: currentScenicId, roleId: currentRoleId)
            }
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    private func reload(showLoading: Bool = true) async {
        do {
            try await globalLoading.withOptionalLoading(showLoading && currentScenicId != nil && viewModel.dailyItems.isEmpty, message: "加载中...") {
                try await viewModel.reload(api: statisticsAPI, scenicId: currentScenicId, roleId: currentRoleId, showLoading: showLoading)
            }
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    private func loadMore() async {
        do {
            try await viewModel.loadMore(api: statisticsAPI, scenicId: currentScenicId, roleId: currentRoleId)
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }
}

#Preview {
    NavigationStack {
        StatisticsView()
            .environment(AccountContext())
            .environment(PermissionContext())
            .environment(StatisticsAPI(client: APIClient()))
            .environment(ToastCenter())
    }
}
