<?php

namespace App\Http\Controllers;

use App\Models\License;
use App\Models\Invoice;
use App\Models\LicenseLog;
use App\Models\LicenseDomain;
use App\Models\User;
use App\Models\Product;
use App\Models\Ticket;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class ReportsController extends Controller
{
    /**
     * Display the reports dashboard.
     */
    public function index()
    {
        // Basic metrics
        $totalLicenses = License::count();
        $activeLicenses = License::where('status', 'active')->count();
        $expiredLicenses = License::where('status', 'expired')->count();
        $totalUsers = User::count();
        $totalProducts = Product::count();
        $totalTickets = Ticket::count();
        $openTickets = Ticket::whereIn('status', ['open', 'pending'])->count();

        // Monthly license data for charts - Last 3 months
        $monthlyLicensesRaw = License::select(
            DB::raw('YEAR(created_at) as year'),
            DB::raw('MONTH(created_at) as month'),
            DB::raw('COUNT(*) as count')
        )
        ->where('created_at', '>=', now()->subMonths(3))
        ->groupBy('year', 'month')
        ->orderBy('year')
        ->orderBy('month')
        ->get();

        // Monthly revenue data for charts (from licenses) - Last 3 months
        $monthlyRevenueRaw = License::select(
            DB::raw('YEAR(licenses.created_at) as year'),
            DB::raw('MONTH(licenses.created_at) as month'),
            DB::raw('SUM(products.price) as revenue')
        )
        ->join('products', 'licenses.product_id', '=', 'products.id')
        ->where('licenses.created_at', '>=', now()->subMonths(3))
        ->groupBy('year', 'month')
        ->orderBy('year')
        ->orderBy('month')
        ->get();

        // Convert to Chart.js format with last 3 months
        $last3Months = [];
        $last3MonthsLabels = [];
        for ($i = 2; $i >= 0; $i--) {
            $date = now()->subMonths($i);
            $last3Months[] = $date->format('Y-m');
            $last3MonthsLabels[] = $date->format('M Y'); // More readable format
        }
        
        $monthlyRevenueData = [];
        foreach ($last3Months as $month) {
            $found = $monthlyRevenueRaw->first(function($item) use ($month) {
                return $item->year . '-' . str_pad($item->month, 2, '0', STR_PAD_LEFT) === $month;
            });
            $monthlyRevenueData[] = $found ? (float)$found->revenue : 0;
        }
        
        $monthlyRevenue = [
            'labels' => $last3MonthsLabels,
            'datasets' => [[
                'label' => __('app.monthly_revenue'),
                'data' => $monthlyRevenueData,
                'borderColor' => '#10b981',
                'backgroundColor' => 'rgba(16, 185, 129, 0.1)',
                'fill' => true,
                'tension' => 0.4,
                'pointBackgroundColor' => '#10b981',
                'pointBorderColor' => '#ffffff',
                'pointBorderWidth' => 2,
                'pointRadius' => 5
            ]]
        ];

        // Convert to Chart.js format with last 3 months
        $monthlyLicensesData = [];
        foreach ($last3Months as $month) {
            $found = $monthlyLicensesRaw->first(function($item) use ($month) {
                return $item->year . '-' . str_pad($item->month, 2, '0', STR_PAD_LEFT) === $month;
            });
            $monthlyLicensesData[] = $found ? (int)$found->count : 0;
        }
        
        $monthlyLicenses = [
            'labels' => $last3MonthsLabels,
            'datasets' => [[
                'label' => __('app.licenses_created'),
                'data' => $monthlyLicensesData,
                'borderColor' => '#3b82f6',
                'backgroundColor' => 'rgba(59, 130, 246, 0.1)',
                'fill' => true,
                'tension' => 0.4,
                'pointBackgroundColor' => '#3b82f6',
                'pointBorderColor' => '#ffffff',
                'pointBorderWidth' => 2,
                'pointRadius' => 5
            ]]
        ];

        // License type distribution (regular vs extended)
        $licenseTypeDataRaw = License::select('license_type', DB::raw('COUNT(*) as count'))
            ->groupBy('license_type')
            ->get();

        // Convert to Chart.js format
        $licenseTypeData = [
            'labels' => $licenseTypeDataRaw->pluck('license_type')->map(function($type) {
                return __('app.' . $type) ?: ucfirst($type);
            })->toArray(),
            'datasets' => [[
                'data' => $licenseTypeDataRaw->pluck('count')->toArray(),
                'backgroundColor' => ['#3b82f6', '#10b981'],
                'borderWidth' => 0
            ]]
        ];

        // License status distribution
        $licenseStatusDataRaw = License::select('status', DB::raw('COUNT(*) as count'))
            ->groupBy('status')
            ->get();

        // Convert to Chart.js format
        $licenseStatusData = [
            'labels' => $licenseStatusDataRaw->pluck('status')->map(function($status) {
                return __('app.' . $status) ?: ucfirst($status);
            })->toArray(),
            'datasets' => [[
                'data' => $licenseStatusDataRaw->pluck('count')->toArray(),
                'backgroundColor' => ['#4F46E5', '#10B981', '#EF4444', '#F59E0B', '#8B5CF6'],
                'borderWidth' => 0
            ]]
        ];

        // API calls data (from license logs)
        $apiCallsDataRaw = LicenseLog::getApiCallsByDate(30);

        // Convert to Chart.js format
        $apiCallsData = [
            'labels' => $apiCallsDataRaw->pluck('date')->toArray(),
            'datasets' => [[
                'label' => __('app.api_calls'),
                'data' => $apiCallsDataRaw->pluck('count')->toArray(),
                'borderColor' => '#8b5cf6',
                'backgroundColor' => 'rgba(139, 92, 246, 0.1)',
                'fill' => true,
                'tension' => 0.4
            ]]
        ];

        // API status distribution
        $apiStatusDataRaw = LicenseLog::getApiStatusDistribution(30);

        // Convert to Chart.js format
        $apiStatusData = [
            'labels' => $apiStatusDataRaw->pluck('status')->map(function($status) {
                return __('app.' . $status) ?: ucfirst($status);
            })->toArray(),
            'datasets' => [[
                'label' => __('app.api_calls'),
                'data' => $apiStatusDataRaw->pluck('count')->toArray(),
                'backgroundColor' => ['#10B981', '#EF4444', '#F59E0B', '#4F46E5', '#8B5CF6'],
                'borderWidth' => 0
            ]]
        ];

        // Top products by license count
        $topProducts = Product::withCount('licenses')
            ->orderBy('licenses_count', 'desc')
            ->limit(10)
            ->get()
            ->map(function ($product) {
                $product->revenue = $product->licenses->sum(function ($license) {
                    return $license->product->price ?? 0;
                });
                return $product;
            });

        // Recent license activities
        $recentActivities = LicenseLog::with(['license', 'license.user'])
            ->orderBy('created_at', 'desc')
            ->limit(20)
            ->get();

        // Calculate total revenue (from products table via licenses relationship)
        $totalRevenue = License::join('products', 'licenses.product_id', '=', 'products.id')
            ->sum('products.price') ?? 0;

        // --- Invoices: monthly amounts and status totals - Last 3 months ---
        $invoiceMonthlyRaw = Invoice::select(
            DB::raw('YEAR(created_at) as year'),
            DB::raw('MONTH(created_at) as month'),
            DB::raw('SUM(amount) as total')
        )
        ->where('created_at', '>=', now()->subMonths(3))
        ->groupBy('year', 'month')
        ->orderBy('year')
        ->orderBy('month')
        ->get();

        // Convert to Chart.js format with last 3 months
        $invoiceMonthlyData = [];
        foreach ($last3Months as $month) {
            $found = $invoiceMonthlyRaw->first(function($item) use ($month) {
                return $item->year . '-' . str_pad($item->month, 2, '0', STR_PAD_LEFT) === $month;
            });
            $invoiceMonthlyData[] = $found ? (float)$found->total : 0;
        }
        
        $invoiceMonthlyAmounts = [
            'labels' => $last3MonthsLabels,
            'datasets' => [[
                'label' => __('app.invoice_amounts'),
                'data' => $invoiceMonthlyData,
                'borderColor' => '#10b981',
                'backgroundColor' => 'rgba(16, 185, 129, 0.1)',
                'fill' => true,
                'tension' => 0.4,
                'pointBackgroundColor' => '#10b981',
                'pointBorderColor' => '#ffffff',
                'pointBorderWidth' => 2,
                'pointRadius' => 5
            ]]
        ];

        // Status-based monetary totals
        $invoiceStatusTotals = [
            'paid' => (float) Invoice::where('status', 'paid')->sum('amount'),
            'due_soon' => (float) Invoice::where('status', 'pending')->whereBetween('due_date', [now(), now()->addDays(7)])->sum('amount'),
            'pending' => (float) Invoice::where('status', 'pending')->sum('amount'),
            'cancelled' => (float) Invoice::whereIn('status', ['cancelled','overdue'])->sum('amount'),
        ];

        // Domain statistics
        $totalDomains = LicenseDomain::count();
        $activeDomains = LicenseDomain::where('status', 'active')->count();

        // User registrations data for charts - Last 3 months
        $userRegistrationsRaw = User::select(
            DB::raw('YEAR(created_at) as year'),
            DB::raw('MONTH(created_at) as month'),
            DB::raw('COUNT(*) as count')
        )
        ->where('created_at', '>=', now()->subMonths(3))
        ->groupBy('year', 'month')
        ->orderBy('year')
        ->orderBy('month')
        ->get();

        // Convert to Chart.js format with last 3 months
        $userRegistrationsData = [];
        foreach ($last3Months as $month) {
            $found = $userRegistrationsRaw->first(function($item) use ($month) {
                return $item->year . '-' . str_pad($item->month, 2, '0', STR_PAD_LEFT) === $month;
            });
            $userRegistrationsData[] = $found ? (int)$found->count : 0;
        }
        
        $userRegistrations = [
            'labels' => $last3MonthsLabels,
            'datasets' => [[
                'label' => __('app.user_registrations'),
                'data' => $userRegistrationsData,
                'borderColor' => '#f59e0b',
                'backgroundColor' => 'rgba(245, 158, 11, 0.1)',
                'fill' => true,
                'tension' => 0.4,
                'pointBackgroundColor' => '#f59e0b',
                'pointBorderColor' => '#ffffff',
                'pointBorderWidth' => 2,
                'pointRadius' => 5
            ]]
        ];

        // System overview data
        $systemOverviewData = [
            'labels' => [__('app.active_licenses'), __('app.expired_licenses'), __('app.pending_requests'), __('app.total_products')],
            'datasets' => [[
                'data' => [$activeLicenses, $expiredLicenses, $openTickets, $totalProducts],
                'backgroundColor' => ['#10b981', '#ef4444', '#f59e0b', '#3b82f6'],
                'borderWidth' => 0
            ]]
        ];

        // Activity timeline data (last 7 days)
        $activityTimelineRaw = [];
        $today = Carbon::today();
        for ($i = 6; $i >= 0; $i--) {
            $date = $today->copy()->subDays($i);
            $startOfDay = $date->copy()->startOfDay();
            $endOfDay = $date->copy()->endOfDay();

            // Sum total activity counts for the day (tickets created + licenses created)
            $ticketsCount = Ticket::whereBetween('created_at', [$startOfDay, $endOfDay])->count();
            $licensesCount = License::whereBetween('created_at', [$startOfDay, $endOfDay])->count();
            $dailyTotal = $ticketsCount + $licensesCount;

            $activityTimelineRaw[] = [
                'date' => $date->format('M j'),
                'count' => $dailyTotal
            ];
        }

        // Convert to Chart.js format
        $activityTimeline = [
            'labels' => collect($activityTimelineRaw)->pluck('date')->toArray(),
            'datasets' => [[
                'label' => __('app.daily_activity'),
                'data' => collect($activityTimelineRaw)->pluck('count')->toArray(),
                'borderColor' => '#8b5cf6',
                'backgroundColor' => 'rgba(139, 92, 246, 0.1)',
                'fill' => true,
                'tension' => 0.4
            ]]
        ];

        // For demo purposes, we'll show some sample data if there are failed API calls
        $failedApiCalls = LicenseLog::where('status', 'failed')
            ->where('created_at', '>=', now()->subDays(1))
            ->select('ip_address', DB::raw('COUNT(*) as attempts'))
            ->groupBy('ip_address')
            ->having('attempts', '>=', 3)
            ->get();

        $rateLimitedIPs = collect();
        $totalRateLimitedAttempts = 0;

        foreach ($failedApiCalls as $failedCall) {
            $rateLimitedIPs->push([
                'ip' => $failedCall->ip_address,
                'attempts' => $failedCall->attempts,
                'blocked_until' => now()->addMinutes(15) // Default lockout time
            ]);
            $totalRateLimitedAttempts += $failedCall->attempts;
        }

        return view('admin.reports', compact(
            'totalLicenses',
            'activeLicenses',
            'expiredLicenses',
            'totalUsers',
            'totalProducts',
            'totalTickets',
            'openTickets',
            'totalRevenue',
            'monthlyLicenses',
            'monthlyRevenue',
            'activityTimeline',
            'systemOverviewData',
            'licenseStatusData',
            'licenseTypeData',
            'apiCallsData',
            'apiStatusData',
            'topProducts',
            'recentActivities',
            'totalDomains',
            'activeDomains',
            'userRegistrations',
            'rateLimitedIPs',
            'totalRateLimitedAttempts',
            'invoiceStatusTotals',
            'invoiceMonthlyAmounts'
        ));
    }

    /**
     * Get license data for AJAX requests.
     */
    public function getLicenseData(Request $request)
    {
        $period = $request->get('period', 'month');

        switch ($period) {
            case 'week':
                $startDate = now()->subDays(7);
                break;
            case 'month':
                $startDate = now()->subDays(30);
                break;
            case 'year':
                $startDate = now()->subDays(365);
                break;
            default:
                $startDate = now()->subDays(30);
        }

        $data = License::select(
            DB::raw('DATE(created_at) as date'),
            DB::raw('COUNT(*) as count')
        )
        ->where('created_at', '>=', $startDate)
        ->groupBy('date')
        ->orderBy('date')
        ->get();

        return response()->json($data);
    }

    /**
     * Get API status data.
     */
    public function getApiStatusData(Request $request)
    {
        $period = $request->get('period', 'week');

        switch ($period) {
            case 'day':
                $startDate = now()->subDay();
                break;
            case 'week':
                $startDate = now()->subDays(7);
                break;
            case 'month':
                $startDate = now()->subDays(30);
                break;
            default:
                $startDate = now()->subDays(7);
        }

        $data = LicenseLog::select(
            'status',
            DB::raw('COUNT(*) as count'),
            DB::raw('DATE(created_at) as date')
        )
        ->where('created_at', '>=', $startDate)
        ->groupBy('status', 'date')
        ->orderBy('date')
        ->get();

        return response()->json($data);
    }

    /**
     * Export reports data to PDF or CSV format.
     */
    public function export(Request $request)
    {
        $format = $request->get('format', 'pdf');
        $dateFrom = $request->get('date_from');
        $dateTo = $request->get('date_to');

        // Get data for export
        $data = $this->getExportData($dateFrom, $dateTo);

        if ($format === 'csv') {
            return $this->exportToCsv($data);
        } else {
            return $this->exportToPdf($data);
        }
    }

    /**
     * Get data for export.
     */
    private function getExportData($dateFrom = null, $dateTo = null)
    {
        $query = License::with(['user', 'product']);

        if ($dateFrom) {
            $query->where('created_at', '>=', $dateFrom);
        }

        if ($dateTo) {
            $query->where('created_at', '<=', $dateTo);
        }

        $licenses = $query->get();

        return [
            'licenses' => $licenses,
            'summary' => [
                'total_licenses' => $licenses->count(),
                'active_licenses' => $licenses->where('status', 'active')->count(),
                'expired_licenses' => $licenses->where('license_expires_at', '<', now())->count(),
                'total_revenue' => $licenses->sum(function ($license) {
                    return $license->product ? $license->product->price : 0;
                }),
            ],
            'date_from' => $dateFrom,
            'date_to' => $dateTo,
        ];
    }

    /**
     * Export data to CSV format.
     */
    private function exportToCsv($data)
    {
        $filename = 'reports_' . now()->format('Y-m-d_H-i-s') . '.csv';

        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="' . $filename . '"',
        ];

        $callback = function () use ($data) {
            $file = fopen('php://output', 'w');

            // CSV headers
            fputcsv($file, ['License Key', 'Product', 'User', 'Status', 'Created At', 'Expires At', 'Price']);

            // CSV data
            foreach ($data['licenses'] as $license) {
                fputcsv($file, [
                    $license->license_key,
                    $license->product ? $license->product->name : 'N/A',
                    $license->user ? $license->user->name : 'N/A',
                    $license->status,
                    $license->created_at->format('Y-m-d H:i:s'),
                    $license->license_expires_at ? $license->license_expires_at->format('Y-m-d H:i:s') : 'N/A',
                    $license->product ? $license->product->price : '0',
                ]);
            }

            fclose($file);
        };

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

    /**
     * Export data to PDF format.
     */
    private function exportToPdf($data)
    {
        // For now, return CSV as PDF generation requires additional packages
        // You can install dompdf or similar package for proper PDF generation
        $filename = 'reports_' . now()->format('Y-m-d_H-i-s') . '.pdf';

        $headers = [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="' . $filename . '"',
        ];

        $callback = function () use ($data) {
            $file = fopen('php://output', 'w');

            // For now, just output CSV content as PDF placeholder
            // In production, use a proper PDF library like dompdf
            fputcsv($file, ['License Key', 'Product', 'User', 'Status', 'Created At', 'Expires At', 'Price']);

            foreach ($data['licenses'] as $license) {
                fputcsv($file, [
                    $license->license_key,
                    $license->product ? $license->product->name : 'N/A',
                    $license->user ? $license->user->name : 'N/A',
                    $license->status,
                    $license->created_at->format('Y-m-d H:i:s'),
                    $license->license_expires_at ? $license->license_expires_at->format('Y-m-d H:i:s') : 'N/A',
                    $license->product ? $license->product->price : '0',
                ]);
            }

            fclose($file);
        };

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