<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Models\Cheque;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

class ChequeController extends Controller
{
public function index(Request $request)
{
    try {

        $perPage = $request->get('per_page', 15);
        $search  = $request->get('search');

        $query = Cheque::with([
            'organize',
            'bankAccount',
            'chequeBook',
            'chequeFormat',
             'ChlVoucher'
        ])

        ->when($request->Org_Id, fn($q, $v) =>
            $q->where('Org_Id', $v))

              ->when($request->CV_Id, fn($q, $v) =>
            $q->where('CV_Id', $v))

        ->when($request->bank_account_id, fn($q, $v) =>
            $q->where('bank_account_id', $v))

        ->when($request->cheque_book_id, fn($q, $v) =>
            $q->where('cheque_book_id', $v))

        ->when($request->cheque_format_id, fn($q, $v) =>
            $q->where('cheque_format_id', $v))

        // ->when($request->status, fn($q, $v) =>
        //     $q->where('status', $v))

        ->when($request->SL_Name, fn($q, $v) =>
            $q->where('SL_Name', 'LIKE', "%{$v}%"))

        ->when($request->cheque_number, fn($q, $v) =>
            $q->where('cheque_number', 'LIKE', "%{$v}%"))

             ->when($request->status, fn($q, $v) =>
            $q->where('status', 'LIKE', "%{$v}%"))

        ->when($request->amount, fn($q, $v) =>
            $q->where('amount', $v))

        ->when($request->date_from, fn($q, $v) =>
            $q->whereDate('cheque_date', '>=', $v))

        ->when($request->date_to, fn($q, $v) =>
            $q->whereDate('cheque_date', '<=', $v))

        ->when($search, function ($q) use ($search) {

            $q->where(function ($query) use ($search) {

                $query->where('SL_Name', 'LIKE', "%{$search}%")
                    ->orWhere('cheque_number', 'LIKE', "%{$search}%")
                    ->orWhere('amount', 'LIKE', "%{$search}%")
                    ->orWhere('remarks', 'LIKE', "%{$search}%")

                    ->orWhereHas('organize', function ($org) use ($search) {
                        $org->where('Org_Name', 'LIKE', "%{$search}%");
                    })

                    //       ->orWhereHas('ChlVoucher', function ($cv) use ($search) {
                    //     $cv->where('CV_Id', 'LIKE', "%{$search}%");
                    // })


                    ->orWhereHas('bankAccount', function ($account) use ($search) {
                        $account->where('account_name', 'LIKE', "%{$search}%")
                                ->orWhere('account_number', 'LIKE', "%{$search}%");
                    });
            });
        });

        $cheques = $query
            ->orderByDesc('cheque_id')
            ->paginate($perPage);

        // $cheques->getCollection()->transform(function ($item) {

        //     if ($item->statusAction) {
        //         $item->statusAction->setHidden([
        //             'authorities_details',
        //             'viewers_details'
        //         ]);
        //     }

        //     return $item;
        // });

        return response()->json([
            'success' => true,
            'data'    => $cheques
        ]);

    } catch (\Exception $e) {

        Log::error('Cheque index error: '.'Something went wrong. Please try again later.');
        //  Log::error('Cheque index error: ' . $e->getMessage());


        return response()->json([
            'success' => false,
            'message' => 'Something went wrong while fetching cheques.'
        ], 500);
    }
}

public function show($id)
{
    try {

        $cheque = Cheque::with([
            'organize',
            'bankAccount',
            'chequeBook',
            'chequeFormat',
            'ChlVoucher',
            'printQueueEntry'
        ])->findOrFail($id);

        if ($cheque->statusAction) {
            $cheque->statusAction->setHidden([
                'authorities_details',
                'viewers_details'
            ]);
        }

        return response()->json([
            'success' => true,
            'data' => $cheque
        ]);

    } catch (\Exception $e) {

        return response()->json([
            'success' => false,
            'message' => 'Something went wrong. Please try again later.',
            'line' => $e->getLine(),
            'file' => basename($e->getFile())
        ], 500);
    }
}

