<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Models\ProductVariant;
use App\Models\ManualPaymentSubmission;
use App\Models\ProviderLog;
use App\Models\StockCode;
use App\Models\User;
use Symfony\Component\HttpFoundation\StreamedResponse;

class AdminExportController extends Controller
{
    public function orders(): StreamedResponse
    {
        return $this->download('orders-export.csv', [
            'order_number', 'customer_name', 'customer_email', 'total', 'currency', 'payment_status', 'fulfillment_status', 'created_at',
        ], Order::latest()->cursor()->map(fn ($order) => [
            $order->order_number,
            $order->customer_name,
            $order->customer_email,
            number_format($order->total_minor / 100, 2, '.', ''),
            $order->currency_code,
            $order->payment_status,
            $order->fulfillment_status,
            $order->created_at?->toDateTimeString(),
        ]));
    }

    public function customers(): StreamedResponse
    {
        return $this->download('customers-export.csv', [
            'public_id', 'name', 'display_name', 'email', 'phone', 'status', 'orders_count', 'total_spent', 'risk_score', 'created_at',
        ], User::where('role', '!=', 'admin')->latest()->cursor()->map(fn ($user) => [
            $user->public_id,
            $user->name,
            $user->display_name,
            $user->email,
            $user->phone,
            $user->status,
            $user->orders_count,
            number_format($user->total_spent_minor / 100, 2, '.', ''),
            $user->risk_score,
            $user->created_at?->toDateTimeString(),
        ]));
    }

    public function products(): StreamedResponse
    {
        return $this->download('products-export.csv', [
            'sku', 'name_ar', 'name_en', 'price', 'cost', 'stock_available', 'min_stock_alert', 'delivery_method', 'status',
        ], ProductVariant::latest()->cursor()->map(fn ($product) => [
            $product->sku,
            $product->name_ar,
            $product->name_en,
            number_format($product->price_minor / 100, 2, '.', ''),
            number_format($product->cost_minor / 100, 2, '.', ''),
            $product->stock_available,
            $product->min_stock_alert,
            $product->delivery_method,
            $product->status,
        ]));
    }

    public function stockCodes(): StreamedResponse
    {
        return $this->download('stock-codes-export.csv', [
            'product', 'sku', 'batch', 'serial_number', 'status', 'cost', 'currency', 'expires_at', 'reserved_order_id', 'sold_order_item_id', 'provider_id',
        ], StockCode::with('productVariant')->latest()->cursor()->map(fn ($code) => [
            $code->productVariant?->name_ar,
            $code->productVariant?->sku,
            $code->batch_reference,
            $code->serial_number,
            $code->status,
            number_format($code->cost_minor / 100, 2, '.', ''),
            $code->currency_code,
            $code->expires_at?->toDateString(),
            $code->reserved_order_id,
            $code->sold_order_item_id,
            $code->provider_id,
        ]));
    }

    public function manualPayments(): StreamedResponse
    {
        return $this->download('manual-payments-export.csv', [
            'id', 'gateway', 'payer_name', 'payer_identifier', 'amount', 'currency', 'status', 'risk_score', 'reviewer', 'order_number', 'created_at', 'reviewed_at',
        ], ManualPaymentSubmission::with(['gateway', 'reviewer', 'order'])->latest()->cursor()->map(fn ($submission) => [
            $submission->id,
            $submission->gateway?->name_ar,
            $submission->payer_name,
            $submission->payer_identifier,
            number_format($submission->amount_minor / 100, 2, '.', ''),
            $submission->currency_code,
            $submission->status,
            $submission->risk_score,
            $submission->reviewer?->email,
            $submission->order?->order_number,
            $submission->created_at?->toDateTimeString(),
            $submission->reviewed_at?->toDateTimeString(),
        ]));
    }

    public function providerLogs(): StreamedResponse
    {
        return $this->download('provider-logs-export.csv', [
            'id', 'provider', 'endpoint', 'status', 'status_code', 'latency_ms', 'order_number', 'order_item_id', 'created_at',
        ], ProviderLog::with(['provider', 'order'])->latest()->cursor()->map(fn ($log) => [
            $log->id,
            $log->provider?->name,
            $log->endpoint,
            $log->status,
            $log->status_code,
            $log->latency_ms,
            $log->order?->order_number,
            $log->order_item_id,
            $log->created_at?->toDateTimeString(),
        ]));
    }

    private function download(string $filename, array $header, iterable $rows): StreamedResponse
    {
        return response()->streamDownload(function () use ($header, $rows) {
            $output = fopen('php://output', 'w');
            fputcsv($output, $header);

            foreach ($rows as $row) {
                fputcsv($output, $row);
            }

            fclose($output);
        }, $filename, ['Content-Type' => 'text/csv; charset=UTF-8']);
    }
}
