<?php

namespace App\Http\Controllers;

use App\Models\BudgetEntry;
use App\Models\DocumentLibrary;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\File;

class BudgetEntryController extends Controller
{
    private function formatCurrency($amount)
    {
        return '₹ ' . number_format((float) $amount, 2);
    }

    private function getStatusText($status)
    {
        return match ($status) {
            'D' => 'Draft',
            'R' => 'Revised',
            'P' => 'Approve',
            'F' => 'Freeze',
            'A' => 'Active',
            'I' => 'Inactive',
            'RR' => 'Re-Revised',
            'RJ' => 'Reject',
            'J' => 'Justification',
            default => 'Unknown',
        };
    }

    private $statusMap = [
        'Draft' => 'D',
        'Revised' => 'R',
        'Approve' => 'P',
        'Freeze' => 'F',
        'Active' => 'A',
        'Inactive' => 'I',
        'Re-Revised' => 'RR',
        'Reject' => 'RJ',
        'Justification' => 'J',
    ];

    private $reverseStatusMap = [
        'D' => 'Draft',
        'R' => 'Revised',
        'P' => 'Approve',
        'F' => 'Freeze',
        'A' => 'Active',
        'I' => 'Inactive',
        'RR' => 'Re-Revised',
        'RJ' => 'Reject',
        'J' => 'Justification',
    ];

    private function convertToStatusCode($status)
    {
        if ($status === 'Re_Revised' || $status === 'Re-Revised') {
            return 'RR';
        }
        return $this->statusMap[$status] ?? $status;
    }

    private function convertToStatusText($statusCode)
    {
        return $this->reverseStatusMap[$statusCode] ?? $statusCode;
    }

    
    private function parseLargeNumbers($data)
    {
        $largeNumberFields = ['Amount', 'Sug_Amount'];

        foreach ($largeNumberFields as $field) {
            if (isset($data[$field]) && is_numeric($data[$field])) {
                
                $data[$field] = (string) $data[$field];
            }
        }

        return $data;
    }

