<?php

namespace App\Http\Controllers;

use App\Traits\AccountInfoTrait;
use App\Models\Transaction;
use Carbon\Carbon;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Spatie\Browsershot\Browsershot;

class ReportController extends Controller
{
    use AccountInfoTrait;

    /**
    * Create a new controller instance.
    *
    * @return void
    */
    public function __construct()
    {
        $this->middleware('auth');
    }

    public function reports()
    {
        $profile = getActiveProfile();

        if (!$profile) {
            abort(403, 'No active profile');
        }

        // CRITICAL SECURITY: Validate user has ownership/access to this profile
        // This prevents unauthorized access to financial reports via session manipulation
        \App\Helpers\ProfileAuthorizationHelper::authorize($profile);

        $profileAccounts = $this->getAccountsInfo();

        return view('reports.show', compact('profileAccounts'));
    }

    public function downloadPdf(Request $request)
    {
        $profile = getActiveProfile();

        if (!$profile) {
            abort(403, 'No active profile');
        }

        // CRITICAL SECURITY: Validate user has ownership/access to this profile
        // This prevents unauthorized PDF report generation via session manipulation
        \App\Helpers\ProfileAuthorizationHelper::authorize($profile);

        $fromDate = $request->get('fromDate');
        $toDate = $request->get('toDate');
        $decimalFormat = (bool) $request->get('decimal', 0);

        if (!$fromDate || !$toDate) {
            abort(400, 'Missing date parameters');
        }

        // Use the same logic from SingleReport component
        $singleReport = new \App\Http\Livewire\SingleReport();
        $singleReport->fromDate = $fromDate;
        $singleReport->toDate = $toDate;
        $singleReport->decimalFormat = $decimalFormat;

        $accountsData = $singleReport->getAccountsWithPeriodBalances();
        $transactionTypesData = $singleReport->calculateTransactionTypeTotals();
        $statisticsData = $singleReport->calculatePeriodStatistics();
        $returnRatioData = $singleReport->calculateReturnRatioTimeline();
        $returnRatioTimelineData = $returnRatioData['timeline'] ?? [];
        $returnRatioTrendData = $returnRatioData['trend'] ?? [];

        // Check if we have chart images from the frontend
        $chartImage = null; // Legacy single chart support
        $returnRatioChartImage = null;
        $accountBalancesChartImage = null;

        $useChartImage = $request->get('with_chart'); // Legacy single chart
        $useChartsImages = $request->get('with_charts'); // New dual charts

        Log::info('PDF generation request', [
            'useChartImage' => $useChartImage,
            'useChartsImages' => $useChartsImages,
            'hasSessionChartImageId' => session()->has('chart_image_id'),
            'hasSessionChartImageIds' => session()->has('chart_image_ids'),
            'sessionChartImageId' => session('chart_image_id'),
            'sessionChartImageIds' => session('chart_image_ids')
        ]);

        // Handle new dual charts system
        if ($useChartsImages && session('chart_image_ids')) {
            $chartImageIds = session('chart_image_ids');

            // Process Return Ratio Chart
            if (isset($chartImageIds['return_ratio_chart_id'])) {
                $chartImageId = $chartImageIds['return_ratio_chart_id'];
                $tempImagePath = storage_path('app/temp/' . $chartImageId . '.png');

                if (file_exists($tempImagePath)) {
                    $imageData = file_get_contents($tempImagePath);
                    $returnRatioChartImage = 'data:image/png;base64,' . base64_encode($imageData);

                    Log::info('Return Ratio Chart image found in temp file', [
                        'chartImageId' => $chartImageId,
                        'fileSize' => strlen($imageData)
                    ]);

                    // Clean up temporary file
                    unlink($tempImagePath);
                } else {
                    Log::warning('Return Ratio Chart image temp file not found', ['path' => $tempImagePath]);
                }
            }

            // Process Account Balances Chart
            if (isset($chartImageIds['account_balances_chart_id'])) {
                $chartImageId = $chartImageIds['account_balances_chart_id'];
                $tempImagePath = storage_path('app/temp/' . $chartImageId . '.png');

                if (file_exists($tempImagePath)) {
                    $imageData = file_get_contents($tempImagePath);
                    $accountBalancesChartImage = 'data:image/png;base64,' . base64_encode($imageData);

                    Log::info('Account Balances Chart image found in temp file', [
                        'chartImageId' => $chartImageId,
                        'fileSize' => strlen($imageData)
                    ]);

                    // Clean up temporary file
                    unlink($tempImagePath);
                } else {
                    Log::warning('Account Balances Chart image temp file not found', ['path' => $tempImagePath]);
                }
            }

            session()->forget('chart_image_ids');
        }
        // Handle legacy single chart system (backward compatibility)
        else if ($useChartImage && session('chart_image_id')) {
            $chartImageId = session('chart_image_id');
            $tempImagePath = storage_path('app/temp/' . $chartImageId . '.png');

            if (file_exists($tempImagePath)) {
                // Read the image file and convert to base64
                $imageData = file_get_contents($tempImagePath);
                $chartImage = 'data:image/png;base64,' . base64_encode($imageData);

                Log::info('Legacy chart image found in temp file', [
                    'chartImageId' => $chartImageId,
                    'fileSize' => strlen($imageData),
                    'base64Length' => strlen($chartImage)
                ]);

                // Clean up temporary file
                unlink($tempImagePath);
                session()->forget('chart_image_id');
            } else {
                Log::warning('Legacy chart image temp file not found', ['path' => $tempImagePath]);
            }
        } else {
            Log::info('No chart images available, using fallback chart rendering');
        }

        // Prepare chart data for PDF rendering (fallback if no image)
        $chartData = $this->prepareChartDataForPdf($returnRatioTimelineData, $returnRatioTrendData);

        // Clean UTF-8 encoding for all data
        $accountsData = $this->cleanUtf8Data($accountsData);
        $transactionTypesData = $this->cleanUtf8Data($transactionTypesData);
        $statisticsData = $this->cleanUtf8Data($statisticsData);

        // Generate title with profile information
        $fromDateCarbon = Carbon::parse($fromDate);
        $toDateCarbon = Carbon::parse($toDate);

        $activeProfile = getActiveProfile();
        $profileTitle = '';
        if ($activeProfile) {
            $fullName = $activeProfile->full_name ?? $activeProfile->name ?? '';
            $profileName = $activeProfile->name ?? '';
            $profileTitle = ' ' . $fullName . ' (' . $profileName . ')';
        }

        $title = [
            'header' => __('Financial overview') . $profileTitle,
            'sub' => $fromDateCarbon->format('d-m-Y') . ' - ' . $toDateCarbon->format('d-m-Y')
        ];

        $pdf = Pdf::loadView('reports.pdf', [
            'title' => $title,
            'accountsData' => $accountsData,
            'transactionTypesData' => $transactionTypesData,
            'statisticsData' => $statisticsData,
            'returnRatioTimelineData' => $returnRatioTimelineData,
            'returnRatioTrendData' => $returnRatioTrendData,
            'chartData' => $chartData,
            'chartImage' => $chartImage, // Legacy single chart support
            'returnRatioChartImage' => $returnRatioChartImage,
            'accountBalancesChartImage' => $accountBalancesChartImage,
            'isOrganization' => $activeProfile instanceof \App\Models\Organization,
            'decimalFormat' => $decimalFormat,
        ])->setPaper('A4', 'portrait')
          ->setOptions([
              'isHtml5ParserEnabled' => true,
              'isRemoteEnabled' => false,
              'defaultFont' => 'DejaVu Sans',
              'dpi' => 150,
              'defaultPaperSize' => 'A4',
              'chroot' => public_path(),
          ]);

        return $pdf->download('financial-report-' . now()->format('Y-m-d') . '.pdf');
    }

