<?php

namespace App\Http\Controllers;

use App\Models\Customer;
use App\Models\PaymentMethod;
use App\Models\Sale;
use App\Models\SaleItem;
use App\Models\SaleType;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

class SalesDashboardController extends Controller
{
    public function export(Request $request)
    {
        try {
            $request->validate([
                'export_format' => 'required|in:pdf,excel,csv',
                'export_date_from' => 'required|date',
                'export_date_to' => 'required|date|after_or_equal:export_date_from',
            ]);

            $format = $request->get('export_format');
            $dateFrom = Carbon::parse($request->get('export_date_from'));
            $dateTo = Carbon::parse($request->get('export_date_to'));

            $startDate = $dateFrom->startOfDay();
            $endDate = $dateTo->endOfDay();

            logger()->info('Export request received', [
                'format' => $format,
                'dateFrom' => $dateFrom,
                'dateTo' => $dateTo,
            ]);

            // Get all the data for export
            $salesTrends = $this->getSalesTrends($startDate, $endDate);
            $revenueByPaymentMethod = $this->getRevenueByPaymentMethod($startDate, $endDate);
            $topProducts = $this->getTopProducts($startDate, $endDate);
            $salesByUser = $this->getSalesByUser($startDate, $endDate);
            $customerMetrics = $this->getCustomerMetrics($startDate, $endDate);
            $salesSummary = $this->getSalesSummary($startDate, $endDate);
            $salesByType = $this->getSalesByType($startDate, $endDate);

            $filename = 'sales_performance_report_'.$dateFrom->format('Y-m-d').'_to_'.$dateTo->format('Y-m-d').'.'.$format;

            switch ($format) {
                case 'csv':
                    return $this->exportToCsv($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $filename, $dateFrom, $dateTo);
                case 'excel':
                    return $this->exportToExcel($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $filename, $dateFrom, $dateTo);
                case 'pdf':
                    return $this->exportToPdf($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $customerMetrics, $filename, $dateFrom, $dateTo);
                default:
                    return redirect()->back()->with('error', 'Format d\'export non supporté.');
            }
        } catch (\Exception $e) {
            logger()->error('Export failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return redirect()->back()->with('error', 'Erreur lors de l\'export: '.$e->getMessage());
        }
    }

    public function print(Request $request)
    {
        try {
            $request->validate([
                'print_date_from' => 'required|date',
                'print_date_to' => 'required|date|after_or_equal:print_date_from',
            ]);

            $dateFrom = Carbon::parse($request->get('print_date_from'));
            $dateTo = Carbon::parse($request->get('print_date_to'));

            $startDate = $dateFrom->startOfDay();
            $endDate = $dateTo->endOfDay();

            // Get all the data for print
            $salesTrends = $this->getSalesTrends($startDate, $endDate);
            $revenueByPaymentMethod = $this->getRevenueByPaymentMethod($startDate, $endDate);
            $topProducts = $this->getTopProducts($startDate, $endDate);
            $salesByUser = $this->getSalesByUser($startDate, $endDate);
            $customerMetrics = $this->getCustomerMetrics($startDate, $endDate);
            $salesSummary = $this->getSalesSummary($startDate, $endDate);
            $salesByType = $this->getSalesByType($startDate, $endDate);

            return view('livewire.reports.sales.print', [
                'salesSummary' => $salesSummary,
                'salesTrends' => $salesTrends,
                'revenueByPaymentMethod' => $revenueByPaymentMethod,
                'topProducts' => $topProducts,
                'salesByUser' => $salesByUser,
                'salesByType' => $salesByType,
                'customerMetrics' => $customerMetrics,
                'dateFrom' => $dateFrom,
                'dateTo' => $dateTo,
            ]);
        } catch (\Exception $e) {
            return redirect()->back()->with('error', 'Erreur lors de l\'impression: '.$e->getMessage());
        }
    }

    private function exportToCsv($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $filename, $dateFrom, $dateTo)
    {
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="'.$filename.'"',
        ];

