<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Expense;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\StreamedResponse;

class ReportController extends Controller
{
    public function summary(Request $request): JsonResponse
    {
        $userId = $request->user()->id;

        $validator = Validator::make($request->all(), [
            'date_from' => 'nullable|date',
            'date_to' => 'nullable|date|after_or_equal:date_from',
        ]);

        if ($validator->fails()) {
            return response()->json(['message' => 'Invalid date range'], 422);
        }

        $dateFrom = $request->input('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->input('date_to', now()->format('Y-m-d'));

        if (Carbon::parse($dateTo)->diffInDays(Carbon::parse($dateFrom)) > 366) {
            return response()->json(['message' => 'Date range cannot exceed 1 year'], 422);
        }

        $query = Expense::with('category')->where('user_id', $userId)
            ->whereDate('date', '>=', $dateFrom)
            ->whereDate('date', '<=', $dateTo);

        $totalExpense = (float) $query->sum('amount');

        $categoryBreakdown = Expense::with('category')
            ->where('user_id', $userId)
            ->whereDate('date', '>=', $dateFrom)
            ->whereDate('date', '<=', $dateTo)
            ->select('category_id', DB::raw('SUM(amount) as total'), DB::raw('COUNT(*) as count'))
            ->groupBy('category_id')
            ->get()
            ->map(function ($item) use ($totalExpense) {
                return [
                    'category' => $item->category?->name ?? 'Unknown',
                    'icon' => $item->category?->icon ?? '📦',
                    'color' => $item->category?->color ?? '#6B7280',
                    'total' => (float) $item->total,
                    'count' => $item->count,
                    'percentage' => $totalExpense > 0 ? round(($item->total / $totalExpense) * 100, 1) : 0,
                ];
            });

        $dailyBreakdown = Expense::where('user_id', $userId)
            ->whereDate('date', '>=', $dateFrom)
            ->whereDate('date', '<=', $dateTo)
            ->select(DB::raw('DATE(date) as day'), DB::raw('SUM(amount) as total'))
            ->groupBy('day')
            ->orderBy('day')
            ->get()
            ->map(function ($item) {
                return [
                    'date' => $item->day,
                    'total' => (float) $item->total,
                ];
            });

        $expenses = $query->orderBy('date', 'desc')->orderBy('created_at', 'desc')->get();

        return response()->json([
            'date_from' => $dateFrom,
            'date_to' => $dateTo,
            'total_expense' => $totalExpense,
            'total_transactions' => $expenses->count(),
            'daily_breakdown' => $dailyBreakdown,
            'category_breakdown' => $categoryBreakdown,
            'expenses' => $expenses,
        ]);
    }

    public function exportCsv(Request $request): StreamedResponse
    {
        $userId = $request->user()->id;
        $user = $request->user();
        $dateFrom = $request->input('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->input('date_to', now()->format('Y-m-d'));

        $expenses = Expense::with('category')->where('user_id', $userId)
            ->whereDate('date', '>=', $dateFrom)
            ->whereDate('date', '<=', $dateTo)
            ->orderBy('date', 'desc')
            ->get();

        $total = $expenses->sum('amount');

        $callback = function () use ($expenses, $dateFrom, $dateTo, $total, $user) {
            $file = fopen('php://output', 'w');

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

            // Header section
            fputcsv($file, ['ExpenseTracker - Expense Report']);
            fputcsv($file, ['Generated for', $user->name ?? $user->email]);
            fputcsv($file, ['Period', $dateFrom . ' to ' . $dateTo]);
            fputcsv($file, ['Generated At', now()->format('Y-m-d H:i:s')]);
            fputcsv($file, []);

            // Summary section
            fputcsv($file, ['SUMMARY']);
            fputcsv($file, ['Total Expenses', number_format($total, 2)]);
            fputcsv($file, ['Transactions', $expenses->count()]);
            fputcsv($file, []);

            // Data section
            fputcsv($file, ['Date', 'Time', 'Category', 'Amount', 'Payment Method', 'Note']);

            foreach ($expenses as $expense) {
                fputcsv($file, [
                    $expense->date,
                    $expense->time ?? '',
                    $expense->category?->name ?? 'Unknown',
                    number_format($expense->amount, 2),
                    ucfirst($expense->payment_method),
                    $expense->note ?? '',
                ]);
            }

            fclose($file);
        };

        $filename = 'expenses-' . $dateFrom . '-to-' . $dateTo . '.csv';

        return response()->streamDownload($callback, $filename, [
            'Content-Type' => 'text/csv',
        ]);
    }

    public function exportPdf(Request $request)
    {
        $userId = $request->user()->id;
        $user = $request->user();
        $dateFrom = $request->input('date_from', now()->startOfMonth()->format('Y-m-d'));
        $dateTo = $request->input('date_to', now()->format('Y-m-d'));

        $expenses = Expense::with('category')->where('user_id', $userId)
            ->whereDate('date', '>=', $dateFrom)
            ->whereDate('date', '<=', $dateTo)
            ->orderBy('date', 'desc')
            ->get();

        $total = $expenses->sum('amount');
        $count = $expenses->count();
        $generatedAt = now()->format('Y-m-d H:i:s');

        $categoryBreakdown = Expense::with('category')
            ->where('user_id', $userId)
            ->whereDate('date', '>=', $dateFrom)
            ->whereDate('date', '<=', $dateTo)
            ->select('category_id', DB::raw('SUM(amount) as total'), DB::raw('COUNT(*) as count'))
            ->groupBy('category_id')
            ->get()
            ->map(function ($item) use ($total) {
                return [
                    'category' => $item->category?->name ?? 'Unknown',
                    'icon' => $item->category?->icon ?? '📦',
                    'color' => $item->category?->color ?? '#6B7280',
                    'total' => (float) $item->total,
                    'count' => $item->count,
                    'percentage' => $total > 0 ? round(($item->total / $total) * 100, 1) : 0,
                ];
            })->toArray();

        $days = max(1, Carbon::parse($dateTo)->diffInDays(Carbon::parse($dateFrom)) + 1);
        $avgPerDay = $total / $days;

        $pdf = Pdf::loadView('reports.pdf', compact(
            'expenses', 'dateFrom', 'dateTo', 'total', 'count',
            'generatedAt', 'categoryBreakdown', 'avgPerDay', 'user'
        ));

        $filename = 'expenses-' . $dateFrom . '-to-' . $dateTo . '.pdf';

        return response()->streamDownload(function () use ($pdf) {
            echo $pdf->output();
        }, $filename, [
            'Content-Type' => 'application/pdf',
        ]);
    }
}