    /**
     * Clean UTF-8 encoding for strings
     */
    private function cleanUtf8String($string)
    {
        if (!is_string($string)) {
            return $string;
        }

        // Remove or replace problematic characters
        $string = mb_convert_encoding($string, 'UTF-8', 'UTF-8');
        $string = preg_replace('/[\x00-\x1F\x7F-\x9F]/u', '', $string);

        return $string;
    }

    /**
     * Clean UTF-8 encoding for arrays/collections
     */
    private function cleanUtf8Data($data)
    {
        if (is_string($data)) {
            return $this->cleanUtf8String($data);
        }

        if (is_array($data) || $data instanceof \Illuminate\Support\Collection) {
            $cleaned = [];
            foreach ($data as $key => $value) {
                $cleanedKey = $this->cleanUtf8String($key);
                $cleanedValue = $this->cleanUtf8Data($value);
                $cleaned[$cleanedKey] = $cleanedValue;
            }
            return $data instanceof \Illuminate\Support\Collection ? collect($cleaned) : $cleaned;
        }

        return $data;
    }

    /**
     * Prepare chart data for PDF rendering
     */
    private function prepareChartDataForPdf($returnRatioTimelineData, $returnRatioTrendData)
    {
        if (!$returnRatioTimelineData || count($returnRatioTimelineData) <= 1) {
            return null;
        }

        $values = array_column($returnRatioTimelineData, 'return_ratio');
        $labels = array_column($returnRatioTimelineData, 'label');

        // Always start from 0% as requested
        $minValue = 0;
        $maxValue = count($values) > 0 ? max(array_merge($values, [100])) : 100;

        // Add padding to top only
        $padding = ($maxValue - $minValue) * 0.1;
        $maxValue += $padding;
        $range = $maxValue - $minValue;

        // Ensure we have a valid range
        if ($range <= 0) {
            $range = 100;
            $maxValue = 100;
        }

        $pointCount = count($returnRatioTimelineData);
        $points = [];
        $trendPoints = [];

        if ($pointCount > 0 && $range > 0) {
            // Calculate data points
            foreach ($returnRatioTimelineData as $index => $point) {
                $x = $pointCount > 1 ? ($index / ($pointCount - 1)) * 100 : 50;
                $y = 100 - (($point['return_ratio'] - $minValue) / $range * 100);
                $points[] = number_format($x, 2) . ',' . number_format(max(0, min(100, $y)), 2);
            }

            // Calculate trend points if available
            if ($returnRatioTrendData && count($returnRatioTrendData) > 0) {
                $trendCount = count($returnRatioTrendData);
                foreach ($returnRatioTrendData as $index => $point) {
                    $x = $trendCount > 1 ? ($index / ($trendCount - 1)) * 100 : 50;
                    $y = 100 - (($point['trend_value'] - $minValue) / $range * 100);
                    $trendPoints[] = number_format($x, 2) . ',' . number_format(max(0, min(100, $y)), 2);
                }
            }
        }

        return [
            'values' => $values,
            'labels' => $labels,
            'minValue' => $minValue,
            'maxValue' => $maxValue,
            'range' => $range,
            'points' => $points,
            'trendPoints' => $trendPoints,
            'pointsString' => implode(' ', $points),
            'trendPointsString' => implode(' ', $trendPoints),
        ];
    }
}