<?php

namespace App\Http\Controllers;

use App\Models\Budget;
use App\Models\BudgetItem;
use App\Models\Organization;
use App\Models\TransactionCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

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

    protected function getOrganizationScope()
    {
        $user = Auth::user();
        if ($user->hasRole('Super Admin')) {
            return null;
        }
        $orgIds = collect([$user->organization_id]);
        $this->getChildOrganizations($user->organization_id, $orgIds);
        return $orgIds->toArray();
    }

    protected function getChildOrganizations($parentId, &$orgIds)
    {
        $children = Organization::where('parent_id', $parentId)->pluck('id');
        foreach ($children as $childId) {
            $orgIds->push($childId);
            $this->getChildOrganizations($childId, $orgIds);
        }
    }

    public function index(Request $request)
    {
        $query = Budget::with('organization');
        $scope = $this->getOrganizationScope();
        
        if ($scope !== null) {
            $query->whereIn('organization_id', $scope);
        }

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

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

        $budgets = $query->orderByDesc('fiscal_year')->paginate(20)->withQueryString();

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

    public function create()
    {
        $scope = $this->getOrganizationScope();
        $organizations = Organization::query();
        if ($scope !== null) {
            $organizations->whereIn('id', $scope);
        }
        $organizations = $organizations->orderBy('name')->get();

        return view('budgets.create', compact('organizations'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'organization_id' => 'required|exists:organizations,id',
            'fiscal_year' => 'required|integer|min:2020|max:2100',
        ]);

        // Check scope
        $scope = $this->getOrganizationScope();
        if ($scope !== null && !in_array($validated['organization_id'], $scope)) {
            abort(403);
        }

        // Check if budget already exists for this org/year
        $exists = Budget::where('organization_id', $validated['organization_id'])
            ->where('fiscal_year', $validated['fiscal_year'])
            ->exists();
        
        if ($exists) {
            return back()->withInput()->with('error', 'A budget already exists for this organization and fiscal year.');
        }

        $validated['creator_id'] = Auth::id();
        $budget = Budget::create($validated);

        return redirect()->route('budgets.show', $budget)->with('success', 'Budget created. Now add budget items.');
    }

    public function show(Budget $budget)
    {
        $scope = $this->getOrganizationScope();
        if ($scope !== null && !in_array($budget->organization_id, $scope)) {
            abort(403);
        }

        $budget->load(['organization', 'items.category']);
        
        $incomeItems = $budget->items->filter(fn($i) => $i->category?->type === 'Income');
        $expenseItems = $budget->items->filter(fn($i) => $i->category?->type === 'Expense');

        $categories = TransactionCategory::orderBy('type')->orderBy('name')->get();

        return view('budgets.show', compact('budget', 'incomeItems', 'expenseItems', 'categories'));
    }

    public function destroy(Budget $budget)
    {
        $scope = $this->getOrganizationScope();
        if ($scope !== null && !in_array($budget->organization_id, $scope)) {
            abort(403);
        }

        $budget->delete();

        return redirect()->route('budgets.index')->with('success', 'Budget deleted.');
    }

    /**
     * Add item to budget.
     */
    public function addItem(Request $request, Budget $budget)
    {
        $scope = $this->getOrganizationScope();
        if ($scope !== null && !in_array($budget->organization_id, $scope)) {
            abort(403);
        }

        $validated = $request->validate([
            'category_id' => 'required|exists:transaction_categories,id',
            'amount' => 'required|numeric|min:0.01',
            'description' => 'nullable|string|max:255',
        ]);

        $validated['budget_id'] = $budget->id;
        BudgetItem::create($validated);

        return back()->with('success', 'Budget item added.');
    }

    /**
     * Remove item from budget.
     */
    public function removeItem(Budget $budget, BudgetItem $item)
    {
        $scope = $this->getOrganizationScope();
        if ($scope !== null && !in_array($budget->organization_id, $scope)) {
            abort(403);
        }

        if ($item->budget_id !== $budget->id) {
            abort(404);
        }

        $item->delete();

        return back()->with('success', 'Budget item removed.');
    }

    /**
     * Approve budget.
     */
    /**
     * Submit budget for approval.
     */
    public function submit(Budget $budget)
    {
        $this->authorize('update', $budget);
        
        if ($budget->status !== 'Draft') {
            abort(400, 'Only draft budgets can be submitted.');
        }

        $budget->update(['status' => 'Pending']);

        return back()->with('success', 'Budget submitted for approval.');
    }

    /**
     * Approve budget (Dual Control).
     */
    public function approve(Budget $budget)
    {
        $this->authorize('approve', $budget);

        if ($budget->status !== 'Pending') {
            abort(400, 'This budget is not pending approval.');
        }

        if (Auth::id() === $budget->creator_id) {
            return back()->with('error', 'You cannot approve your own budget submission (Maker-Checker rule).');
        }

        $budget->update([
            'status' => 'Approved',
            'approver_id' => Auth::id(),
            'rejection_reason' => null,
        ]);

        return back()->with('success', 'Budget approved successfully.');
    }

    /**
     * Reject budget.
     */
    public function reject(Request $request, Budget $budget)
    {
        $this->authorize('approve', $budget);

        if ($budget->status !== 'Pending') {
            abort(400, 'This budget is not pending approval.');
        }

        $request->validate(['reason' => 'required|string|max:255']);

        $budget->update([
            'status' => 'Draft',
            'rejection_reason' => $request->reason,
            'approver_id' => Auth::id(),
        ]);

        return back()->with('success', 'Budget rejected and returned to draft.');
    }

    /**
     * Request amendment (Unpublish).
     */
    public function requestAmendment(Budget $budget)
    {
        if ($budget->status !== 'Approved') {
            abort(400, 'Only approved budgets can request amendment.');
        }

        $budget->update(['status' => 'Amendment Pending']);

        return back()->with('success', 'Amendment requested.');
    }

    /**
     * Grant amendment request.
     */
    public function grantAmendment(Budget $budget)
    {
        $this->authorize('approve', $budget);

        if ($budget->status !== 'Amendment Pending') {
            abort(400, 'No amendment pending.');
        }

        $budget->update([
            'status' => 'Draft',
            'approver_id' => Auth::id(), // Track who granted it
        ]);

        return back()->with('success', 'Amendment granted. Budget is now actionable.');
    }
}
