<?php
// app/Http/Controllers/admin/ExpenseController.php

namespace App\Http\Controllers\admin;

use App\Http\Controllers\Controller;
use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Services\ExpenseServices;
use App\Services\ExcelServices;
use App\Traits\GetCompanyInfo;
use App\Traits\GetModelsPaginated;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

class ExpenseController extends Controller
{
    use GetCompanyInfo;
    use GetModelsPaginated;
    
    protected ExpenseServices $expenseServices;
    protected ExcelServices $excelServices;
    
    public function __construct(ExpenseServices $expenseServices, ExcelServices $excelServices)
    {
        $this->expenseServices = $expenseServices;
        $this->excelServices = $excelServices;
    }
    
    /**
     * Listado de gastos
     */
    public function index()
    {
        return view('admin.expense.index');
    }
    
    /**
     * Datos paginados para DataTable
     */
    public function expensePaginatedJson(Request $request)
    {
        $companyId = $this->resolveCompanyId();
        
        return $this->paginateFromService(
            $request,
            function (int $page, int $length, ?string $searchValue, ?string $status, Request $req) use ($companyId) {
                return $this->expenseServices->getExpenseData(
                    $page,
                    $length,
                    $searchValue,
                    $status,
                    $req->input('date_from'),
                    $req->input('date_to'),
                    $req->input('category_id'),
                    $companyId
                );
            }
        );
    }
    
    /**
     * Formulario de creación
     */
    public function create()
    {
        $companyId = $this->resolveCompanyId();
        $categories = $this->expenseServices->getCategories($companyId);
        $suppliers = $this->getSuppliers();
        $activeRate = $this->getActiveRate();
        
        return view('admin.expense.create', compact('categories', 'suppliers', 'activeRate'));
    }
    
    /**
     * Guardar nuevo gasto
     */
    public function store(Request $request)
    {
        $userId = Auth::id();
        $companyId = $this->resolveCompanyId();
        
        if (!$companyId) {
            return redirect()->back()->withErrors(['error' => 'No se encontró empresa asociada.'])->withInput();
        }
        
        try {
            $expense = $this->expenseServices->createExpense($request, $userId, $companyId);
            
            return redirect()
                ->route('admin_fit.expense.index')
                ->with('success', "Gasto #{$expense->id} registrado correctamente.");
        } catch (\Illuminate\Validation\ValidationException $e) {
            return redirect()->back()->withErrors($e->errors())->withInput();
        } catch (\Exception $e) {
            return redirect()->back()->withErrors(['error' => 'Error al registrar el gasto: ' . $e->getMessage()])->withInput();
        }
    }
    
    /**
     * Formulario de edición
     */
    public function edit(Expense $expense)
    {
        $companyId = $this->resolveCompanyId();
        
        // Verificar que el gasto pertenezca a la empresa
        if ($expense->company_id !== $companyId) {
            abort(403, 'No autorizado para editar este gasto.');
        }
        
        $categories = $this->expenseServices->getCategories($companyId);
        $suppliers = $this->getSuppliers();
        $activeRate = $this->getActiveRate();
        return view('admin.expense.edit', compact('expense', 'categories', 'suppliers', 'activeRate'));
    }
    
    /**
     * Actualizar gasto
     */
    public function update(Request $request, Expense $expense)
    {
        $companyId = $this->resolveCompanyId();
        
        if ($expense->company_id !== $companyId) {
            abort(403, 'No autorizado para modificar este gasto.');
        }
        
        try {
            $this->expenseServices->updateExpense($request, $expense, $companyId);
            
            return redirect()
                ->route('admin_fit.expense.index')
                ->with('success', "Gasto #{$expense->id} actualizado correctamente.");
        } catch (\Illuminate\Validation\ValidationException $e) {
            return redirect()->back()->withErrors($e->errors())->withInput();
        } catch (\Exception $e) {
            return redirect()->back()->withErrors(['error' => 'Error al actualizar el gasto: ' . $e->getMessage()])->withInput();
        }
    }
    
    /**
     * Eliminar gasto
     */
    public function destroy(Expense $expense)
    {
        $companyId = $this->resolveCompanyId();
        
        if ($expense->company_id !== $companyId) {
            abort(403, 'No autorizado para eliminar este gasto.');
        }
        
        try {
            $this->expenseServices->deleteExpense($expense, $companyId);
            
            return redirect()
                ->route('admin_fit.expense.index')
                ->with('success', "Gasto #{$expense->id} eliminado correctamente.");
        } catch (\Exception $e) {
            return redirect()->back()->withErrors(['error' => 'Error al eliminar el gasto: ' . $e->getMessage()]);
        }
    }
    
