<?php

namespace App\Http\Controllers\Accounting;

use App\Classes\EditLogHistory;
use Carbon\Carbon;
use App\Models\Income;
use App\Models\IncomeHead;
use App\Models\Banking;
use App\Models\BankTransfar;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\File;
use App\Services\FundTransferService;
use Illuminate\Support\Facades\Storage;
use Brian2694\Toastr\Facades\Toastr;


class IncomeController extends Controller
{

    public function __construct()
    {
        $this->middleware('permission:income-section|income-entry|income-head|income-report|other-income', ['only' => ['index', 'show']]);
        $this->middleware('permission:income-entry', ['only' => ['create', 'store']]);
        $this->middleware('permission:income-entry', ['only' => ['edit', 'update']]);
    }

    public function index()
    {
        $data = [
            'incomes' => Income::with('bankAccount')->orderBy('id', 'desc')->paginate(1000),
        ];
        // $incomes = Income::all();
        //dd($data);
        return view('accounts.income.index', $data);
    }


    public function create()
    {
        $incomeHead = IncomeHead::all();
        $bankAccounts = Banking::where('status', 1)->get();
        return view('accounts.income.create', compact('incomeHead', 'bankAccounts'));
    }


    public function store(Request $request)
    {
        $request->validate([
            'attach_document' => 'mimes:jpeg,jpg,png,webp,gif,pdf|max:10240',
            //       'teacher_id' => 'required|unique:subjects,name,' . $complain->id,
            // 'phone' => 'required|regex:/^([0-9\s\-\+\(\)]*)$/|digits:11|unique:complains,phone,' . $request->id,
        ]);


        DB::beginTransaction();
        try {


            $income = new Income();
            $income->name = $request->name;
            $income->incomeHead = $request->incomeHead;
            $income->invoice_number = $request->invoice_number ?? 'nan';
            $income->date = $request->date;
            $income->amount = $request->amount;
            $income->description = $request->description;
            $income->bank_account_id = $request->bank_account_id ?? null;



            if ($request->attach_document != null) {
                // for s3 upload
                if (checkSettings('store_image_to_s3') === 'enable') {
                    $fileName = time() . '.' . $request->attach_document->extension();
                    $path = 'attachDocument/' . $fileName;

                    // Store to S3
                    $request->attach_document->storeAs('attachDocument', $fileName, 's3');

                    // Optionally make public (if needed)
                    Storage::disk('s3')->setVisibility($path, 'public');

                    // ✅ Save full URL or path
                    $income->attach_document = Storage::disk('s3')->url($path); // or just $path
                } else {
                    $fileName = time() . '.' . $request->attach_document->extension();
                    $request->attach_document->move(storage_path('app/public/attachDocument'), $fileName);
                    $income->attach_document = $fileName;
                }
            }

            $income->save();

            // Check if bank account is selected
            if ($request->filled('bank_account_id')) {
                // Deposit to bank account
                $bankDeposit = new BankTransfar();
                $bankDeposit->account_id = $request->bank_account_id;
                $bankDeposit->diposit_amount = $request->amount;
                $bankDeposit->description = 'Income: ' . $request->name . ' - ' . $request->description;
                $bankDeposit->by = auth()->user()->name ?? 'System';
                $bankDeposit->save();
            }
            // Add to cash (existing behavior)
            $note = 'Fund Added For: ' . $request->name . ' : ' . $request->description;
            (new FundTransferService)->addFundToCash($request->amount, $note, $income->id, 'income');

            DB::commit();
            return redirect()->route('income.index')->with('success_message', 'Income Added');

            //code...
        } catch (\Throwable $th) {
            //throw $th;
            DB::rollback();
        }

        // dd($request->all());

    }


    public function show(Income $income)
    {
        //
    }


    public function edit($id)
    {
        $income = Income::find($id);

        $data = [
            'model' => $income,
            'incomeHead' => IncomeHead::all(),
            'bankAccounts' => Banking::where('status', 1)->get(),
            'title' => 'Income'
        ];
        return view('accounts.income.edit', $data);
    }


