<?php

namespace App\Http\Controllers;

use App\Models\Admission;
use App\Models\Document;
use App\Models\Emergency_contact;
use App\Models\Fee_structure;
use App\Models\Guardian;
use App\Models\Student;
use App\Models\Student_assign_fee;
use App\Models\Student_classe;
use App\Models\Student_fee;
use App\Models\Student_fee_detail;
use App\Models\Transaction;
use App\Models\Transaction_detail;
use App\Models\School_setting;
use App\Models\School_session;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use Illuminate\Support\Facades\Storage;

class AdmissionController extends Controller
{
    public function show()
    {
        $classes        = DB::table('classes')->get();
        $sections       = DB::table('sections')->get();
        $school_session = School_session::where('status', 'active')
            ->latest()
            ->first();
        // Split session_year into start_year and end_year
        if ($school_session && $school_session->session_year) {
            $years = explode('-', $school_session->session_year);
            $start_year = $years[0] ?? '';
            $end_year = $years[1] ?? '';
        } else {
            $start_year = '';
            $end_year = '';
        }

        $fee_structures = Fee_structure::all();
        return view('stdAdmission.admForm', compact('classes', 'sections', 'fee_structures', 'start_year', 'end_year'));
    }

    public function store(Request $request)
    {
        $request->validate([
            // 'user_id' => 'required|integer|exists:users,id',
            'student_name'             => 'required|string|max:255',
            'father_name'              => 'required|string|max:255',
            'father_cnic'              => 'required|string|max:15',
            'gender'                   => 'required|string',
            'email'                    => 'required|email',
            'date_of_birth'            => 'required|date',
            'permanent_address'        => 'required|string|max:500',
            'guardian_name'            => 'required|string|max:255',
            'guardian_contact'         => 'required|string|max:15',
            'emergency_contact_name'   => 'required|string|max:255',
            'emergency_contact_number' => 'required|string|max:15',
            'relationship'             => 'required|string|max:255',
            'discount'                 => 'nullable',
            'net_amount'             => 'nullable',
            'class'                 => 'required|integer|exists:classes,id',
            'class_section'                 => 'required|integer|exists:sections,id',
            'fee_assign'                 => 'required|array|min:1'
        ]);


        $fee_structures = Fee_structure::where('class_id', $request->class)->get();
        if ($fee_structures->isEmpty()) {
            return redirect()->back()->with('error', 'Fee structure not defined for the selected class, please add Fee for this class. ');
        }

        // Begin transaction
        DB::beginTransaction();

        try {
            // Get the next available ID
            $nextId       = Student::max('id') + 1;
            $stdHeadCode = '20100' . $nextId;
            $schoolName = School_setting::where('setting_key', 'school_name')->value('setting_value');
            $schoolPrefix = strtoupper(implode('', array_map(fn($word) => $word[0], explode(' ', $schoolName))));
            $reg_no       = $schoolPrefix . str_pad($nextId, 2, '0', STR_PAD_LEFT); // e.g., "SCH0001"
            //get record on the entered cnic and check for the same student name if exists already
            $student = Student::where('father_cnic', $request->father_cnic)->where('student_name', $request->student_name)->first();
            if ($student) {
                return redirect()->back()->with('error', 'Student already exists with the same name and CNIC');
            }
            // Insert student data
            $student = Student::create([
                'user_id'           => $request->user_id,
                'reg_no'            => $reg_no,
                'head_code'         => $stdHeadCode,
                'student_name'      => $request->student_name,
                'father_name'       => $request->father_name,
                'father_cnic'       => $request->father_cnic,
                'email'             => $request->email,
                'religion'          => $request->religion,
                'mother_name'       => $request->mother_name,
                'gender'            => $request->gender,
                'place_of_birth'    => $request->place_of_birth,
                'date_of_birth'     => $request->date_of_birth,
                'permanent_address' => $request->permanent_address,
                'current_address'   => $request->current_address,
                'discount_type'     => 'poor',
                'status'            => 'active',
                'blood_group'       => $request->blood_group,
            ]);

            //
            $lastRoll = Admission::where('class_id', $request->class)
                ->where('section_id', $request->class_section)
                ->where('session_year', ($request->session_start . '-' . $request->session_end))
                ->max('roll_number');

            $newRoll = $lastRoll ? $lastRoll + 1 : 1;


            // Insert Admission data
            $admission = Admission::create([
                'student_id'       => $student->id, // Use the ID of the newly created student
                'head_code'         => $stdHeadCode,
                'reg_no'           => $reg_no,
                'admission_no'     => Date('Y') . $reg_no,
                'class_id'         => $request->class,                                         // Get from request
                'section_id'       => $request->class_section,
                'roll_number' => $newRoll,                                // Get from request
                'session_year'     => ($request->session_start . '-' . $request->session_end), // Ensure this field exists in the form
                'admission_date'   => date('Y-m-d') ?? now(),
                'status'           => 'active',
                'admission_status' => 'new',
            ]);

            // Insert student_classes entry
            Student_classe::create([
                'student_id'    => $student->id,
                'head_code'     => $stdHeadCode,
                'reg_no'        => $reg_no,                                     // Use the ID of the newly created student
                'class_id'      => $request->class,                                         // Get from request
                'section_id'    => $request->class_section,                                 // Get from request
                'academic_year' => ($request->session_start . '-' . $request->session_end), // Ensure this field exists in the form
            ]);

            // Insert Emergency Contact (if provided)
            if ($request->filled(['emergency_contact_name', 'emergency_contact_number', 'relationship'])) {
                Emergency_contact::create([
                    'student_id'     => $student->id,
                    'contact_name'   => $request->emergency_contact_name,
                    'contact_number' => $request->emergency_contact_number,
                    'relationship'   => $request->relationship,
                ]);
            }

            // Insert Documents (if uploaded)
            // if ($request->hasFile('student_photo') || $request->hasFile('birth_certificate') || $request->hasFile('leaving_certificate')) {
            //     $documentData = [
            //         'student_id'                 => $student->id,
            //         'photo'                      => $request->hasFile('student_photo') ? $request->file('student_photo')->store('student_documents', 'public') : null,
            //         'birth_certificate'          => $request->hasFile('birth_certificate') ? $request->file('birth_certificate')->store('student_documents', 'public') : null,
            //         'school_leaving_certificate' => $request->hasFile('leaving_certificate') ? $request->file('leaving_certificate')->store('student_documents', 'public') : null,
            //     ];

            //     Document::updateOrCreate(
            //         ['student_id' => $student->id], // Ensure a single entry per student
            //         $documentData
            //     );
            // }

            if ($request->hasFile('student_photo') || $request->hasFile('birth_certificate') || $request->hasFile('leaving_certificate')) {
                $documentData = [
                    'student_id'                 => $student->id,
                    'photo'                      => $request->hasFile('student_photo') ? $this->storeFile($request->file('student_photo'), 'student_photo') : null,
                    'birth_certificate'          => $request->hasFile('birth_certificate') ? $this->storeFile($request->file('birth_certificate'), 'birth_certificate') : null,
                    'school_leaving_certificate' => $request->hasFile('leaving_certificate') ? $this->storeFile($request->file('leaving_certificate'), 'leaving_certificate') : null,
                ];

                Document::updateOrCreate(
                    ['student_id' => $student->id], // Ensure a single entry per student
                    $documentData
                );
            }


            // Step 2: Determine payment status
            $status_paid = "UnPaid";
            $total_amount = $request->net_amount + $request->discount; // Calculate total amount including discount

            // Step 3: Insert into Student_fee table
            $student_fee = Student_fee::create([
                'student_id'   => $student->id,
                'head_code'    => $stdHeadCode,
                'reg_no'       => $reg_no,
                'class_id'     => $request->class,
                'section_id'   => $request->class_section,
                'description'  => 'Admission',
                'status'       => $status_paid,
                'discount'     => $request->discount,
                'total_amount' => $total_amount,
                'date'         => date('Y-m-d'),
            ]);

            // Step 4: Prepare fee detail data with proportional discount
            $feeData = [
                'student_id'    => $student->id,
                'head_code'     => $stdHeadCode,
                'reg_no'        => $reg_no,
                'class_id'      => $request->class,
                'std_fee_id'    => $student_fee->id,
                'academic_year' => $request->session_start . '-' . $request->session_end,
            ];

            $totalDiscount = $request->discount ?? 0;
            $totalFeeAmount = $total_amount; // already calculated above


            $fee_assign = $request->input('fee_assign', []); // array of selected fee IDs
            $fee_amounts = $request->input('fee_amount', []); // array: [fee_id => amount]

            foreach ($fee_assign as $feeId) {
                $amount = $fee_amounts[$feeId] ?? 0;

                $feeStructure = \App\Models\Fee_structure::find($feeId);
                $columnName = $feeStructure ? $feeStructure->fee_type : 'Unknown';

                // Calculate proportional discount
                $proportionalDiscount = $totalFeeAmount > 0
                    ? ($amount / $totalFeeAmount) * $totalDiscount
                    : 0;

                $finalAmount = $amount - $proportionalDiscount;

                // Round to 2 decimal places for accuracy
                $feeData[$columnName] = round($finalAmount, 2);
            }


            // Step 5: Insert into Student_fee_detail table
            Student_fee_detail::create($feeData);

            foreach ($fee_assign as $feeId) {
                $amount = $fee_amounts[$feeId] ?? 0;

                // Get the fee type name from the database
                $feeStructure = \App\Models\Fee_structure::find($feeId);
                $columnName = $feeStructure ? $feeStructure->fee_type : 'Unknown';

                $updateData = [
                    'academic_year' => ($request->session_start . '-' . $request->session_end),
                    $columnName => $amount,
                ];

                $updateData['admission_fee'] = null;
                $updateData['promotion_fee'] = null;

                // Perform update or create
                Student_assign_fee::updateOrCreate(
                    [
                        'student_id' => $student->id,
                        'head_code'  => $stdHeadCode,
                        'reg_no'     => $reg_no,
                        'class_id'   => $request->class,
                    ],
                    $updateData
                );
            }

            // Insert Guardian
            Guardian::create([
                'student_id'            => $student->id,
                'guardian_name'         => $request->guardian_name,
                'guardian_contact'      => $request->guardian_contact,
                'relation_with_student' => $request->guardian_relation,
            ]);


            //Insert Transaction Data
            $transaction = Transaction::create([
                'transaction_type' => 'admission',
                'trans_type_id' => $student_fee->id,
                'transaction_date' => date('Y-m-d'),
                'total_amount'     => ($total_amount - $request->discount),
                'remarks'          => 'Admission Fee',
            ]);

            //Debit balance on student through head code
            Transaction_detail::create([
                'transaction_id'   => $transaction->id,
                'coa_id'           => $stdHeadCode,
                'transaction_type' => 'admission',
                'credit'           => 0,
                'debit'            => ($total_amount - $request->discount), // total_amount payble
            ]);

            //Credit balance from income through head code is 20400
            Transaction_detail::create([
                'transaction_id'   => $transaction->id,
                'coa_id'           => '20400',
                'transaction_type' => 'admission',
                'credit'           => ($total_amount - $request->discount),
                'debit'            => 0,
            ]);

            // Do work for remaining rupees of all students. we manage
            // accounts for it is receivable
            // head code for receivable is 20600
            Transaction_detail::create([
                'transaction_id'   => $transaction->id,
                'coa_id'           => '20600',
                'transaction_type' => 'admission',
                'credit'           => 0,
                'debit'            => (($total_amount - $request->discount)),
            ]);

            //store QR code for student
            $qrCode = QrCode::size(200)->generate($student->id);
            $qrCodePath = 'student_qr_codes/' . $student->id . '.svg';
            Storage::disk('public')->put($qrCodePath, $qrCode);
            $student->qr_code = $qrCodePath;
            $student->save();
            // Store QR code in the public directory

            // Commit transaction
            DB::commit();

            return redirect()->back()->with('success', 'Student registered successfully!');
        } catch (\Exception $e) {
            DB::rollBack();

            Log::error('Student Registration Failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString(),
            ]);

            return redirect()->back()->with('error', 'Failed to register student: ' . $e->getMessage());
        }
    }

    /**
     * Helper function to handle file storage and naming.
     */
    private function storeFile($file, $filePrefix)
    {
        $fileName = time() . '_' . $filePrefix . '.' . $file->getClientOriginalExtension();
        return $file->storeAs('student_documents', $fileName, 'public');
    }


    // student admission letter
    public function letter()
    {
        $student = Student::with(['admission', 'previousEducation', 'guardian', 'emergencyContact', 'documents', 'studentFee', 'studentFeeDetail', 'studentAssignFee', 'transaction', 'transactionDetail'])
            ->get();
        return view('stdAdmission.letters', compact('student'));
    }
}
