<?php

namespace App\Http\Controllers;

use App\Models\PettyCashBalance;
use App\Models\PettyCashTransaction;
use App\Models\Expense;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class PettyCashController extends Controller
{
    public function getBalance(Request $request): JsonResponse
    {
        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        $balance = PettyCashBalance::where('restaurant_id', $restaurantId)
            ->where('branch_id', $branchId)
            ->first();

        if (!$balance) {
            // Create default balance if it doesn't exist
            $balance = PettyCashBalance::create([
                'restaurant_id' => $restaurantId,
                'branch_id' => $branchId,
                'current_balance' => 0,
                'daily_limit' => 5000,
                'transaction_limit' => 1000,
                'is_active' => true,
            ]);
        }

        // Get today's withdrawals
        $todayWithdrawals = $balance->getTodayWithdrawals();
        $remainingDailyLimit = max(0, $balance->daily_limit - $todayWithdrawals);

        return response()->json([
            'balance' => $balance,
            'today_withdrawals' => $todayWithdrawals,
            'remaining_daily_limit' => $remainingDailyLimit,
            'formatted_today_withdrawals' => 'KES ' . number_format($todayWithdrawals, 2),
            'formatted_remaining_daily_limit' => 'KES ' . number_format($remainingDailyLimit, 2),
        ]);
    }

    public function getTransactions(Request $request): JsonResponse
    {
        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        $query = PettyCashTransaction::with(['user', 'expense'])
            ->where('restaurant_id', $restaurantId)
            ->where('branch_id', $branchId);

        // Apply filters
        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        if ($request->filled('start_date')) {
            $query->whereDate('created_at', '>=', $request->start_date);
        }

        if ($request->filled('end_date')) {
            $query->whereDate('created_at', '<=', $request->end_date);
        }

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('description', 'like', "%{$search}%")
                  ->orWhere('transaction_number', 'like', "%{$search}%")
                  ->orWhere('notes', 'like', "%{$search}%");
            });
        }

        $transactions = $query->orderBy('created_at', 'desc')
            ->paginate($request->get('per_page', 2000));

        return response()->json($transactions);
    }

    public function deposit(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'description' => 'required|string|max:255',
            'notes' => 'nullable|string|max:1000',
        ]);

        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        try {
            DB::beginTransaction();

            $balance = PettyCashBalance::where('restaurant_id', $restaurantId)
                ->where('branch_id', $branchId)
                ->first();

            if (!$balance) {
                $balance = PettyCashBalance::create([
                    'restaurant_id' => $restaurantId,
                    'branch_id' => $branchId,
                    'current_balance' => 0,
                    'daily_limit' => 5000,
                    'transaction_limit' => 1000,
                    'is_active' => true,
                ]);
            }

            $transaction = $balance->deposit(
                $validated['amount'],
                $request->user(),
                $validated['description'],
                $validated['notes'] ?? null
            );

            DB::commit();

            return response()->json([
                'message' => 'Deposit recorded successfully',
                'transaction' => $transaction->load(['user']),
                'new_balance' => $balance->fresh(),
            ], 201);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'message' => 'Failed to record deposit',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function withdraw(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'description' => 'required|string|max:255',
            'expense_id' => 'nullable|exists:expenses,id',
            'notes' => 'nullable|string|max:1000',
        ]);

        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        try {
            DB::beginTransaction();

            $balance = PettyCashBalance::where('restaurant_id', $restaurantId)
                ->where('branch_id', $branchId)
                ->first();

            if (!$balance) {
                return response()->json(['message' => 'Petty cash not initialized'], 422);
            }

            // No balance or limit checks - allow any withdrawal amount
            $expense = null;
            if (isset($validated['expense_id']) && $validated['expense_id']) {
                $expense = Expense::find($validated['expense_id']);
                if ($expense && $expense->restaurant_id !== $restaurantId) {
                    return response()->json(['message' => 'Expense not found'], 404);
                }
            }

            $transaction = $balance->withdraw(
                $validated['amount'],
                $request->user(),
                $validated['description'],
                $expense,
                $validated['notes'] ?? null
            );

            // If linked to an expense, update the expense
            if ($expense) {
                $expense->update([
                    'is_petty_cash' => true,
                    'petty_cash_balance_before' => $transaction->balance_before,
                    'petty_cash_balance_after' => $transaction->balance_after,
                    'status' => 'paid',
                    'paid_at' => now(),
                ]);
            }

            DB::commit();

            return response()->json([
                'message' => 'Withdrawal recorded successfully',
                'transaction' => $transaction->load(['user', 'expense']),
                'new_balance' => $balance->fresh(),
            ], 201);

        } catch (\Exception $e) {
            DB::rollBack();
            
            // Log the error for debugging
            \Log::error('Petty cash withdrawal failed', [
                'user_id' => $request->user()->id,
                'amount' => $validated['amount'],
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'message' => 'Failed to record withdrawal',
                'error' => $e->getMessage(),
                'debug_info' => [
                    'user_id' => $request->user()->id,
                    'restaurant_id' => $request->user()->restaurant_id,
                    'branch_id' => $request->user()->branch_id,
                    'amount' => $validated['amount']
                ]
            ], 500);
        }
    }

    public function adjust(Request $request): JsonResponse
    {
        // Only admin can make adjustments
        if ($request->user()->role !== 'admin') {
            return response()->json(['message' => 'Only administrators can make balance adjustments'], 403);
        }

        $validated = $request->validate([
            'new_balance' => 'required|numeric|min:0',
            'description' => 'required|string|max:255',
            'notes' => 'nullable|string|max:1000',
        ]);

        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        try {
            DB::beginTransaction();

            $balance = PettyCashBalance::where('restaurant_id', $restaurantId)
                ->where('branch_id', $branchId)
                ->first();

            if (!$balance) {
                $balance = PettyCashBalance::create([
                    'restaurant_id' => $restaurantId,
                    'branch_id' => $branchId,
                    'current_balance' => 0,
                    'daily_limit' => 5000,
                    'transaction_limit' => 1000,
                    'is_active' => true,
                ]);
            }

            $transaction = $balance->adjust(
                $validated['new_balance'],
                $request->user(),
                $validated['description'],
                $validated['notes'] ?? null
            );

            DB::commit();

            return response()->json([
                'message' => 'Balance adjustment recorded successfully',
                'transaction' => $transaction->load(['user']),
                'new_balance' => $balance->fresh(),
            ], 201);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'message' => 'Failed to record adjustment',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function updateSettings(Request $request): JsonResponse
    {
        // Only admin and manager can update settings
        if (!in_array($request->user()->role, ['admin', 'manager'])) {
            return response()->json(['message' => 'Insufficient permissions'], 403);
        }

        $validated = $request->validate([
            'daily_limit' => 'required|numeric|min:0',
            'transaction_limit' => 'required|numeric|min:0',
            'is_active' => 'boolean',
        ]);

        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        try {
            $balance = PettyCashBalance::where('restaurant_id', $restaurantId)
                ->where('branch_id', $branchId)
                ->first();

            if (!$balance) {
                $balance = PettyCashBalance::create([
                    'restaurant_id' => $restaurantId,
                    'branch_id' => $branchId,
                    'current_balance' => 0,
                    'daily_limit' => $validated['daily_limit'],
                    'transaction_limit' => $validated['transaction_limit'],
                    'is_active' => $validated['is_active'] ?? true,
                ]);
            } else {
                $balance->update($validated);
            }

            return response()->json([
                'message' => 'Petty cash settings updated successfully',
                'balance' => $balance,
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'message' => 'Failed to update settings',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function getSummary(Request $request): JsonResponse
    {
        $branchId = $request->user()->branch_id;
        $restaurantId = $request->user()->restaurant_id;

        $startDate = $request->get('start_date', Carbon::now()->startOfMonth());
        $endDate = $request->get('end_date', Carbon::now()->endOfMonth());

        $balance = PettyCashBalance::where('restaurant_id', $restaurantId)
            ->where('branch_id', $branchId)
            ->first();

        if (!$balance) {
            return response()->json([
                'message' => 'Petty cash not initialized',
                'summary' => null
            ]);
        }

        $transactionsQuery = PettyCashTransaction::where('restaurant_id', $restaurantId)
            ->where('branch_id', $branchId)
            ->whereBetween('created_at', [$startDate, $endDate]);

        $summary = [
            'current_balance' => $balance->current_balance,
            'formatted_current_balance' => $balance->formatted_balance,
            'daily_limit' => $balance->daily_limit,
            'transaction_limit' => $balance->transaction_limit,
            'is_active' => $balance->is_active,
            'status' => $balance->status_label,
            'status_color' => $balance->status_color,
            
            // Period statistics
            'period' => [
                'start_date' => $startDate,
                'end_date' => $endDate,
                'total_deposits' => $transactionsQuery->clone()->where('type', 'deposit')->sum('amount'),
                'total_withdrawals' => $transactionsQuery->clone()->where('type', 'withdrawal')->sum('amount'),
                'total_adjustments' => $transactionsQuery->clone()->where('type', 'adjustment')->sum('amount'),
                'transaction_count' => $transactionsQuery->clone()->count(),
                'deposit_count' => $transactionsQuery->clone()->where('type', 'deposit')->count(),
                'withdrawal_count' => $transactionsQuery->clone()->where('type', 'withdrawal')->count(),
                'adjustment_count' => $transactionsQuery->clone()->where('type', 'adjustment')->count(),
            ],
            
            // Today's statistics
            'today' => [
                'withdrawals' => $balance->getTodayWithdrawals(),
                'remaining_daily_limit' => max(0, $balance->daily_limit - $balance->getTodayWithdrawals()),
                'deposits' => PettyCashTransaction::where('restaurant_id', $restaurantId)
                    ->where('branch_id', $branchId)
                    ->where('type', 'deposit')
                    ->whereDate('created_at', today())
                    ->sum('amount'),
                'transaction_count' => PettyCashTransaction::where('restaurant_id', $restaurantId)
                    ->where('branch_id', $branchId)
                    ->whereDate('created_at', today())
                    ->count(),
            ]
        ];

        // Add formatted values
        $summary['period']['formatted_total_deposits'] = 'KES ' . number_format($summary['period']['total_deposits'], 2);
        $summary['period']['formatted_total_withdrawals'] = 'KES ' . number_format($summary['period']['total_withdrawals'], 2);
        $summary['period']['formatted_total_adjustments'] = 'KES ' . number_format($summary['period']['total_adjustments'], 2);
        
        $summary['today']['formatted_withdrawals'] = 'KES ' . number_format($summary['today']['withdrawals'], 2);
        $summary['today']['formatted_remaining_daily_limit'] = 'KES ' . number_format($summary['today']['remaining_daily_limit'], 2);
        $summary['today']['formatted_deposits'] = 'KES ' . number_format($summary['today']['deposits'], 2);

        return response()->json($summary);
    }
}