    public function update(Request $request)
    {
        DB::beginTransaction();
        try {
            $type = 'Income';
            $old_info = Income::where('id', $request->id)->first();

            $income = Income::find($request->id);

            $income->name = $request->name;
            $income->incomeHead = $request->incomeHead;
            $income->invoice_number = $request->invoice_number ?? 'nan';
            $income->date = $request->date;
            $income->amount = $request->amount;
            $income->description = $request->description;
            $income->bank_account_id = $request->bank_account_id ?? null;

            if ($request->attach_document != null) {
                // for s3 upload
                if (checkSettings('store_image_to_s3') === 'enable') {
                    if ($income->attach_document != null) {
                        // Extract the path after the domain
                        $parsedUrl = parse_url($income->attach_document);
                        $oldPath = ltrim($parsedUrl['path'], '/'); // remove leading slash

                        // Delete the old file from S3
                        Storage::disk('s3')->delete($oldPath);
                    }

                    $fileName = time() . '.' . $request->attach_document->extension();
                    $path = 'attachDocument/' . $fileName;

                    // Store the new file to S3
                    $request->attach_document->storeAs('attachDocument', $fileName, 's3');

                    // Make it public (optional)
                    Storage::disk('s3')->setVisibility($path, 'public');

                    // Save the new file URL
                    $income->attach_document = Storage::disk('s3')->url($path);
                } else {
                    File::delete(public_path('storage/attachDocument/' . $income->attach_document));
                    $fileName = time() . '.' . $request->attach_document->extension();
                    $request->attach_document->move(storage_path('app/public/attachDocument'), $fileName);
                    $income->attach_document = $fileName;
                }
            }

            $income->update();

            // Handle bank deposit update
            // Find existing bank deposit for this income using multiple strategies
            $existingBankDeposit = BankTransfar::where('description', 'like', '%Income:%')
                ->where(function($query) use ($old_info, $request, $income) {
                    // Strategy 1: Match by old income name
                    $query->where('description', 'like', '%Income: ' . $old_info->name . '%')
                    // Strategy 2: Match by new income name (in case name changed)
                          ->orWhere('description', 'like', '%Income: ' . $request->name . '%')
                    // Strategy 3: Match by creation time (within 5 minutes of income creation)
                          ->orWhere(function($q) use ($income) {
                              $incomeCreatedAt = $income->created_at;
                              $q->whereBetween('created_at', [
                                  $incomeCreatedAt->copy()->subMinutes(5),
                                  $incomeCreatedAt->copy()->addMinutes(5)
                              ]);
                          });
                })
                ->whereNotNull('diposit_amount')
                ->orderBy('created_at', 'desc')
                ->first();

            // Check if bank account is selected
            if ($request->filled('bank_account_id')) {
                if ($existingBankDeposit) {
                    // Update existing bank deposit
                    $existingBankDeposit->account_id = $request->bank_account_id;
                    $existingBankDeposit->diposit_amount = $request->amount;
                    $existingBankDeposit->description = 'Income: ' . $request->name . ' - ' . $request->description;
                    $existingBankDeposit->by = auth()->user()->name ?? 'System';
                    $existingBankDeposit->save();
                } else {
                    // Create new bank deposit
                    $bankDeposit = new BankTransfar();
                    $bankDeposit->account_id = $request->bank_account_id;
                    $bankDeposit->diposit_amount = $request->amount;
                    $bankDeposit->description = 'Income: ' . $request->name . ' - ' . $request->description;
                    $bankDeposit->by = auth()->user()->name ?? 'System';
                    $bankDeposit->save();
                }
            }
            // else {
            //     // If bank account is not selected, find and delete existing deposits
            //     $depositsToDelete = BankTransfar::where('description', 'like', '%Income:%')
            //         ->where(function($query) use ($old_info, $request, $income) {
            //             $query->where('description', 'like', '%Income: ' . $old_info->name . '%')
            //                   ->orWhere('description', 'like', '%Income: ' . $request->name . '%')
            //                   ->orWhere(function($q) use ($income) {
            //                       $incomeCreatedAt = $income->created_at;
            //                       $q->whereBetween('created_at', [
            //                           $incomeCreatedAt->copy()->subMinutes(5),
            //                           $incomeCreatedAt->copy()->addMinutes(5)
            //                       ]);
            //                   });
            //         })
            //         ->whereNotNull('diposit_amount')
            //         ->get();

            //     foreach ($depositsToDelete as $deposit) {
            //         $deposit->delete();
            //     }
            // }

            $note = 'Fund Added For: ' . $request->name . ' : ' . $request->description;
            (new FundTransferService)->modifyAddFundToCash($request->amount, $note, $income->id, 'income');

            $new_info = Income::find($income->id);
            (new EditLogHistory)->editLogSave($income, $type, $old_info, $new_info);

            DB::commit();
            Toastr::success('Income Updated Successfully', 'Success', ['success' => 'alert alert-success']);
            return redirect()->back();
        } catch (\Throwable $th) {
            //throw $th;
        }
    }


    public function destroy(Income $income)
    {
        $income->delete();
        return redirect()->route('income.index');
    }

    public function incomeReport()
    {
        //dd('hello');
        $start = Carbon::now()->today()->firstOfMonth();
        $end = today();
        $heads = IncomeHead::all();
        return view('accounts.incomeReport.index', [
            'start' => $start,
            'end'   => $end,
            'heads' => $heads
        ]);
    }

    public function incomeSearchResult(Request $request)
    {

        $start = Carbon::parse($request->from_date)->format('Y-m-d 00:00:00');
        $end = Carbon::parse($request->to_date)->format('Y-m-d 23:59:59');

        // $incomes = Income::whereBetween('date', [$start, $end])->orderBy('id','DESC')->get();
        if ($request->incomeHead == 'all') {
            $incomes = Income::whereBetween('date', [$start, $end])->orderBy('id', 'DESC')->get();
        } else {
            $incomes = Income::whereBetween('date', [$start, $end])->where('incomeHead', $request->incomeHead)->orderBy('id', 'DESC')->get();
        }

        $data = [
            'incomes' => $incomes,

        ];
        return view('accounts.incomeReport.result', $data);
    }
}