        $callback = function () use ($salesSummary, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $dateFrom, $dateTo) {
            $file = fopen('php://output', 'w');

            // Add BOM for UTF-8
            fwrite($file, "\xEF\xBB\xBF");

            // Header
            fputcsv($file, ['RAPPORT DE PERFORMANCE DES VENTES']);
            fputcsv($file, ['Période', $dateFrom->format('d/m/Y').' - '.$dateTo->format('d/m/Y')]);
            fputcsv($file, ['Date de génération', now()->format('d/m/Y H:i')]);
            fputcsv($file, []);

            // Sales Summary
            fputcsv($file, ['RÉSUMÉ DES VENTES']);
            fputcsv($file, ['Chiffre d\'affaires total', number_format($salesSummary['total_revenue'], 0, ',', ' ').' FC']);
            fputcsv($file, ['Nombre total de ventes', number_format($salesSummary['total_sales'])]);
            fputcsv($file, ['Vente moyenne', number_format($salesSummary['average_sale'], 0, ',', ' ').' FC']);
            fputcsv($file, ['Croissance des revenus', $salesSummary['revenue_growth'].'%']);
            fputcsv($file, ['Croissance des ventes', $salesSummary['sales_growth'].'%']);
            fputcsv($file, []);

            // Top Products
            fputcsv($file, ['TOP 10 PRODUITS']);
            fputcsv($file, ['Produit', 'Catégorie', 'Quantité vendue', 'Revenus (FC)']);
            foreach ($topProducts as $product) {
                fputcsv($file, [
                    $product['product']->name,
                    $product['product']->category->name ?? 'N/A',
                    number_format($product['total_quantity']),
                    number_format($product['total_revenue'], 0, ',', ' '),
                ]);
            }
            fputcsv($file, []);

            // Sales by User
            fputcsv($file, ['PERFORMANCE PAR UTILISATEUR']);
            fputcsv($file, ['Utilisateur', 'Rôle', 'Nombre de ventes', 'Revenus (FC)']);
            foreach ($salesByUser as $user) {
                fputcsv($file, [
                    $user['user']->firstname.' '.$user['user']->lastname,
                    $user['user']->role,
                    number_format($user['sales_count']),
                    number_format($user['total_revenue'], 0, ',', ' '),
                ]);
            }
            fputcsv($file, []);

            // Revenue by Payment Method
            fputcsv($file, ['REVENUS PAR MÉTHODE DE PAIEMENT']);
            fputcsv($file, ['Méthode de paiement', 'Revenus (FC)', 'Pourcentage']);
            foreach ($revenueByPaymentMethod as $method) {
                fputcsv($file, [
                    $method['method'],
                    number_format($method['amount'], 0, ',', ' '),
                    number_format($method['percentage'], 1).'%',
                ]);
            }
            fputcsv($file, []);

            // Sales by Type
            fputcsv($file, ['VENTES PAR TYPE']);
            fputcsv($file, ['Type de vente', 'Nombre de ventes', 'Revenus (FC)', 'Pourcentage']);
            foreach ($salesByType as $type) {
                fputcsv($file, [
                    $type['type'],
                    number_format($type['count']),
                    number_format($type['amount'], 0, ',', ' '),
                    number_format($type['percentage'], 1).'%',
                ]);
            }

            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    private function exportToExcel($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $filename, $dateFrom, $dateTo)
    {
        $export = new \App\Exports\SalesPerformanceExport($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $dateFrom, $dateTo);

        return Excel::download($export, $filename);
    }

    private function exportToPdf($salesSummary, $salesTrends, $revenueByPaymentMethod, $topProducts, $salesByUser, $salesByType, $customerMetrics, $filename, $dateFrom, $dateTo)
    {
        try {
            logger()->info('Starting PDF export', ['filename' => $filename]);

            // Debug data structure
            logger()->info('Sales by User data', [
                'count' => $salesByUser->count(),
                'first_user' => $salesByUser->first() ? [
                    'user_exists' => isset($salesByUser->first()['user']),
                    'user_name' => $salesByUser->first()['user']->firstname ?? 'no firstname',
                ] : 'no data',
            ]);

            $pdf = Pdf::loadView('livewire.reports.sales.export-pdf', [
                'salesSummary' => $salesSummary,
                'salesTrends' => $salesTrends,
                'revenueByPaymentMethod' => $revenueByPaymentMethod,
                'topProducts' => $topProducts,
                'salesByUser' => $salesByUser,
                'salesByType' => $salesByType,
                'customerMetrics' => $customerMetrics,
                'dateFrom' => $dateFrom,
                'dateTo' => $dateTo,
            ]);

            $pdf->setPaper('A4', 'portrait');
            $pdf->setOptions([
                'isHtml5ParserEnabled' => true,
                'isRemoteEnabled' => true,
                'defaultFont' => 'Arial',
            ]);

            logger()->info('PDF generated successfully', ['filename' => $filename]);

            // Try different download methods
            $response = $pdf->download($filename);
            logger()->info('PDF download response created', [
                'filename' => $filename,
                'response_type' => get_class($response),
                'headers' => $response->headers->all(),
            ]);

            return $response;

        } catch (\Exception $e) {
            logger()->error('PDF export failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return redirect()->back()->with('error', 'Erreur lors de la génération du PDF: '.$e->getMessage());
        }
    }

    private function getSalesTrends($startDate, $endDate): array
    {
        $trends = [];
        $current = $startDate->copy();

        while ($current->lte($endDate)) {
            $dayStart = $current->copy()->startOfDay();
            $dayEnd = $current->copy()->endOfDay();

            $sales = Sale::whereBetween('created_at', [$dayStart, $dayEnd])
                ->where('status', Sale::STATUS_COMPLETED)
                ->get();

            $trends[] = [
                'date' => $current->format('Y-m-d'),
                'date_label' => $current->format('d/m'),
                'sales_count' => $sales->count(),
                'revenue' => $sales->sum('total_amount'),
                'transactions' => $sales->count(),
                'average_sale' => $sales->count() > 0 ? $sales->sum('total_amount') / $sales->count() : 0,
            ];

            $current->addDay();
        }

        return $trends;
    }

    private function getRevenueByPaymentMethod($startDate, $endDate): \Illuminate\Support\Collection
    {
        $paymentMethods = PaymentMethod::all();
        $revenue = [];

        foreach ($paymentMethods as $method) {
            $total = Sale::where('payment_method_id', $method->id)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->where('status', Sale::STATUS_COMPLETED)
                ->sum('total_amount');

            $count = Sale::where('payment_method_id', $method->id)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->where('status', Sale::STATUS_COMPLETED)
                ->count();

            $revenue[] = [
                'method' => $method->name,
                'amount' => $total,
                'count' => $count,
                'percentage' => 0,
            ];
        }

        // Calculate percentages
        $totalRevenue = collect($revenue)->sum('amount');
        foreach ($revenue as &$item) {
            $item['percentage'] = $totalRevenue > 0 ? round(($item['amount'] / $totalRevenue) * 100, 1) : 0;
        }

        return collect($revenue)->sortByDesc('amount')->values();
    }

    private function getTopProducts($startDate, $endDate): \Illuminate\Support\Collection
    {
        return SaleItem::with(['product', 'sale'])
            ->whereHas('sale', function ($query) use ($startDate, $endDate) {
                $query->whereBetween('created_at', [$startDate, $endDate])
                    ->where('status', Sale::STATUS_COMPLETED);
            })
            ->select(
                'product_id',
                DB::raw('SUM(quantity) as total_quantity'),
                DB::raw('SUM(quantity * unit_price) as total_revenue'),
                DB::raw('COUNT(DISTINCT sale_id) as sale_count')
            )
            ->groupBy('product_id')
            ->orderByDesc('total_revenue')
            ->limit(10)
            ->get()
            ->map(function ($item) {
                return [
                    'product' => $item->product,
                    'total_quantity' => $item->total_quantity,
                    'total_revenue' => $item->total_revenue,
                    'sale_count' => $item->sale_count,
                    'average_price' => $item->total_quantity > 0 ? $item->total_revenue / $item->total_quantity : 0,
                ];
            });
    }

    private function getSalesByUser($startDate, $endDate): \Illuminate\Support\Collection
    {
        return Sale::with('user')
            ->whereBetween('created_at', [$startDate, $endDate])
            ->where('status', Sale::STATUS_COMPLETED)
            ->select(
                'user_id',
                DB::raw('COUNT(*) as sales_count'),
                DB::raw('SUM(total_amount) as total_revenue'),
                DB::raw('AVG(total_amount) as average_sale')
            )
            ->groupBy('user_id')
            ->orderByDesc('total_revenue')
            ->get()
            ->map(function ($sale) {
                return [
                    'user' => $sale->user,
                    'sales_count' => $sale->sales_count,
                    'total_revenue' => $sale->total_revenue,
                    'average_sale' => $sale->average_sale,
                ];
            });
    }

    private function getCustomerMetrics($startDate, $endDate): array
    {
        $totalCustomers = Customer::count();
        $newCustomers = Customer::whereBetween('created_at', [$startDate, $endDate])->count();
        $activeCustomers = Sale::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', Sale::STATUS_COMPLETED)
            ->distinct('customer_id')
            ->count('customer_id');

        $repeatCustomers = Sale::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', Sale::STATUS_COMPLETED)
            ->whereNotNull('customer_id')
            ->select('customer_id', DB::raw('COUNT(*) as purchase_count'))
            ->groupBy('customer_id')
            ->having('purchase_count', '>', 1)
            ->count();

        $averageOrderValue = Sale::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', Sale::STATUS_COMPLETED)
            ->avg('total_amount');

        return [
            'total_customers' => $totalCustomers,
            'new_customers' => $newCustomers,
            'active_customers' => $activeCustomers,
            'repeat_customers' => $repeatCustomers,
            'customer_retention_rate' => $activeCustomers > 0 ? round(($repeatCustomers / $activeCustomers) * 100, 1) : 0,
            'average_order_value' => $averageOrderValue,
        ];
    }

    private function getSalesSummary($startDate, $endDate): array
    {
        $sales = Sale::whereBetween('created_at', [$startDate, $endDate])
            ->where('status', Sale::STATUS_COMPLETED);

        $totalRevenue = $sales->sum('total_amount');
        $totalSales = $sales->count();
        $averageSale = $totalSales > 0 ? $totalRevenue / $totalSales : 0;

        // Previous period comparison
        $previousStart = $startDate->copy()->subDays($startDate->diffInDays($endDate) + 1);
        $previousEnd = $startDate->copy()->subDay();

        $previousSales = Sale::whereBetween('created_at', [$previousStart, $previousEnd])
            ->where('status', Sale::STATUS_COMPLETED);

        $previousRevenue = $previousSales->sum('total_amount');
        $previousCount = $previousSales->count();

        $revenueGrowth = $previousRevenue > 0 ? round((($totalRevenue - $previousRevenue) / $previousRevenue) * 100, 1) : 0;
        $salesGrowth = $previousCount > 0 ? round((($totalSales - $previousCount) / $previousCount) * 100, 1) : 0;

        return [
            'total_revenue' => $totalRevenue,
            'total_sales' => $totalSales,
            'average_sale' => $averageSale,
            'revenue_growth' => $revenueGrowth,
            'sales_growth' => $salesGrowth,
            'previous_revenue' => $previousRevenue,
            'previous_sales' => $previousCount,
        ];
    }

    private function getSalesByType($startDate, $endDate): \Illuminate\Support\Collection
    {
        $saleTypes = SaleType::all();
        $sales = [];

        foreach ($saleTypes as $type) {
            $total = Sale::where('sale_type_id', $type->id)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->where('status', Sale::STATUS_COMPLETED)
                ->sum('total_amount');

            $count = Sale::where('sale_type_id', $type->id)
                ->whereBetween('created_at', [$startDate, $endDate])
                ->where('status', Sale::STATUS_COMPLETED)
                ->count();

            $sales[] = [
                'type' => $type->name,
                'amount' => $total,
                'count' => $count,
                'percentage' => 0,
            ];
        }

        // Calculate percentages
        $totalAmount = collect($sales)->sum('amount');
        foreach ($sales as &$item) {
            $item['percentage'] = $totalAmount > 0 ? round(($item['amount'] / $totalAmount) * 100, 1) : 0;
        }

        return collect($sales)->sortByDesc('amount')->values();
    }
}