    /**
     * Resumen de gastos (dashboard)
     */
    public function summary(Request $request)
    {
        $companyId = $this->resolveCompanyId();
        $startDate = $request->input('start_date', now()->startOfMonth()->toDateString());
        $endDate = $request->input('end_date', now()->endOfMonth()->toDateString());
        
        $summary = $this->expenseServices->getExpenseSummary($companyId, $startDate, $endDate);
        
        return response()->json($summary);
    }
    
    /**
     * Exportar gastos a Excel
     */
    public function export(Request $request)
    {
        $companyId = $this->resolveCompanyId();
        
        $exportFields = [
            'id' => 'ID',
            'description' => 'Descripción',
            'amount_formatted' => 'Monto',
            'expense_date_formatted' => 'Fecha',
            'payment_method' => 'Método de Pago',
            'reference' => 'Referencia',
            'category_name' => 'Categoría',
            'supplier_name' => 'Proveedor',
            'status' => 'Estado',
            'created_at_formatted' => 'Registrado',
        ];
        
        $selectedFields = $request->input('fields', array_keys($exportFields));
        $searchValue = $request->input('search_value');
        $status = $request->input('status');
        $dateFrom = $request->input('date_from');
        $dateTo = $request->input('date_to');
        $categoryId = $request->input('category_id');
        
        $paginator = $this->expenseServices->getExpenseData(
            1, 9999, $searchValue, $status, $dateFrom, $dateTo, $categoryId, $companyId
        );
        
        $rows = $paginator->getCollection();
        
        return $this->excelServices->downloadGenericExcel(
            'gastos_' . now()->format('Ymd_His') . '.xls',
            $exportFields,
            $selectedFields,
            $rows
        );
    }
    
    /**
     * Imagen del comprobante
     */
    public function image(string $filename)
    {
        $imagePath = storage_path('app/public/expenses/large/' . $filename);
        
        if (!\Illuminate\Support\Facades\File::exists($imagePath)) {
            $imagePath = storage_path('app/public/expenses/small/' . $filename);
        }
        
        if (!\Illuminate\Support\Facades\File::exists($imagePath)) {
            $imagePath = public_path('images/no-user-imagen.jpg');
        }
        
        return response()->file($imagePath);
    }
    
    // ==================== CATEGORÍAS ====================
    
    /**
     * Listado de categorías de gastos
     */
    public function categoriesIndex()
    {
        $companyId = $this->resolveCompanyId();
        $categories = $this->expenseServices->getCategories($companyId);
        
        return view('admin.expense.categories', compact('categories'));
    }
    
    /**
     * Crear categoría
     */
    public function storeCategory(Request $request)
    {
        $companyId = $this->resolveCompanyId();
        
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:100'],
            'description' => ['nullable', 'string', 'max:255'],
            'color' => ['nullable', 'string', 'max:20'],
            'is_active' => ['nullable', 'boolean'],
        ]);
        
        $category = $this->expenseServices->createCategory($validated, $companyId);
        
        return response()->json([
            'success' => true,
            'message' => 'Categoría creada correctamente.',
            'data' => $category,
        ]);
    }
    
    /**
     * Actualizar categoría
     */
    public function updateCategory(Request $request, ExpenseCategory $category)
    {
        $companyId = $this->resolveCompanyId();
        
        $validated = $request->validate([
            'name' => ['required', 'string', 'max:100'],
            'description' => ['nullable', 'string', 'max:255'],
            'color' => ['nullable', 'string', 'max:20'],
            'is_active' => ['nullable', 'boolean'],
        ]);
        
        $category = $this->expenseServices->updateCategory($category, $validated, $companyId);
        
        return response()->json([
            'success' => true,
            'message' => 'Categoría actualizada correctamente.',
            'data' => $category,
        ]);
    }
    
    /**
     * Eliminar categoría
     */
    public function destroyCategory(ExpenseCategory $category)
    {
        $companyId = $this->resolveCompanyId();
        
        try {
            $this->expenseServices->deleteCategory($category, $companyId);
            
            return response()->json([
                'success' => true,
                'message' => 'Categoría eliminada correctamente.',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => $e->getMessage(),
            ], 422);
        }
    }
    
    // ==================== MÉTODOS PRIVADOS ====================
    
    private function resolveCompanyId(): int
    {
        $userId = Auth::id();
        $companyInfo = $this->getCompanyInfo($userId);
        
        return (int) ($companyInfo?->id ?? 0);
    }
    
    private function getSuppliers(): \Illuminate\Support\Collection
    {
        return \App\Models\Supplier::query()
            ->where('is_active', 1)
            ->orderBy('supplier_name')
            ->get(['id', 'supplier_name']);
    }
    
    private function getActiveRate(): float
    {
        $rate = \App\Models\rate::query()
            ->where('is_active', 1)
            ->latest()
            ->first();
        
        return $rate ? (float) $rate->usd_rate : 1.0;
    }
}