<?php

namespace App\Http\Controllers;

use App\Models\Expense;
use App\Models\CattleCategory;
use App\Models\ExpenseCategory;
use Illuminate\Http\Request;

class ExpenseController extends Controller
{
    public function __construct()
    {
        $this->middleware('permission:view expenses', ['only' => ['index', 'show']]);
        $this->middleware('permission:create expenses', ['only' => ['create', 'store']]);
        $this->middleware('permission:update expenses', ['only' => ['edit', 'update']]);
        $this->middleware('permission:delete expenses', ['only' => ['destroy']]);
    }

    public function index()
    {
        $user = auth()->user();

        if ($user->hasRole('super admin')) {
            $expenses = Expense::with(['user', 'cattleCategory', 'expenseCategory'])
                ->latest()
                ->get();
        } else {
            $expenses = Expense::with(['user', 'cattleCategory', 'expenseCategory'])
                ->where('user_id', $user->id)
                ->latest()
                ->get();
        }

        return view('expenses.index', compact('expenses'));
    }

    public function create()
    {
        $user = auth()->user();

        if ($user->hasRole('super admin')) {
            $cattleCategories = CattleCategory::latest()->get();
            $expenseCategories = ExpenseCategory::latest()->get();
        } else {
            $cattleCategories = CattleCategory::where('user_id', $user->id)
                ->latest()
                ->get();

            $expenseCategories = ExpenseCategory::where('user_id', $user->id)
                ->latest()
                ->get();
        }

        return view('expenses.create', compact('cattleCategories', 'expenseCategories'));
    }

    public function store(Request $request)
    {
        $user = auth()->user();

        $request->validate([
            'cattle_category_id' => 'required|exists:cattle_categories,id',
            'expense_category_id' => 'required|exists:expense_categories,id',
            'title' => 'nullable|string|max:255',
            'expense_date' => 'nullable|date',
            'amount' => 'required|numeric|min:0',
            'description' => 'nullable|string',
        ]);

        $this->authorizeSelectedCategories(
            $request->cattle_category_id,
            $request->expense_category_id
        );

        $expense = Expense::create([
            'user_id' => $user->id,
            'cattle_category_id' => $request->cattle_category_id,
            'expense_category_id' => $request->expense_category_id,
            'title' => $request->title,
            'expense_date' => $request->expense_date,
            'amount' => $request->amount,
            'description' => $request->description,
        ]);

        audit_log(
            'expenses',
            $expense->id,
            'created',
            'Expense created successfully',
            $expense->toArray()
        );

        return redirect()
            ->route('expenses.index')
            ->with('success', 'Expense created successfully.');
    }

    public function show(Expense $expense)
    {
        $this->authorizeOwner($expense);

        $expense->load(['user', 'cattleCategory', 'expenseCategory']);

        audit_log(
            'expenses',
            $expense->id,
            'viewed',
            'Expense viewed successfully',
            $expense->toArray()
        );

        return view('expenses.show', compact('expense'));
    }

    public function edit(Expense $expense)
    {
        $this->authorizeOwner($expense);

        $user = auth()->user();

        if ($user->hasRole('super admin')) {
            $cattleCategories = CattleCategory::latest()->get();
            $expenseCategories = ExpenseCategory::latest()->get();
        } else {
            $cattleCategories = CattleCategory::where('user_id', $user->id)
                ->latest()
                ->get();

            $expenseCategories = ExpenseCategory::where('user_id', $user->id)
                ->latest()
                ->get();
        }

        return view('expenses.edit', compact('expense', 'cattleCategories', 'expenseCategories'));
    }

    public function update(Request $request, Expense $expense)
    {
        $this->authorizeOwner($expense);

        $request->validate([
            'cattle_category_id' => 'required|exists:cattle_categories,id',
            'expense_category_id' => 'required|exists:expense_categories,id',
            'title' => 'nullable|string|max:255',
            'expense_date' => 'nullable|date',
            'amount' => 'required|numeric|min:0',
            'description' => 'nullable|string',
        ]);

        $this->authorizeSelectedCategories(
            $request->cattle_category_id,
            $request->expense_category_id
        );

        $oldData = $expense->toArray();

        $expense->update([
            'cattle_category_id' => $request->cattle_category_id,
            'expense_category_id' => $request->expense_category_id,
            'title' => $request->title,
            'expense_date' => $request->expense_date,
            'amount' => $request->amount,
            'description' => $request->description,
        ]);

        audit_log(
            'expenses',
            $expense->id,
            'updated',
            'Expense updated successfully',
            [
                'old' => $oldData,
                'new' => $expense->fresh()->toArray(),
            ]
        );

        return redirect()
            ->route('expenses.index')
            ->with('success', 'Expense updated successfully.');
    }

    public function destroy(Expense $expense)
    {
        $this->authorizeOwner($expense);

        $oldData = $expense->toArray();

        $expense->delete();

        audit_log(
            'expenses',
            $oldData['id'],
            'deleted',
            'Expense deleted successfully',
            $oldData
        );

        return redirect()
            ->route('expenses.index')
            ->with('success', 'Expense deleted successfully.');
    }

    private function authorizeOwner(Expense $expense)
    {
        $user = auth()->user();

        if ($user->hasRole('super admin')) {
            return true;
        }

        if ($expense->user_id == $user->id) {
            return true;
        }

        abort(403, 'Unauthorized access.');
    }

    private function authorizeSelectedCategories($cattleCategoryId, $expenseCategoryId)
    {
        $user = auth()->user();

        if ($user->hasRole('super admin')) {
            return true;
        }

        $cattleCategoryExists = CattleCategory::where('id', $cattleCategoryId)
            ->where('user_id', $user->id)
            ->exists();

        $expenseCategoryExists = ExpenseCategory::where('id', $expenseCategoryId)
            ->where('user_id', $user->id)
            ->exists();

        if ($cattleCategoryExists && $expenseCategoryExists) {
            return true;
        }

        abort(403, 'Unauthorized category access.');
    }
}