<?php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Api\ApiController;
use App\Models\FeeTransaction;
use App\Models\FeePayment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;

class FeeTransactionController extends ApiController
{
    /**
     * Display a listing of fee transactions with pagination and search
     */
    public function index(Request $request)
    {
        $perPage = $request->get('per_page', 15);
        $search = $request->get('search');
        $sortBy = $request->get('sort_by', 'payment_date');
        $sortOrder = $request->get('sort_order', 'desc');

        $query = FeePayment::with(['student', 'feeStructure', 'collectedBy']);

        // Apply search
        if ($search) {
            $query->whereHas('student', function($q) use ($search) {
                $q->where('first_name', 'like', "%{$search}%")
                  ->orWhere('last_name', 'like', "%{$search}%")
                  ->orWhere('admission_number', 'like', "%{$search}%");
            })->orWhere('receipt_number', 'like', "%{$search}%");
        }

        // Apply filters
        if ($request->has('student_id') && $request->student_id) {
            $query->where('student_id', $request->student_id);
        }

        if ($request->has('class_id') && $request->class_id) {
            $query->whereHas('student', function($q) use ($request) {
                $q->where('class_id', $request->class_id);
            });
        }

        if ($request->has('payment_status') && $request->payment_status) {
            $query->where('payment_status', $request->payment_status);
        }

        if ($request->has('payment_method') && $request->payment_method) {
            $query->where('payment_method', $request->payment_method);
        }

        if ($request->has('start_date') && $request->start_date) {
            $query->where('payment_date', '>=', $request->start_date);
        }

        if ($request->has('end_date') && $request->end_date) {
            $query->where('payment_date', '<=', $request->end_date);
        }

        // Apply sorting
        $query = $this->applySorting($query, $sortBy, $sortOrder);

        return $this->paginatedResponse($query, $perPage);
    }