    public function index(Request $request)
    {
        try {
            $query = BudgetEntry::query();

            if ($request->has('Fin_Year')) {
                $query->where('Fin_Year', $request->Fin_Year);
            }

            if ($request->has('Dpt_Id')) {
                $query->where('Dpt_Id', $request->Dpt_Id);
            }

            if ($request->has('Bh_Id')) {
                $query->where('Bh_Id', $request->Bh_Id);
            }

            if ($request->has('status')) {
                $status = $this->convertToStatusCode($request->status);
                $query->where('Status', $status);
            }

            if ($request->has('budg_id')) {
                $query->where('Budg_Id', $request->budg_id);
            }

            if ($request->has('Ref_Id')) {
                $refId = $request->Ref_Id;
                $query->where('Ref_Id', $refId == '0' || $refId == 0 ? 0 : $refId);
            }

            if ($request->has('is_latest')) {
                $isLatest = filter_var($request->is_latest, FILTER_VALIDATE_BOOLEAN);
                $query->where('Is_Latest', $isLatest);
            }

            if ($request->has('show_only_latest') && $request->show_only_latest == true) {
                $query->where('Is_Latest', true);
            }

            if ($request->has('show_only_root') && $request->show_only_root == true) {
                $query->where('Ref_Id', 0);
            }

            if ($request->has('search') && $request->search != '') {
                $search = $request->search;
                $query->where(function ($q) use ($search) {
                    $q->whereHas('department', function ($dept) use ($search) {
                        $dept->where('Dpt_Desc', 'LIKE', "%{$search}%")
                            ->orWhere('Dpt_Name', 'LIKE', "%{$search}%");
                    })
                    ->orWhereHas('budgetHead', function ($budgetHead) use ($search) {
                        $budgetHead->where('Gr_Cd', 'LIKE', "%{$search}%")
                            ->orWhere('Gr_Nm', 'LIKE', "%{$search}%");
                    })
                    ->orWhere('Amount', 'LIKE', "%{$search}%");
                });
            }

            $with = [
                'financialYear',
                'department',
                'budgetHead'
            ];

            $query->with(
                array_merge($with, [
                    'parentEntry' => function ($q) use ($with) {
                        $q->with($with);
                    },
                ]),
            );

            $sortField = $request->get('sort_by', 'Budg_Id');
            $sortOrder = $request->get('sort_order', 'desc');
            $query->orderBy($sortField, $sortOrder);

            $perPage = $request->get('per_page', 15);
            $budgetEntries = $query->paginate($perPage);

            $formattedData = $budgetEntries->map(function ($item) {
                return $this->formatBudgetEntryData($item);
            });

            $totalAmount = $budgetEntries->sum(function ($item) {
                return (float) $item->Amount;
            });
            $totalSugAmount = $budgetEntries->sum(function ($item) {
                return (float) $item->Sug_Amount;
            });

            return response()->json([
                'success' => true,
                'message' => 'Budget entries retrieved successfully',
                'data' => $formattedData,
                'summary' => [
                    'total_amount' => (float) $totalAmount,
                    'formatted_total_amount' => '₹ ' . number_format($totalAmount, 2),
                    'total_sug_amount' => (float) $totalSugAmount,
                    'formatted_total_sug_amount' => '₹ ' . number_format($totalSugAmount, 2),
                    'total_records' => $budgetEntries->total(),
                    'latest_records_count' => $budgetEntries->where('Is_Latest', true)->count(),
                    'non_latest_records_count' => $budgetEntries->where('Is_Latest', false)->count(),
                ],
                'pagination' => [
                    'current_page' => $budgetEntries->currentPage(),
                    'per_page' => $budgetEntries->perPage(),
                    'total' => $budgetEntries->total(),
                    'last_page' => $budgetEntries->lastPage(),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json(
                [
                    'success' => false,
                    'message' => 'Failed to retrieve budget entries',
                    'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage(),
                ],
                500,
            );
        }
    }


    public function all(Request $request)
{
    try {
       $query = BudgetEntry::with([
    'financialYear',
    'department',
    'budgetHead'
])
->where('Status', BudgetEntry::STATUS_DRAFT) 
->latest('Budg_Id');

        if ($request->filled('Dpt_Id')) {
            $query->where('Dpt_Id', $request->Dpt_Id);
        }

        if ($request->filled('Bh_Id')) {
            $query->where('Bh_Id', $request->Bh_Id);
        }

        if ($request->filled('search')) {
            $search = $request->search;

            $query->where(function ($q) use ($search) {

                $q->whereHas('department', function ($dept) use ($search) {
                    $dept->where('Dpt_Name', 'LIKE', "%{$search}%")
                         ->orWhere('Dpt_Desc', 'LIKE', "%{$search}%");
                })

                ->orWhereHas('budgetHead', function ($bh) use ($search) {
                    $bh->where('Gr_Cd', 'LIKE', "%{$search}%")
                       ->orWhere('Gr_Nm', 'LIKE', "%{$search}%");
                })

                ->orWhere('Amount', 'LIKE', "%{$search}%");
            });
        }

        $budgetEntries = $query->get();

        return response()->json([
            'success' => true,
            'message' => 'Freeze budget entries retrieved successfully',
            'data' => $budgetEntries->map(fn($item) => $this->formatBudgetEntryData($item)),
            'total_records' => $budgetEntries->count(),
        ]);

    } catch (\Exception $e) {
        return response()->json(
            [
                'success' => false,
                'message' => 'Failed to retrieve budget entries',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage(),
            ],
            500
        );
    }
}

    public function getStatusCounts(Request $request)
    {
        try {
            $query = BudgetEntry::query();

            if ($request->has('fin_year')) {
                $query->where('Fin_Year', $request->fin_year);
            }
            if ($request->has('dpt_id')) {
                $query->where('Dpt_Id', $request->dpt_id);
            }
            if ($request->has('bh_id')) {
                $query->where('Bh_Id', $request->bh_id);
            }
            if ($request->has('budg_id')) {
                $query->where('Budg_Id', $request->budg_id);
            }

            if ($request->has('is_latest')) {
                $isLatest = filter_var($request->is_latest, FILTER_VALIDATE_BOOLEAN);
                $query->where('Is_Latest', $isLatest);
            }

            if ($request->has('count_only_latest') && $request->count_only_latest == true) {
                $query->where('Is_Latest', true);
            }

            if ($request->has('count_only_root') && $request->count_only_root == true) {
                $query->where('Ref_Id', 0);
            }

            $statusCounts = $query->select('Status', DB::raw('COUNT(*) as count'))->groupBy('Status')->get()->mapWithKeys(fn($item) => [$item->Status => $item->count])->toArray();

            $totalCount = array_sum($statusCounts);

            $latestCount = $query->clone()->where('Is_Latest', true)->count();
            $nonLatestCount = $query->clone()->where('Is_Latest', false)->count();

            $allStatuses = [
                'D' => 'Draft',
                'R' => 'Revised',
                'P' => 'Approve',
                'F' => 'Freeze',
                'A' => 'Active',
                'I' => 'Inactive',
                'RR' => 'Re-Revised',
                'RJ' => 'Reject',
                'J' => 'Justification',
            ];

            $formattedCounts = [];
            $totalAmount = $totalSugAmount = $latestTotalAmount = $latestTotalSugAmount = 0;

            foreach ($allStatuses as $code => $text) {
                $count = $statusCounts[$code] ?? 0;

                if ($count > 0) {
                    $statusQuery = BudgetEntry::query();
                    if ($request->has('fin_year')) {
                        $statusQuery->where('Fin_Year', $request->fin_year);
                    }
                    if ($request->has('dpt_id')) {
                        $statusQuery->where('Dpt_Id', $request->dpt_id);
                    }
                    if ($request->has('bh_id')) {
                        $statusQuery->where('Bh_Id', $request->bh_id);
                    }
                    if ($request->has('budg_id')) {
                        $statusQuery->where('Budg_Id', $request->budg_id);
                    }

                    if ($request->has('count_only_latest') && $request->count_only_latest) {
                        $statusQuery->where('Is_Latest', true);
                    }
                    if ($request->has('count_only_root') && $request->count_only_root) {
                        $statusQuery->where('Ref_Id', 0);
                    }
                    if ($request->has('is_latest')) {
                        $statusQuery->where('Is_Latest', filter_var($request->is_latest, FILTER_VALIDATE_BOOLEAN));
                    }

                    $statusQuery->where('Status', $code);
                    $statusEntries = $statusQuery->get();

                    $amount = $statusEntries->sum(function ($item) {
                        return (float) $item->Amount;
                    });
                    $sugAmount = $statusEntries->sum(function ($item) {
                        return (float) $item->Sug_Amount;
                    });

                    $latestEntries = $statusQuery->clone()->where('Is_Latest', true)->get();
                    $latestAmount = $latestEntries->sum(function ($item) {
                        return (float) $item->Amount;
                    });
                    $latestSugAmount = $latestEntries->sum(function ($item) {
                        return (float) $item->Sug_Amount;
                    });

                    $totalAmount += $amount;
                    $totalSugAmount += $sugAmount;
                    $latestTotalAmount += $latestAmount;
                    $latestTotalSugAmount += $latestSugAmount;

                    $formattedCounts[] = [
                        'status_code' => $code,
                        'status_text' => $text,
                        'count' => $count,
                        'amount' => (float) $amount,
                        'formatted_amount' => '₹ ' . number_format($amount, 2),
                        'sug_amount' => (float) $sugAmount,
                        'formatted_sug_amount' => '₹ ' . number_format($sugAmount, 2),
                        'latest_count' => $latestEntries->count(),
                        'latest_amount' => (float) $latestAmount,
                        'formatted_latest_amount' => '₹ ' . number_format($latestAmount, 2),
                        'latest_sug_amount' => (float) $latestSugAmount,
                        'formatted_latest_sug_amount' => '₹ ' . number_format($latestSugAmount, 2),
                        'percentage' => $totalCount > 0 ? round(($count / $totalCount) * 100, 2) : 0,
                        'is_workflow_status' => !in_array($code, ['A', 'I']),
                        'is_active' => $code === 'A',
                        'can_edit' => in_array($code, ['D', 'R', 'RR', 'J']),
                    ];
                } else {
                    $formattedCounts[] = [
                        'status_code' => $code,
                        'status_text' => $text,
                        'count' => 0,
                        'amount' => 0.0,
                        'formatted_amount' => '₹ 0.00',
                        'sug_amount' => 0.0,
                        'formatted_sug_amount' => '₹ 0.00',
                        'latest_count' => 0,
                        'latest_amount' => 0.0,
                        'formatted_latest_amount' => '₹ 0.00',
                        'latest_sug_amount' => 0.0,
                        'formatted_latest_sug_amount' => '₹ 0.00',
                        'percentage' => 0.0,
                        'is_workflow_status' => !in_array($code, ['A', 'I']),
                        'is_active' => $code === 'A',
                        'can_edit' => in_array($code, ['D', 'R', 'RR', 'J']),
                    ];
                }
            }

            $workflowStatuses = array_filter($formattedCounts, fn($item) => $item['is_workflow_status']);
            $finalStatuses = array_filter($formattedCounts, fn($item) => !$item['is_workflow_status']);

            $workflowCount = array_sum(array_column($workflowStatuses, 'count'));
            $finalCount = array_sum(array_column($finalStatuses, 'count'));
            $latestWorkflowCount = array_sum(array_column($workflowStatuses, 'latest_count'));
            $latestFinalCount = array_sum(array_column($finalStatuses, 'latest_count'));

            return response()->json([
                'success' => true,
                'message' => 'Status counts retrieved successfully',
                'data' => $formattedCounts,
                'summary' => [
                    'total_count' => $totalCount,
                    'total_amount' => (float) $totalAmount,
                    'formatted_total_amount' => '₹ ' . number_format($totalAmount, 2),
                    'total_sug_amount' => (float) $totalSugAmount,
                    'formatted_total_sug_amount' => '₹ ' . number_format($totalSugAmount, 2),
                    'latest_count' => $latestCount,
                    'non_latest_count' => $nonLatestCount,
                    'latest_total_amount' => (float) $latestTotalAmount,
                    'formatted_latest_total_amount' => '₹ ' . number_format($latestTotalAmount, 2),
                    'latest_total_sug_amount' => (float) $latestTotalSugAmount,
                    'formatted_latest_total_sug_amount' => '₹ ' . number_format($latestTotalSugAmount, 2),
                    'workflow_status_count' => $workflowCount,
                    'final_status_count' => $finalCount,
                    'latest_workflow_count' => $latestWorkflowCount,
                    'latest_final_count' => $latestFinalCount,
                    'workflow_percentage' => $totalCount > 0 ? round(($workflowCount / $totalCount) * 100, 2) : 0,
                    'final_percentage' => $totalCount > 0 ? round(($finalCount / $totalCount) * 100, 2) : 0,
                    'latest_workflow_percentage' => $latestCount > 0 ? round(($latestWorkflowCount / $latestCount) * 100, 2) : 0,
                    'latest_final_percentage' => $latestCount > 0 ? round(($latestFinalCount / $latestCount) * 100, 2) : 0,
                ],
                'filters_applied' => [
                    'fin_year' => $request->fin_year ?? null,
                    'dpt_id' => $request->dpt_id ?? null,
                    'bh_id' => $request->bh_id ?? null,
                    'budg_id' => $request->budg_id ?? null,
                    'is_latest' => $request->has('is_latest') ? filter_var($request->is_latest, FILTER_VALIDATE_BOOLEAN) : null,
                    'count_only_latest' => $request->count_only_latest ?? false,
                    'count_only_root' => $request->count_only_root ?? false,
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json(
                [
                    'success' => false,
                    'message' => 'Failed to retrieve status counts',
                    'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage(),
                ],
                500,
            );
        }
    }

 
    public function store(Request $request)
    {
        DB::beginTransaction();

        try {
            
            $requestData = $this->parseLargeNumbers($request->all());

            $request->merge($requestData);

            $validator = Validator::make($request->all(), [
                'Fin_Year' => 'required|integer|exists:fyear_master,FY_Id',
                'Dpt_Id' => 'required|integer|exists:dept_master,Dpt_id',
                'Bh_Id' => 'required|integer|exists:budget_head,Bh_Id',
                'Amount' => 'required|numeric|min:0|max:99999999999999.99',
                'Sug_Amount' => 'nullable|numeric|min:0|max:99999999999999.99',
                'Fnc_Id' => 'nullable|exists:function_types,Fnc_Id',
                'Beg_Doc' => 'nullable|array',
                'Beg_Doc.*' => 'nullable|file',
                'Beg_Doc_description' => 'nullable|array',
                'Beg_Doc_description.*' => 'nullable|string',
                'Status' => 'sometimes|string'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'success' => false,
                    'errors' => $validator->errors(),
                ], 422);
            }

            $status = $this->convertToStatusCode($request->Status ?? 'Draft');

            $existingEntry = BudgetEntry::where('Ref_Id', 0)
                ->where('Fin_Year', $request->Fin_Year)
                ->where('Dpt_Id', $request->Dpt_Id)
                ->where('Bh_Id', $request->Bh_Id)
                ->first();

            if ($existingEntry) {
                return response()->json([
                    'success' => false,
                    'message' => 'Budget entry already exists',
                ], 409);
            }

            $amount = (string) $request->Amount;
            $sugAmount = $request->Sug_Amount ? (string) $request->Sug_Amount : null;

            $budgetEntry = BudgetEntry::create([
                'Fin_Year'   => (int) $request->Fin_Year,
                'Dpt_Id'     => (int) $request->Dpt_Id,
                'Bh_Id'      => (int) $request->Bh_Id,
                'Amount'     => $amount,
                'Sug_Amount' => $sugAmount,
                'Beg_Doc'    => [],
                'Status'     => $status,
                'Ref_Id'     => 0,
            ]);

            $newDocs = [];

            if ($request->hasFile('Beg_Doc')) {
                foreach ($request->file('Beg_Doc') as $index => $file) {
                    if (!$file->isValid()) continue;

                    $folderName = 'budget_documents';
                    $folderPath = public_path($folderName);

                    if (!File::exists($folderPath)) {
                        File::makeDirectory($folderPath, 0755, true, true);
                    }

                    $fileName = Str::uuid() . '.' . $file->getClientOriginalExtension();
                    $file->move($folderPath, $fileName);

                    $fullUrl = url($folderName . '/' . $fileName);

                    $docName = 'Document_' . ($index + 1);
                    $docDescription = $request->Beg_Doc_description[$index] ?? null;

                    $docRecord = DocumentLibrary::create([
                        'Fnc_Id'      => $request->Fnc_Id,
                        'Rec_Id'      => $budgetEntry->Budg_Id,
                        'Description' => $docDescription,
                        'Doc_Upload'  => $fullUrl,
                        'Serial_No'   => $index + 1,
                    ]);

                    $newDocs[] = [
                        'doc_lib_id' => $docRecord->Doc_Lib,
                        'name'       => $docName,
                        'description'=> $docDescription,
                        'url'        => $fullUrl,
                        'type'       => $file->getClientOriginalExtension(),
                    ];
                }
            }

            if (!empty($newDocs)) {
                $budgetEntry->update([
                    'Beg_Doc' => $newDocs
                ]);
            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Budget entry created successfully',
                'data' => $this->formatBudgetEntryData($budgetEntry),
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Store Budget Entry Error: ' . 'Something went wrong. Please try again later.');
            return response()->json([
                'success' => false,
                'message' => 'Something went wrong. Please try again later.',
            ], 500);
        }
    }

    public function show($id)
    {
        try {
            $budgetEntry = BudgetEntry::with([
                'financialYear',
                'department',
                'budgetHead',
                'parentEntry.financialYear',
                'parentEntry.department',
                'parentEntry.budgetHead',
                'childEntries.financialYear',
                'childEntries.department',
                'childEntries.budgetHead'
            ])->find($id);

            if (!$budgetEntry) {
                return response()->json(
                    [
                        'success' => false,
                        'message' => 'Budget entry not found',
                    ],
                    404,
                );
            }

            $versionHistory = $budgetEntry->getVersionHistory();

            return response()->json([
                'success' => true,
                'message' => 'Budget entry retrieved successfully',
                'data' => $this->formatBudgetEntryData($budgetEntry),
                'version_history' => $versionHistory->map(function ($v) {
                    return $this->formatBudgetEntryData($v);
                }),
                'version_info' => [
                    'version_number' => $budgetEntry->version_number ?? 1,
                    'is_latest' => $budgetEntry->Is_Latest ?? false,
                    'root_id' => optional($budgetEntry->getRootEntryAttribute())->Budg_Id,
                    'total_versions' => $versionHistory->count(),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json(
                [
                    'success' => false,
                    'message' => 'Failed to retrieve budget entry',
                    'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage(),
                ],
                500,
            );
        }
    }


   public function update(Request $request, $id)
{
    DB::beginTransaction();

    try {

        $existingEntry = BudgetEntry::find($id);

        if (!$existingEntry) {
            return response()->json([
                'success' => false,
                'message' => 'Budget entry not found',
            ], 404);
        }

        $validator = Validator::make($request->all(), [
            'Amount' => 'sometimes|numeric|min:0',
            'Sug_Amount' => 'nullable|numeric|min:0',
            'Bh_Id' => 'nullable|integer|exists:budget_head,Bh_Id',
            'Status' => 'sometimes|string',
            'remarks' => 'nullable|string|max:500',

            'Beg_Doc' => 'nullable|array',
            'Beg_Doc.*' => 'nullable',

            'Beg_Doc_description' => 'nullable|array',
            'Beg_Doc_description.*' => 'nullable|string|max:255',

            'delete_existing_docs' => 'nullable|boolean',
            'replace_documents' => 'nullable|boolean',

            'Fnc_Id' => 'nullable|exists:function_types,Fnc_Id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors' => $validator->errors(),
            ], 422);
        }

        $currentStatus = $existingEntry->Status;

        $newStatus = $request->Status
            ? $this->convertToStatusCode($request->Status)
            : $currentStatus;

        $existingEntry->update(['Is_Latest' => false]);

        $begDocData = $existingEntry->Beg_Doc ?? [];

        if (is_string($begDocData)) {
            $begDocData = json_decode($begDocData, true) ?? [];
        }

        $docsToKeep = $begDocData;

        if ($request->delete_existing_docs == true || $request->replace_documents == true) {

            foreach ($begDocData as $doc) {

                if (isset($doc['url'])) {

                    $parsedUrl = parse_url($doc['url']);
                    $path = isset($parsedUrl['path']) ? ltrim($parsedUrl['path'], '/') : '';

                    if (strpos($path, 'budget_documents/') === 0) {

                        $filePath = public_path($path);

                        if (file_exists($filePath)) {
                            unlink($filePath);
                        }
                    }
                }

                if (isset($doc['doc_lib_id'])) {
                    DocumentLibrary::where('Doc_Lib', $doc['doc_lib_id'])->delete();
                }
            }

            $docsToKeep = [];
        }


        $newBudgetEntry = BudgetEntry::create([
            'Fin_Year'   => $existingEntry->Fin_Year,
            'Dpt_Id'     => $request->Dpt_Id ?? $existingEntry->Dpt_Id,
            'Bh_Id'      => $request->Bh_Id ?? $existingEntry->Bh_Id,
            'Amount'     => $request->Amount ?? $existingEntry->Amount,
            'Sug_Amount' => $request->Sug_Amount ?? $existingEntry->Sug_Amount,
            'Beg_Doc'    => $docsToKeep,
            'Status'     => $newStatus,
            'remarks'    => $request->remarks ?? $existingEntry->remarks,
            'Ref_Id'     => $existingEntry->Budg_Id,
            'Is_Latest'  => true,
        ]);

        $newDocs = [];

        if ($request->hasFile('Beg_Doc')) {

            foreach ($request->file('Beg_Doc') as $index => $file) {

                if (!$file->isValid()) continue;

                $folderName = 'budget_documents';
                $folderPath = public_path($folderName);

                if (!File::exists($folderPath)) {
                    File::makeDirectory($folderPath, 0755, true, true);
                }

                $fileName = Str::uuid() . '.' . $file->getClientOriginalExtension();
                $file->move($folderPath, $fileName);

                $fullUrl = url($folderName . '/' . $fileName);

                $docDescription = $request->Beg_Doc_description[$index] ?? 'Document_' . ($index + 1);

                $docRecord = DocumentLibrary::create([
                    'Fnc_Id'      => $request->Fnc_Id ?? 1,
                    'Rec_Id'      => $newBudgetEntry->Budg_Id,
                    'Description' => $docDescription,
                    'Doc_Upload'  => $fullUrl,
                    'Serial_No'   => count($docsToKeep) + count($newDocs) + 1,
                ]);

                $newDocs[] = [
                    'doc_lib_id'  => $docRecord->Doc_Lib,
                    'name'        => 'Document_' . ($index + 1),
                    'description' => $docDescription,
                    'url'         => $fullUrl,
                    'type'        => $file->getClientOriginalExtension(),
                ];
            }
        }

 

        elseif ($request->has('Beg_Doc') && is_array($request->Beg_Doc)) {

            foreach ($request->Beg_Doc as $index => $base64String) {

                if (empty($base64String)) continue;

                $fileInfo = $this->extractFileInfoFromBase64($base64String);

                if (!$fileInfo) continue;

                $fileData = $fileInfo['data'];
                $mimeType = $fileInfo['mime'];
                $extension = $this->getExtensionFromMime($mimeType);

                $docDescription = $request->Beg_Doc_description[$index] ?? 'Document_' . ($index + 1);

                $fileName = Str::uuid() . '.' . $extension;

                $folderName = 'budget_documents';
                $folderPath = public_path($folderName);

                if (!File::exists($folderPath)) {
                    File::makeDirectory($folderPath, 0755, true, true);
                }

                $filePath = $folderPath . '/' . $fileName;

                file_put_contents($filePath, $fileData);

                $publicUrl = url($folderName . '/' . $fileName);

                $docRecord = DocumentLibrary::create([
                    'Fnc_Id'      => $request->Fnc_Id ?? 1,
                    'Rec_Id'      => $newBudgetEntry->Budg_Id,
                    'Description' => $docDescription,
                    'Doc_Upload'  => $publicUrl,
                    'Serial_No'   => count($docsToKeep) + count($newDocs) + 1,
                ]);

                $newDocs[] = [
                    'doc_lib_id'  => $docRecord->Doc_Lib,
                    'name'        => 'Document_' . ($index + 1),
                    'description' => $docDescription,
                    'url'         => $publicUrl,
                    'type'        => $extension,
                ];
            }
        }


        $allDocs = array_merge($docsToKeep, $newDocs);

        if (!empty($newDocs)) {

            $newBudgetEntry->update([
                'Beg_Doc' => $allDocs
            ]);
        }

        DB::commit();

        $freshEntry = BudgetEntry::with(['financialYear', 'department', 'budgetHead'])
            ->find($newBudgetEntry->Budg_Id);

        return response()->json([
            'success' => true,
            'message' => 'Budget entry updated successfully',
            'data' => $this->formatBudgetEntryData($freshEntry),
        ], 200);

    } catch (\Exception $e) {

        DB::rollBack();

        Log::error('Budget Entry Update Error: ' . 'Something went wrong. Please try again later.');

        return response()->json([
            'success' => false,
            'message' => 'Failed to update budget entry',
            'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage(),
        ], 500);
    }
}


    private function extractFileInfoFromBase64($base64String)
    {
        $base64String = trim($base64String);

        if (preg_match('/^data:([a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+);base64,/', $base64String, $matches)) {
            $mimeType = $matches[1];
            $base64Data = substr($base64String, strpos($base64String, ',') + 1);
            $fileData = base64_decode($base64Data, true);

            if ($fileData !== false) {
                return [
                    'mime' => $mimeType,
                    'data' => $fileData,
                ];
            }
        }

        $fileData = base64_decode($base64String, true);
        if ($fileData !== false) {
            $finfo = finfo_open(FILEINFO_MIME_TYPE);
            $mimeType = finfo_buffer($finfo, $fileData);
            finfo_close($finfo);
            return [
                'mime' => $mimeType ?: 'application/octet-stream',
                'data' => $fileData,
            ];
        }

        return null;
    }

    private function getExtensionFromMime($mimeType)
    {
        $mimeMap = [
            'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
            'application/vnd.oasis.opendocument.text' => 'odt',
            'application/vnd.oasis.opendocument.presentation' => 'odp',
            'application/vnd.oasis.opendocument.graphics' => 'odg',
            'application/vnd.ms-excel' => 'xls',
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
            'application/vnd.ms-powerpoint' => 'ppt',
            'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
            'application/msword' => 'doc',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
            'application/pdf' => 'pdf',
            'image/jpeg' => 'jpg',
            'image/png' => 'png',
            'image/gif' => 'gif',
            'image/bmp' => 'bmp',
            'image/svg+xml' => 'svg',
            'image/webp' => 'webp',
            'text/plain' => 'txt',
            'text/csv' => 'csv',
            'text/html' => 'html',
            'application/json' => 'json',
            'application/xml' => 'xml',
            'application/octet-stream' => 'bin'
        ];

        return $mimeMap[$mimeType] ?? 'bin';
    }

    public function getVersionHistory($budgId)
    {
        try {
            $budgetEntry = BudgetEntry::find($budgId);

            if (!$budgetEntry) {
                return response()->json(
                    [
                        'success' => false,
                        'message' => 'Budget entry not found',
                    ],
                    404,
                );
            }

            $rootEntry = $budgetEntry->getRootEntryAttribute();

            $versions = BudgetEntry::where('Budg_Id', $rootEntry->Budg_Id)
                ->orWhere('Ref_Id', $rootEntry->Budg_Id)
                ->with(['financialYear', 'department', 'budgetHead'])
                ->orderBy('created_at', 'asc')
                ->get();

            $formattedVersions = [];
            $previousVersion = null;

            foreach ($versions as $index => $version) {
                $versionData = $this->formatBudgetEntryData($version);

                $changes = [];
                if ($previousVersion) {
                    if ((float) $previousVersion->Amount != (float) $version->Amount) {
                        $changes[] = [
                            'field' => 'Amount',
                            'old' => (float) $previousVersion->Amount,
                            'new' => (float) $version->Amount,
                            'change' => (float) ($version->Amount - $previousVersion->Amount),
                            'formatted_change' => ($version->Amount > $previousVersion->Amount ? '+' : '') . '₹ ' . number_format($version->Amount - $previousVersion->Amount, 2),
                        ];
                    }

                    if ($previousVersion->Status != $version->Status) {
                        $changes[] = [
                            'field' => 'Status',
                            'old' => $this->convertToStatusText($previousVersion->Status),
                            'new' => $this->convertToStatusText($version->Status),
                            'old_code' => $previousVersion->Status,
                            'new_code' => $version->Status,
                        ];
                    }

                    if ($previousVersion->Bh_Id != $version->Bh_Id) {
                        $changes[] = [
                            'field' => 'Budget Head',
                            'old' => $previousVersion->bh_id,
                            'new' => $version->bh_id,
                        ];
                    }
                }

                $versionData['version_number'] = $index + 1;
                $versionData['is_latest'] = $version->is_latest;
                $versionData['Ref_Id'] = $version->Ref_Id;
                $versionData['changes_from_previous'] = $changes;

                $formattedVersions[] = $versionData;
                $previousVersion = $version;
            }

            return response()->json([
                'success' => true,
                'message' => 'Version history retrieved successfully',
                'root_entry_id' => $rootEntry->Budg_Id,
                'current_version_id' => $budgetEntry->Budg_Id,
                'total_versions' => $versions->count(),
                'versions' => $formattedVersions,
                'summary' => [
                    'first_version_date' => $versions->first()->created_at->format('Y-m-d H:i:s'),
                    'last_version_date' => $versions->last()->created_at->format('Y-m-d H:i:s'),
                    'time_span_days' => $versions->first()->created_at->diffInDays($versions->last()->created_at),
                    'status_transitions' => $this->getStatusTransitions($versions),
                ],
            ]);
        } catch (\Exception $e) {
            return response()->json(
                [
                    'success' => false,
                    'message' => 'Failed to retrieve version history',
                    'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage(),
                ],
                500,
            );
        }
    }

    private function getStatusTransitions($versions)
    {
        $transitions = [];
        $previousStatus = null;

        foreach ($versions as $version) {
            if ($previousStatus !== null && $previousStatus !== $version->Status) {
                $transitions[] = [
                    'from' => $this->convertToStatusText($previousStatus),
                    'to' => $this->convertToStatusText($version->Status),
                    'from_code' => $previousStatus,
                    'to_code' => $version->Status,
                    'date' => $version->created_at->format('Y-m-d H:i:s'),
                    'version' => $version->Budg_Id,
                ];
            }
            $previousStatus = $version->Status;
        }

        return $transitions;
    }

    public function destroy($id)
    {
        DB::beginTransaction();

        try {
            $entry = BudgetEntry::find($id);

            if (!$entry) {
                return response()->json([
                    'success' => false,
                    'message' => 'Budget entry not found'
                ], 404);
            }

            Log::info("Deleting Budget Entry ID: " . $id);

            if (!empty($entry->Beg_Doc)) {
                $this->deleteBudgetDocuments($entry->Beg_Doc);
            }

            $entry->delete();

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Budget entry deleted successfully'
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Delete Budget Entry Error: ' . 'Something went wrong. Please try again later.');
            return response()->json([
                'success' => false,
                'message' => 'Failed to delete budget entry',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function deleteDocument(Request $request, $budgetEntryId, $documentId)
    {
        DB::beginTransaction();

        try {
            $budgetEntry = BudgetEntry::find($budgetEntryId);

            if (!$budgetEntry) {
                return response()->json([
                    'success' => false,
                    'message' => 'Budget entry not found'
                ], 404);
            }

            $documents = $budgetEntry->Beg_Doc ?? [];
            if (is_string($documents)) {
                $documents = json_decode($documents, true) ?? [];
            }

            $documentToDelete = null;
            $documentIndex = null;

            foreach ($documents as $index => $doc) {
                if (isset($doc['doc_lib_id']) && $doc['doc_lib_id'] == $documentId) {
                    $documentToDelete = $doc;
                    $documentIndex = $index;
                    break;
                }
            }

            if (!$documentToDelete) {
                return response()->json([
                    'success' => false,
                    'message' => 'Document not found in this budget entry'
                ], 404);
            }

            if (isset($documentToDelete['url'])) {
                $parsedUrl = parse_url($documentToDelete['url']);
                $path = isset($parsedUrl['path']) ? ltrim($parsedUrl['path'], '/') : '';

                if (strpos($path, 'budget_documents/') === 0) {
                    $filePath = public_path($path);
                    if (file_exists($filePath)) {
                        unlink($filePath);
                        Log::info("Deleted physical file: " . $filePath);
                    }
                }
            }

            DocumentLibrary::where('Doc_Lib', $documentId)->delete();
            Log::info("Deleted document library record: " . $documentId);

            unset($documents[$documentIndex]);
            $documents = array_values($documents);

            $budgetEntry->update([
                'Beg_Doc' => $documents
            ]);

            DB::commit();

            $freshEntry = BudgetEntry::with(['financialYear', 'department', 'budgetHead'])
                ->find($budgetEntry->Budg_Id);

            return response()->json([
                'success' => true,
                'message' => 'Document deleted successfully',
                'data' => [
                    'budg_id' => $budgetEntry->Budg_Id,
                    'deleted_document' => [
                        'doc_lib_id' => $documentToDelete['doc_lib_id'] ?? null,
                        'name' => $documentToDelete['name'] ?? 'Unknown',
                        'url' => $documentToDelete['url'] ?? null,
                        'type' => $documentToDelete['type'] ?? null
                    ],
                    'remaining_documents' => count($documents),
                    'updated_budget_entry' => $this->formatBudgetEntryData($freshEntry)
                ]
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Delete Document Error: ' . 'Something went wrong. Please try again later.');
            return response()->json([
                'success' => false,
                'message' => 'Failed to delete document',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    private function deleteBudgetDocuments($documents)
    {
        if (!is_array($documents)) {
            return;
        }

        foreach ($documents as $doc) {
            try {
                if (isset($doc['url'])) {
                    $parsed = parse_url($doc['url']);
                    if (isset($parsed['path'])) {
                        $path = ltrim($parsed['path'], '/');
                        if (str_starts_with($path, 'storage/')) {
                            $fullPath = public_path($path);
                            if (file_exists($fullPath)) {
                                unlink($fullPath);
                            }
                        } elseif (str_starts_with($path, 'budget_documents/')) {
                            $fullPath = public_path($path);
                            if (file_exists($fullPath)) {
                                unlink($fullPath);
                            }
                        }
                    }
                }
            } catch (\Exception $e) {
                Log::error('Error deleting document: ' . 'Something went wrong. Please try again later.');
            }
        }
    }

    private function formatBudgetEntryData($item)
    {
        $docs = $item->Beg_Doc ?? [];
        if (is_string($docs)) {
            $docs = json_decode($docs, true) ?? [];
        }

        $formattedDocs = [];
        foreach ($docs as $doc) {
            if (is_array($doc)) {
                $extension = $doc['type'] ?? '';
                if (empty($extension) && isset($doc['url'])) {
                    $extension = $this->getFileExtensionFromUrl($doc['url']);
                }

                $size = $doc['size'] ?? null;
                $formattedSize = $size ? $this->formatFileSize($size) : null;
                $fileCategory = $this->getFileCategory($extension);

                $formattedDocs[] = [
                    'doc_lib_id' => $doc['doc_lib_id'] ?? null,
                    'name' => $doc['name'] ?? 'Document',
                    'original_name' => $doc['original_name'] ?? $doc['name'] ?? 'Document',
                    'url' => $doc['url'] ?? null,
                    'path' => $doc['path'] ?? null,
                    'type' => $extension,
                    'mime' => $doc['mime'] ?? $this->getMimeFromExtension($extension),
                    'size' => $size,
                    'formatted_size' => $formattedSize,
                    'file_category' => $fileCategory,
                    'icon' => $this->getFileIcon($fileCategory, $extension),
                    'serial_no' => $doc['serial_no'] ?? null,
                    'description' => $doc['description'] ?? $doc['name'] ?? 'Document',
                    'uploaded_at' => $doc['created_at'] ?? $item->created_at,
                    'is_image' => in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']),
                    'is_pdf' => $extension === 'pdf',
                    'is_document' => in_array($extension, ['doc', 'docx', 'txt', 'rtf', 'odt']),
                    'is_spreadsheet' => in_array($extension, ['xls', 'xlsx', 'csv', 'ods']),
                    'is_presentation' => in_array($extension, ['ppt', 'pptx', 'odp']),
                    'is_archive' => in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz']),
                ];
            } elseif (is_string($doc)) {
                $extension = $this->getFileExtensionFromUrl($doc);
                $fileCategory = $this->getFileCategory($extension);

                $formattedDocs[] = [
                    'doc_lib_id' => null,
                    'name' => 'Document',
                    'original_name' => 'Document',
                    'url' => $doc,
                    'path' => null,
                    'type' => $extension,
                    'mime' => $this->getMimeFromExtension($extension),
                    'size' => null,
                    'formatted_size' => null,
                    'file_category' => $fileCategory,
                    'icon' => $this->getFileIcon($fileCategory, $extension),
                    'serial_no' => null,
                    'description' => 'Document',
                    'uploaded_at' => $item->created_at,
                    'is_image' => in_array($extension, ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg']),
                    'is_pdf' => $extension === 'pdf',
                    'is_document' => in_array($extension, ['doc', 'docx', 'txt', 'rtf', 'odt']),
                    'is_spreadsheet' => in_array($extension, ['xls', 'xlsx', 'csv', 'ods']),
                    'is_presentation' => in_array($extension, ['ppt', 'pptx', 'odp']),
                    'is_archive' => in_array($extension, ['zip', 'rar', '7z', 'tar', 'gz']),
                ];
            }
        }

        $totalSize = array_sum(array_column($formattedDocs, 'size') ?: [0]);

        $documentsByCategory = [
            'images' => array_filter($formattedDocs, fn($d) => $d['is_image']),
            'pdfs' => array_filter($formattedDocs, fn($d) => $d['is_pdf']),
            'spreadsheets' => array_filter($formattedDocs, fn($d) => $d['is_spreadsheet']),
            'presentations' => array_filter($formattedDocs, fn($d) => $d['is_presentation']),
            'documents' => array_filter($formattedDocs, fn($d) => $d['is_document']),
            'archives' => array_filter($formattedDocs, fn($d) => $d['is_archive']),
            'others' => array_filter($formattedDocs, fn($d) => !$d['is_image'] && !$d['is_pdf'] && !$d['is_spreadsheet'] && !$d['is_presentation'] && !$d['is_document'] && !$d['is_archive']),
        ];

        return [
            'budg_id' => $item->Budg_Id,
            'FY_Id' => $item->Fin_Year,
            'Dpt_id' => $item->Dpt_Id,
            'Bh_Id' => $item->Bh_Id,

            'financial_year' => $item->financialYear
                ? [
                    'financial_year_id' => $item->financialYear->FY_Id,
                    'financial_year_code' => $item->financialYear->FY_Code,
                    'financial_year_name' => $item->financialYear->FY_Name,
                    'start_date' => $item->financialYear->St_Date ?? ($item->financialYear->start_date ?? ($item->financialYear->From_Date ?? ($item->financialYear->FY_From ?? null))),
                    'end_date' => $item->financialYear->Ed_Date ?? ($item->financialYear->end_date ?? ($item->financialYear->To_Date ?? ($item->financialYear->FY_To ?? null))),
                    'is_active' => $item->financialYear->IsActive ?? null,
                    'created_at' => $item->financialYear->created_at ?? null,
                    'updated_at' => $item->financialYear->updated_at ?? null,
                ]
                : null,

            'department' => $item->department
                ? [
                    'id' => $item->department->Dpt_id,
                    'desc' => $item->department->Dpt_Desc ?? null,
                    'name' => $item->department->Dpt_Name ?? null,
                    'group_code' => $item->department->GrCod ?? null,
                    'up_group' => $item->department->UpGrp ?? null,
                    'group_srn' => $item->department->GrSrn ?? null,
                    'group_stt' => $item->department->GrStt ?? null,
                    'is_visible' => $item->department->isvisible ?? 1,
                    'created_at' => $item->department->created_at ?? null,
                    'updated_at' => $item->department->updated_at ?? null,
                    'deleted_at' => $item->department->deleted_at ?? null,
                ]
                : null,

            'budget_head' => $item->budgetHead ? [
                'bh_id' => $item->budgetHead->Bh_Id,
                'gr_cd' => $item->budgetHead->Gr_Cd,
                'up_gr' => $item->budgetHead->Up_Gr,
                'gr_nm' => $item->budgetHead->Gr_Nm,
                'gr_sr' => $item->budgetHead->Gr_Sr,
                'gr_st' => $item->budgetHead->Gr_St,
                'is_del' => $item->budgetHead->is_del,
                'gr_exp' => $item->budgetHead->Gr_Exp,
                'gr_buk' => $item->budgetHead->Gr_Buk,
                'gr_prt' => $item->budgetHead->Gr_Prt,
                'level_name' => $item->budgetHead->level_name,
                'is_root_level' => $item->budgetHead->isRootLevel(),
                'has_children' => $item->budgetHead->hasChildren(),
                'series' => $item->budgetHead->series,
                'created_at' => $item->budgetHead->created_at,
                'updated_at' => $item->budgetHead->updated_at,
                'deleted_at' => $item->budgetHead->deleted_at,
                'parent_group' => $item->budgetHead->parentGroup ? [
                    'bh_id' => $item->budgetHead->parentGroup->Bh_Id,
                    'gr_cd' => $item->budgetHead->parentGroup->Gr_Cd,
                    'gr_nm' => $item->budgetHead->parentGroup->Gr_Nm,
                ] : null,
            ] : null,

            'amount' => (float) $item->Amount,
            'formatted_amount' => $this->formatCurrency($item->Amount),
            'sug_amount' => $item->Sug_Amount ? (float) $item->Sug_Amount : null,
            'formatted_sug_amount' => $this->formatCurrency($item->Sug_Amount),

            'Beg_Doc' => $formattedDocs,
            'document_count' => count($formattedDocs),
            'has_documents' => !empty($formattedDocs),
            'document_summary' => [
                'total_files' => count($formattedDocs),
                'total_size' => $totalSize,
                'formatted_total_size' => $this->formatFileSize($totalSize),
                'by_category' => [
                    'images' => count($documentsByCategory['images']),
                    'pdfs' => count($documentsByCategory['pdfs']),
                    'spreadsheets' => count($documentsByCategory['spreadsheets']),
                    'presentations' => count($documentsByCategory['presentations']),
                    'documents' => count($documentsByCategory['documents']),
                    'archives' => count($documentsByCategory['archives']),
                    'others' => count($documentsByCategory['others']),
                ],
                'file_types' => array_values(array_unique(array_column($formattedDocs, 'type'))),
                'has_images' => !empty($documentsByCategory['images']),
                'has_pdfs' => !empty($documentsByCategory['pdfs']),
                'has_spreadsheets' => !empty($documentsByCategory['spreadsheets']),
                'has_presentations' => !empty($documentsByCategory['presentations']),
            ],

            'status' => $item->Status,
            'status_text' => $this->getStatusText($item->Status),
            'is_workflow_status' => $item->IsWFStatus ?? $item->getIsWorkflowStatusAttribute(),
            'is_active' => $item->IsActive ?? $item->getIsActiveAttribute(),
            'can_edit' => $item->CanEdit ?? $item->getCanEditAttribute(),
            'Ref_Id' => $item->Ref_Id,
            'is_latest' => $item->Is_Latest,

            'created_at' => $item->created_at,
            'updated_at' => $item->updated_at,
        ];
    }

    private function getFileExtensionFromUrl($url)
    {
        if (!$url) return 'unknown';
        $path = parse_url($url, PHP_URL_PATH);
        return strtolower(pathinfo($path, PATHINFO_EXTENSION)) ?: 'unknown';
    }

    private function formatFileSize($bytes, $precision = 2)
    {
        if ($bytes === null || $bytes === 0) return null;
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow);
        return round($bytes, $precision) . ' ' . $units[$pow];
    }

    private function getFileCategory($extension)
    {
        $extension = strtolower($extension);
        $categories = [
            'image' => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg', 'ico'],
            'pdf' => ['pdf'],
            'spreadsheet' => ['xls', 'xlsx', 'csv', 'ods', 'xlsm'],
            'presentation' => ['ppt', 'pptx', 'odp', 'pps', 'ppsx'],
            'document' => ['doc', 'docx', 'txt', 'rtf', 'odt', 'md'],
            'archive' => ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'],
        ];
        foreach ($categories as $category => $extensions) {
            if (in_array($extension, $extensions)) {
                return $category;
            }
        }
        return 'other';
    }

    private function getFileIcon($category, $extension)
    {
        $icons = [
            'image' => 'fa-file-image',
            'pdf' => 'fa-file-pdf',
            'spreadsheet' => 'fa-file-excel',
            'presentation' => 'fa-file-powerpoint',
            'document' => 'fa-file-word',
            'archive' => 'fa-file-archive',
            'other' => 'fa-file',
        ];
        $extensionIcons = [
            'txt' => 'fa-file-alt',
            'csv' => 'fa-file-csv',
            'xml' => 'fa-file-code',
            'json' => 'fa-file-code',
            'mp3' => 'fa-file-audio',
            'mp4' => 'fa-file-video',
        ];
        if (isset($extensionIcons[$extension])) {
            return $extensionIcons[$extension];
        }
        return $icons[$category] ?? 'fa-file';
    }

    private function getMimeFromExtension($extension)
    {
        $mimeMap = [
            'pdf' => 'application/pdf',
            'doc' => 'application/msword',
            'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'xls' => 'application/vnd.ms-excel',
            'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            'ppt' => 'application/vnd.ms-powerpoint',
            'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            'txt' => 'text/plain',
            'csv' => 'text/csv',
            'rtf' => 'application/rtf',
            'odt' => 'application/vnd.oasis.opendocument.text',
            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
            'odp' => 'application/vnd.oasis.opendocument.presentation',
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            'bmp' => 'image/bmp',
            'svg' => 'image/svg+xml',
            'webp' => 'image/webp',
            'ico' => 'image/x-icon',
            'zip' => 'application/zip',
            'rar' => 'application/x-rar-compressed',
            '7z' => 'application/x-7z-compressed',
            'tar' => 'application/x-tar',
            'gz' => 'application/gzip',
        ];
        return $mimeMap[$extension] ?? 'application/octet-stream';
    }
}
