<?php

namespace App\Http\Controllers;

use App\Models\JointAccount;
use App\Models\JointAccountTransaction;
use App\Models\JointAccountApproval;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class JointAccountTransactionController extends Controller
{
    public function index($jointAccountId): JsonResponse
    {
        try {
            $user = Auth::user();
            $jointAccount = JointAccount::find($jointAccountId);

            if (!$jointAccount || !$jointAccount->isMember($user)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Access denied'
                ], 403);
            }

            $transactions = JointAccountTransaction::where('joint_account_id', $jointAccountId)
                ->with(['initiator', 'approvals.approver'])
                ->latest()
                ->paginate(20);

            return response()->json([
                'status' => 'success',
                'transactions' => $transactions
            ]);

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

    public function store(Request $request, $jointAccountId): JsonResponse
    {
        try {
            $user = Auth::user();
            $jointAccount = JointAccount::find($jointAccountId);

            if (!$jointAccount || !$jointAccount->isMember($user)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Access denied'
                ], 403);
            }

            $validator = Validator::make($request->all(), [
                'transaction_type' => 'required|in:deposit,withdrawal,investment,transfer',
                'amount' => 'required|numeric|min:0.01',
                'description' => 'nullable|string|max:500',
                'metadata' => 'nullable|array'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Validation failed',
                    'errors' => $validator->errors()
                ], 422);
            }

            // Check for withdrawal or transfer - ensure sufficient balance
            if (($request->transaction_type === 'withdrawal' || $request->transaction_type === 'transfer') && $request->amount > $jointAccount->balance) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Insufficient balance'
                ], 400);
            }

            DB::beginTransaction();

            $transaction = JointAccountTransaction::create([
                'joint_account_id' => $jointAccountId,
                'initiated_by' => $user->id,
                'transaction_type' => $request->transaction_type,
                'amount' => $request->amount,
                'description' => $request->description,
                'metadata' => $request->metadata ?? []
            ]);

            // For withdrawal and transfer transactions, ALWAYS require member approval
            if ($request->transaction_type === 'withdrawal' || $request->transaction_type === 'transfer') {
                // Set status to pending for member approval
                $transaction->update(['status' => 'pending']);
            } else {
                // For non-withdrawal/transfer transactions, check if approval is required
                if (!$jointAccount->requiresApproval($request->amount)) {
                    // Auto-approve small amounts for non-withdrawal/transfer transactions
                    $this->processTransaction($transaction);
                }
            }

            DB::commit();

            $transaction->load(['initiator', 'approvals.approver']);

            return response()->json([
                'status' => 'success',
                'message' => 'Transaction initiated successfully',
                'transaction' => $transaction
            ], 201);

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

    public function approve(Request $request, $transactionId): JsonResponse
    {
        try {
            $user = Auth::user();
            $transaction = JointAccountTransaction::with(['jointAccount', 'approvals'])
                ->find($transactionId);

            if (!$transaction) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Transaction not found'
                ], 404);
            }

            if (!$transaction->canUserApprove($user)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'You cannot approve this transaction'
                ], 403);
            }

            $validator = Validator::make($request->all(), [
                'action' => 'required|in:approved,rejected',
                'comment' => 'nullable|string|max:500'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Validation failed',
                    'errors' => $validator->errors()
                ], 422);
            }

            DB::beginTransaction();

            // Create approval record
            JointAccountApproval::create([
                'joint_account_transaction_id' => $transactionId,
                'approver_id' => $user->id,
                'action' => $request->action,
                'comment' => $request->comment,
                'action_at' => now()
            ]);

            $transaction->refresh();

            if ($request->action === 'approved') {
                if ($transaction->isFullyApproved()) {
                    // All members have approved - change status to 'processing' for admin review
                    $transaction->update([
                        'status' => 'processing',
                        'approval_data' => array_merge($transaction->approval_data ?? [], [
                            'member_consensus_reached_at' => now(),
                            'member_approvals' => $transaction->approvals()->where('action', 'approved')->with('approver')->get()
                        ])
                    ]);
                }
            } elseif ($request->action === 'rejected') {
                $transaction->reject();
            }

            DB::commit();

            return response()->json([
                'status' => 'success',
                'message' => 'Transaction ' . $request->action . ' successfully',
                'transaction' => $transaction->fresh(['initiator', 'approvals.approver'])
            ]);

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

    public function show($transactionId): JsonResponse
    {
        try {
            $user = Auth::user();
            $transaction = JointAccountTransaction::with([
                'jointAccount.members',
                'initiator',
                'approvals.approver'
            ])->find($transactionId);

            if (!$transaction) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Transaction not found'
                ], 404);
            }

            if (!$transaction->jointAccount->isMember($user)) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Access denied'
                ], 403);
            }

            return response()->json([
                'status' => 'success',
                'transaction' => $transaction
            ]);

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

    public function pendingApprovals(): JsonResponse
    {
        try {
            $user = Auth::user();

            // Get transactions pending approval from joint accounts where user can approve
            $transactions = JointAccountTransaction::whereHas('jointAccount', function($query) use ($user) {
                $query->whereHas('members', function($memberQuery) use ($user) {
                    $memberQuery->where('user_id', $user->id)
                        ->where('status', 'active');
                });
            })
            ->where('status', 'pending')
            ->whereDoesntHave('approvals', function($query) use ($user) {
                $query->where('approver_id', $user->id);
            })
            ->with(['jointAccount', 'initiator', 'approvals.approver'])
            ->latest()
            ->get();

            return response()->json([
                'status' => 'success',
                'pending_transactions' => $transactions
            ]);

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

    public function adminPendingWithdrawals(): JsonResponse
    {
        try {
            $user = Auth::user();
            
            if (!$user->isAdmin()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Access denied. Admin privileges required.'
                ], 403);
            }

            // Get all withdrawal and transfer transactions that are ready for admin approval (status: processing)
            $pendingTransactions = JointAccountTransaction::whereIn('transaction_type', ['withdrawal', 'transfer'])
                ->where('status', 'processing')
                ->with(['jointAccount.members.user', 'initiator', 'approvals.approver'])
                ->latest()
                ->get();

            return response()->json([
                'status' => 'success',
                'transactions' => $pendingTransactions
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch pending withdrawals and transfers',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function adminApproveWithdrawal(Request $request, $transactionId): JsonResponse
    {
        try {
            $user = Auth::user();

            // Check if user is admin
            if (!$user->isAdmin()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Access denied. Admin privileges required.'
                ], 403);
            }

            $validator = Validator::make($request->all(), [
                'action' => 'required|in:approved,rejected',
                'admin_notes' => 'nullable|string|max:500'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Validation failed',
                    'errors' => $validator->errors()
                ], 422);
            }

            $transaction = JointAccountTransaction::with(['jointAccount', 'approvals'])
                ->where('id', $transactionId)
                ->whereIn('transaction_type', ['withdrawal', 'transfer'])
                ->where('status', 'processing')
                ->first();

            if (!$transaction) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Transaction not found or not ready for admin approval'
                ], 404);
            }

            DB::beginTransaction();

            if ($request->action === 'approved') {
                // Admin gives final approval - process the transaction
                $this->processTransaction($transaction);
                
                // Add admin approval record
                JointAccountApproval::create([
                    'joint_account_transaction_id' => $transactionId,
                    'approver_id' => $user->id,
                    'action' => 'approved',
                    'comment' => $request->admin_notes ?: 'Admin final approval',
                    'action_at' => now()
                ]);

            } else {
                // Reject the transaction
                $transaction->update([
                    'status' => 'rejected',
                    'approval_data' => array_merge($transaction->approval_data ?? [], [
                        'admin_rejected_by' => $user->id,
                        'admin_rejected_at' => now(),
                        'admin_notes' => $request->admin_notes
                    ])
                ]);

                // Add admin rejection record
                JointAccountApproval::create([
                    'joint_account_transaction_id' => $transactionId,
                    'approver_id' => $user->id,
                    'action' => 'rejected',
                    'comment' => $request->admin_notes ?: 'Admin rejected ' . $transaction->transaction_type,
                    'action_at' => now()
                ]);
            }

            DB::commit();

            return response()->json([
                'status' => 'success',
                'message' => ucfirst($transaction->transaction_type) . ' ' . $request->action . ' successfully',
                'transaction' => $transaction->fresh(['jointAccount', 'initiator', 'approvals.approver'])
            ]);

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

    private function processTransaction(JointAccountTransaction $transaction): void
    {
        $jointAccount = $transaction->jointAccount;

        switch ($transaction->transaction_type) {
            case 'deposit':
                $jointAccount->increment('balance', $transaction->amount);
                break;
            case 'withdrawal':
                $jointAccount->decrement('balance', $transaction->amount);
                break;
            case 'investment':
                $jointAccount->decrement('balance', $transaction->amount);
                break;
            case 'transfer':
                // Transfer from joint account to personal account
                // Decrement joint account balance
                $jointAccount->decrement('balance', $transaction->amount);
                // The transfer amount will be added to user's personal balance via the User model's balance calculation
                break;
        }

        $transaction->complete();
    }
} 