    /**
     * Store a newly created fee transaction
     */
    public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'student_id' => 'required|exists:students,id',
            'fee_structure_id' => 'required|exists:fee_structures,id',
            'amount_due' => 'required|numeric|min:0',
            'amount_paid' => 'required|numeric|min:0',
            'discount_amount' => 'nullable|numeric|min:0',
            'fine_amount' => 'nullable|numeric|min:0',
            'payment_date' => 'required|date',
            'payment_method' => 'required|in:cash,cheque,online,card,upi,bank_transfer',
            'payment_status' => 'required|in:paid,partial,pending,overdue',
            'transaction_id' => 'nullable|string',
            'receipt_number' => 'required|string|unique:fee_payments,receipt_number',
            'remarks' => 'nullable|string',
            'cheque_number' => 'nullable|string',
            'cheque_date' => 'nullable|date',
            'bank_name' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return $this->errorResponse('Validation failed', 422, $validator->errors());
        }

        DB::beginTransaction();
        try {
            $data = $request->all();
            $data['collected_by'] = auth('admin')->id();

            // Calculate total amount
            $totalAmount = $request->amount_paid + ($request->discount_amount ?? 0) - ($request->fine_amount ?? 0);
            $data['total_amount'] = $totalAmount;

            // Calculate balance
            $data['balance_amount'] = $request->amount_due - $request->amount_paid;

            $feePayment = FeePayment::create($data);

            DB::commit();

            return $this->successResponse(
                $feePayment->load(['student', 'feeStructure', 'collectedBy']),
                'Fee transaction created successfully',
                201
            );
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Failed to create transaction: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Display the specified fee transaction
     */
    public function show($id)
    {
        $feePayment = FeePayment::with([
            'student.class',
            'student.section',
            'feeStructure.feeType',
            'collectedBy'
        ])->find($id);

        if (!$feePayment) {
            return $this->errorResponse('Fee transaction not found', 404);
        }

        return $this->successResponse($feePayment);
    }

    /**
     * Update the specified fee transaction
     */
    public function update(Request $request, $id)
    {
        $feePayment = FeePayment::find($id);

        if (!$feePayment) {
            return $this->errorResponse('Fee transaction not found', 404);
        }

        $validator = Validator::make($request->all(), [
            'student_id' => 'sometimes|exists:students,id',
            'fee_structure_id' => 'sometimes|exists:fee_structures,id',
            'amount_due' => 'sometimes|numeric|min:0',
            'amount_paid' => 'sometimes|numeric|min:0',
            'discount_amount' => 'nullable|numeric|min:0',
            'fine_amount' => 'nullable|numeric|min:0',
            'payment_date' => 'sometimes|date',
            'payment_method' => 'sometimes|in:cash,cheque,online,card,upi,bank_transfer',
            'payment_status' => 'sometimes|in:paid,partial,pending,overdue',
            'receipt_number' => 'sometimes|string|unique:fee_payments,receipt_number,' . $id,
            'remarks' => 'nullable|string',
        ]);

        if ($validator->fails()) {
            return $this->errorResponse('Validation failed', 422, $validator->errors());
        }

        DB::beginTransaction();
        try {
            $data = $request->all();

            // Recalculate if amounts are changed
            if ($request->has('amount_paid') || $request->has('discount_amount') || $request->has('fine_amount')) {
                $amountPaid = $request->amount_paid ?? $feePayment->amount_paid;
                $discountAmount = $request->discount_amount ?? $feePayment->discount_amount ?? 0;
                $fineAmount = $request->fine_amount ?? $feePayment->fine_amount ?? 0;

                $data['total_amount'] = $amountPaid + $discountAmount - $fineAmount;

                $amountDue = $request->amount_due ?? $feePayment->amount_due;
                $data['balance_amount'] = $amountDue - $amountPaid;
            }

            $feePayment->update($data);

            DB::commit();

            return $this->successResponse(
                $feePayment->load(['student', 'feeStructure', 'collectedBy']),
                'Fee transaction updated successfully'
            );
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Failed to update transaction: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Remove the specified fee transaction
     */
    public function destroy($id)
    {
        $feePayment = FeePayment::find($id);

        if (!$feePayment) {
            return $this->errorResponse('Fee transaction not found', 404);
        }

        DB::beginTransaction();
        try {
            $feePayment->delete();
            DB::commit();

            return $this->successResponse(null, 'Fee transaction deleted successfully');
        } catch (\Exception $e) {
            DB::rollBack();
            return $this->errorResponse('Failed to delete transaction: ' . $e->getMessage(), 500);
        }
    }

    /**
     * Get student's fee payment history
     */
    public function studentHistory(Request $request, $studentId)
    {
        $perPage = $request->get('per_page', 15);

        $query = FeePayment::with(['feeStructure.feeType', 'collectedBy'])
            ->where('student_id', $studentId)
            ->orderBy('payment_date', 'desc');

        if ($request->has('start_date') && $request->start_date) {
            $query->where('payment_date', '>=', $request->start_date);
        }

        if ($request->has('end_date') && $request->end_date) {
            $query->where('payment_date', '<=', $request->end_date);
        }

        $summary = [
            'total_paid' => (clone $query)->sum('amount_paid'),
            'total_due' => (clone $query)->sum('amount_due'),
            'total_balance' => (clone $query)->sum('balance_amount'),
            'total_discount' => (clone $query)->sum('discount_amount'),
            'total_fine' => (clone $query)->sum('fine_amount'),
        ];

        $data = $query->paginate($perPage);

        return response()->json([
            'success' => true,
            'data' => $data->items(),
            'summary' => $summary,
            'pagination' => [
                'total' => $data->total(),
                'per_page' => $data->perPage(),
                'current_page' => $data->currentPage(),
                'last_page' => $data->lastPage(),
            ],
        ]);
    }

    /**
     * Generate receipt for fee payment
     */
    public function generateReceipt($id)
    {
        $feePayment = FeePayment::with([
            'student.class',
            'student.section',
            'feeStructure.feeType',
            'collectedBy'
        ])->find($id);

        if (!$feePayment) {
            return $this->errorResponse('Fee transaction not found', 404);
        }

        // Here you can implement PDF generation or return receipt data
        return $this->successResponse([
            'receipt' => $feePayment,
            'school_details' => $feePayment->student->school ?? null,
        ], 'Receipt generated successfully');
    }
}