    public function getAll(Request $request)
{
    try {

        $search = $request->get('search');

        $cheques = Cheque::with([
            'organize',
            'bankAccount',
            'chequeBook',
            'chequeFormat',
            'ChlVoucher'
        ])

        ->when($request->Org_Id, fn($q, $v) =>
            $q->where('Org_Id', $v))

              ->when($request->CV_Id, fn($q, $v) =>
            $q->where('CV_Id', $v))

        ->when($request->bank_account_id, fn($q, $v) =>
            $q->where('bank_account_id', $v))

        ->when($request->cheque_book_id, fn($q, $v) =>
            $q->where('cheque_book_id', $v))

        ->when($request->cheque_format_id, fn($q, $v) =>
            $q->where('cheque_format_id', $v))

        ->when($request->status, fn($q, $v) =>
            $q->where('status', $v))

        ->when($request->SL_Name, fn($q, $v) =>
            $q->where('SL_Name', 'LIKE', "%{$v}%"))

        ->when($request->cheque_no, fn($q, $v) =>
            $q->where('cheque_no', 'LIKE', "%{$v}%"))

        ->when($request->amount, fn($q, $v) =>
            $q->where('amount', $v))

        ->when($request->date_from, fn($q, $v) =>
            $q->whereDate('cheque_date', '>=', $v))

        ->when($request->date_to, fn($q, $v) =>
            $q->whereDate('cheque_date', '<=', $v))

        ->when($search, function ($q) use ($search) {

            $q->where(function ($query) use ($search) {

                $query->where('SL_Name', 'LIKE', "%{$search}%")
                    ->orWhere('cheque_no', 'LIKE', "%{$search}%")
                    ->orWhere('amount', 'LIKE', "%{$search}%")
                    ->orWhere('remarks', 'LIKE', "%{$search}%")

                    ->orWhereHas('organize', function ($org) use ($search) {
                        $org->where('Org_Name', 'LIKE', "%{$search}%");
                    })

                           ->orWhereHas('ChlVoucher', function ($cv) use ($search) {
                        $cv->where('CV_Id', 'LIKE', "%{$search}%");
                    })

                    ->orWhereHas('bankAccount', function ($account) use ($search) {
                        $account->where('account_name', 'LIKE', "%{$search}%")
                                ->orWhere('account_number', 'LIKE', "%{$search}%");
                    });
            });
        })

        ->orderByDesc('cheque_id')
        ->get();

        

    } catch (\Exception $e) {

        Log::error('Cheque getAll error: '.'Something went wrong. Please try again later.');

        return response()->json([
            'success' => false,
            'message' => 'Something went wrong while fetching cheques.'
        ], 500);
    }
}

    public function store(Request $request)
    {
        try {
            $data = $request->validate([
                'Org_Id' => 'nullable|exists:org_master,Org_Id',
                'bank_account_id' => 'nullable|exists:bank_accounts,bank_account_id',
                'cheque_book_id' => 'nullable|exists:cheque_books,cheque_book_id',
                'cheque_format_id' => 'nullable|exists:cheque_formats,cheque_format_id',
                'CV_Id' => 'nullable|exists:chl_voucher,CV_Id|unique:cheques,CV_Id',
                'status' => 'nullable|string',
                'print_queues_id' => 'nullable|exists:print_queues,print_queues_id',

                'cheque_number' => 'required|string|max:20',
                'cheque_date' => 'required|date',
                'SL_Name' => 'required|string|max:300',
                'amount' => 'required|numeric|min:0',
                'amount_words' => 'nullable|string',
                'payment_type' => 'required|string|max:20',
                'pdc_clearing_date' => 'nullable|date',
                'narration' => 'nullable|string',
                'ref_doc_number' => 'nullable|string|max:100',
                'ref_doc_type' => 'nullable|string|max:50',
                'department' => 'nullable|string|max:100',
                'cost_centre' => 'nullable|string|max:100',
                'is_account_payee' => 'nullable|boolean',
                'is_not_negotiable' => 'nullable|boolean',
                'approval_level' => 'nullable|integer',
            ]);

            $cheque = Cheque::create($data);

            return response()->json([
                'success' => true,
                'message' => 'Cheque created successfully.',
                'data' => $cheque
            ], 201);

        } catch (ValidationException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $e->errors()
            ], 422);

        } catch (\Exception $e) {
            Log::error('Cheque store error: ' . 'Something went wrong. Please try again later.');

            return response()->json([
                'success' => false,
                'message' => 'Failed to create cheque.'
            ], 500);
        }
    }

    public function update(Request $request, $id)
    {
        try {
            $cheque = Cheque::findOrFail($id);

            $data = $request->validate([
                'Org_Id' => 'nullable|exists:org_master,Org_Id',
                'bank_account_id' => 'nullable|exists:bank_accounts,bank_account_id',
                'cheque_book_id' => 'nullable|exists:cheque_books,cheque_book_id',
                'cheque_format_id' => 'nullable|exists:cheque_formats,cheque_format_id',
                'CV_Id' => 'nullable|exists:chl_voucher,CV_Id|unique:cheques,CV_Id',
                'status' => 'nullable|string',
                'print_queues_id' => 'nullable|exists:print_queues,print_queues_id',

                'cheque_number' => 'sometimes|string|max:20',
                'cheque_date' => 'sometimes|date',
                'SL_Name' => 'sometimes|string|max:300',
                'amount' => 'sometimes|numeric|min:0',
                'amount_words' => 'nullable|string',
                'payment_type' => 'sometimes|string|max:20',
                'pdc_clearing_date' => 'nullable|date',
                'narration' => 'nullable|string',
                'ref_doc_number' => 'nullable|string|max:100',
                'ref_doc_type' => 'nullable|string|max:50',
                'department' => 'nullable|string|max:100',
                'cost_centre' => 'nullable|string|max:100',
                'is_account_payee' => 'nullable|boolean',
                'is_not_negotiable' => 'nullable|boolean',
                'approval_level' => 'nullable|integer',
            ]);

            $cheque->update($data);

            return response()->json([
                'success' => true,
                'message' => 'Cheque updated successfully.',
                'data' => $cheque->fresh()
            ]);

        } catch (ValidationException $e) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error',
                'errors' => $e->errors()
            ], 422);

        } catch (\Exception $e) {
            Log::error('Cheque update error: ' . 'Something went wrong. Please try again later.');

            return response()->json([
                'success' => false,
                'message' => 'Failed to update cheque.'
            ], 500);
        }
    }

    public function destroy($id)
    {
        try {
            $cheque = Cheque::findOrFail($id);
            $cheque->delete();

            return response()->json([
                'success' => true,
                'message' => 'Cheque deleted successfully.'
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to delete cheque.'
            ], 500);
        }
    }

    public function markCleared(Request $request, $id)
    {
        try {
            $request->validate([
                'cleared_date' => 'required|date'
            ]);

            $cheque = Cheque::findOrFail($id);

            $cheque->update([
                'cleared_date' => $request->cleared_date
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Cheque marked as cleared.',
                'data' => $cheque->fresh()
            ]);

        } catch (ValidationException $e) {
            return response()->json([
                'success' => false,
                'errors' => $e->errors()
            ], 422);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to mark cleared.'
            ], 500);
        }
    }

    public function markBounced(Request $request, $id)
    {
        try {
            $request->validate([
                'bounce_reason' => 'required|string'
            ]);

            $cheque = Cheque::findOrFail($id);

            $cheque->update([
                'bounce_date' => now()->toDateString(),
                'bounce_reason' => $request->bounce_reason
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Cheque marked as bounced.',
                'data' => $cheque->fresh()
            ]);

        } catch (ValidationException $e) {
            return response()->json([
                'success' => false,
                'errors' => $e->errors()
            ], 422);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to mark bounced.'
            ], 500);
        }
    }
}
