<?php

namespace App\Http\Controllers;

use App\Models\DocumentLibrary;
use App\Models\TenderEntry;
use App\Models\WorkAllocationBook;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class WorkAllocationBookController extends Controller
{

public function index(Request $request)
{
    try {

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

        $query = WorkAllocationBook::query()
            ->with([
                'subledger',
                'tender',
                'department',
                'ledger',
            ])
            ->orderBy('WA_Id', 'desc');

        if ($search !== '') {

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

                $q->where('WA_RefId', 'like', "%{$search}%")
                ->orWhere('WO_Amount', 'like', "%{$search}%")
                ->orWhereDate('WO_Date', '=', $search)

                ->orWhereHas('subledger', function ($sub) use ($search) {
                    $sub->where('SL_Name', 'like', "%{$search}%")
                        ->orWhere('SL_Code', 'like', "%{$search}%");
                })

                ->orWhereHas('tender', function ($tender) use ($search) {
                    $tender->where('Proposal_Amount', 'like', "%{$search}%")
                        ->orWhere('Approved_Amount', 'like', "%{$search}%")
                        ->orWhereDate('Tnd_Date', '=', $search)
                        ->orWhere('Description', 'like', "%{$search}%");
                })

                ->orWhereHas('department', function ($dept) use ($search) {
                    $dept->where('Dpt_Name', 'like', "%{$search}%");
                })

                ->orWhereHas('ledger', function ($ledger) use ($search) {
                    $ledger->where('Lg_Name', 'like', "%{$search}%");
                });

            });

        }

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

        return response()->json([
            'success' => true,
            'data'    => $allocations->items(),
            'meta'    => [
                'current_page' => $allocations->currentPage(),
                'last_page'    => $allocations->lastPage(),
                'per_page'     => $allocations->perPage(),
                'total'        => $allocations->total(),
                'search_used'  => $search ?: null,
            ]
        ]);

    } catch (\Exception $e) {

        return response()->json([
            'success' => false,
            'message' => 'Something went wrong. Please try again later.'
        ], 500);
    }
}


public function show($id)
{
    try {

        $allocation = WorkAllocationBook::with([
            'subledger',
            'tender',
            'department',
            'ledger'
        ])->findOrFail($id);

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

    } catch (\Exception $e) {

        return response()->json([
            'success' => false,
            'message' => 'Something went wrong. Please try again later.'
        ], 500);
    }
}




public function store(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'WA_RefId'      => 'nullable|string|max:25',
            'SL_Id'         => 'nullable|exists:subledg_master,SL_Id',
            'TE_Id'         => 'required|exists:tender_entry,TE_Id',
            'WO_Amount'     => 'required|numeric|min:0',
            'WO_Date'       => 'nullable|date',
            'Fnc_Id'        => 'required|exists:function_types,Fnc_Id',
              'Is_Active' => 'nullable|boolean',

            // ✅ NORMAL FILE
            'WA_Documents'   => 'nullable|array',
            'WA_Documents.*' => 'file|max:20480',
            'Dpt_id' => 'nullable|exists:dept_master,Dpt_id',
            'Lg_Id'  => 'nullable|exists:ledger_master,Lg_Id',
            'Description' => 'nullable|string',
        ]);


        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors'  => $validator->errors()
            ], 422);
        }


        DB::beginTransaction();


        try {


            /*
            ===============================
            CHECK REMAINING AMOUNT
            ===============================
            */


            $tender = TenderEntry::findOrFail($request->TE_Id);
            $approvedAmount = (float) $tender->Approved_Amount;


            $allocatedTotal = WorkAllocationBook::where('TE_Id', $request->TE_Id)
                ->sum('WO_Amount');


            $remainingAmount = $approvedAmount - $allocatedTotal;


            // if ($request->WO_Amount > $remainingAmount) {
            //     return response()->json([
            //         'success' => false,
            //         'message' => 'Allocation amount exceeds remaining approved amount',
            //         'remaining_amount' => $remainingAmount
            //     ], 400);
            // }


            /*
            ===============================
            CREATE RECORD
            ===============================
            */


            $allocation = WorkAllocationBook::create([
                'WA_RefId'  => $request->WA_RefId,
                'SL_Id'     => $request->SL_Id,
                'TE_Id'     => $request->TE_Id,
                'WO_Amount' => $request->WO_Amount,
                'WO_Date'   => $request->WO_Date,
                'Dpt_id'      => $request->Dpt_id,
                'Lg_Id'       => $request->Lg_Id,
                'Description' => $request->Description,
                   'Is_Active' => $request->Is_Active ?? 1


            ]);


            /*
            ===============================
            SAVE DOCUMENTS (NORMAL FILE)
            ===============================
            */


            $folderName = 'work_allocation_documents';
            $folderPath = public_path($folderName);


            if (!File::exists($folderPath)) {
                File::makeDirectory($folderPath, 0755, true);
            }


            $newDocs = [];


            if ($request->hasFile('WA_Documents')) {


                foreach ($request->file('WA_Documents') as $index => $file) {


                    $extension = $file->getClientOriginalExtension();
                    $fileName  = Str::uuid() . '.' . $extension;


                    $file->move($folderPath, $fileName);


                    $fullUrl = url($folderName . '/' . $fileName);


                    $docRecord = DocumentLibrary::create([
                        'Fnc_Id'      => $request->Fnc_Id,
                        'Rec_Id'      => $allocation->WA_Id,
                        'Description' => 'Document_' . ($index + 1),
                        'Doc_Upload'  => $fullUrl,
                        'Serial_No'   => $index + 1,
                    ]);


                    $newDocs[] = [
                        'doc_lib_id' => $docRecord->Doc_Lib,
                        'name'       => 'Document_' . ($index + 1),
                        'url'        => $fullUrl,
                        'type'       => $extension,
                    ];
                }


                $allocation->update([
                    'WA_Documents' => $newDocs
                ]);
            }


            DB::commit();


            return response()->json([
                'success' => true,
                'message' => 'Work allocation created successfully',
                'remaining_amount' => $remainingAmount - $request->WO_Amount,
                'data' => $allocation->fresh()
            ], 201);


        } catch (\Exception $e) {


            DB::rollBack();


            return response()->json([
                'success' => false,
                'message' => 'Something went wrong. Please try again later.'
            ], 500);
        }
    }



public function update(Request $request, $id)
{
    $validator = Validator::make($request->all(), [
        'WA_RefId'      => 'sometimes|nullable|string|max:25',
        'SL_Id'         => 'sometimes|nullable|exists:subledg_master,SL_Id',
        'TE_Id'         => 'sometimes|nullable|exists:tender_entry,TE_Id',
        'WO_Amount'     => 'sometimes|nullable|numeric|min:0',
        'WO_Date'       => 'sometimes|nullable|date',
  'Is_Active' => 'sometimes|boolean',
        'Fnc_Id'        => 'sometimes|nullable|exists:function_types,Fnc_Id',

        'WA_Documents'   => 'nullable|array',
        'WA_Documents.*' => 'nullable|string',

        'WA_Documents_description' => 'nullable|array',
        'WA_Documents_description.*' => 'nullable|string',

        'Dpt_id' => 'sometimes|nullable|exists:dept_master,Dpt_id',
        'Lg_Id'  => 'sometimes|nullable|exists:ledger_master,Lg_Id',
        'Description' => 'sometimes|nullable|string',

    ]);

    if ($validator->fails()) {
        return response()->json([
            'success' => false,
            'errors'  => $validator->errors()
        ], 422);
    }

    DB::beginTransaction();

    try {

        $allocation = WorkAllocationBook::findOrFail($id);

        // ✅ NORMAL UPDATE
        $allocation->update([
            'WA_RefId'  => $request->WA_RefId ?? $allocation->WA_RefId,
            'SL_Id'     => $request->SL_Id ?? $allocation->SL_Id,
            'TE_Id'     => $request->TE_Id ?? $allocation->TE_Id,
            'WO_Amount' => $request->WO_Amount ?? $allocation->WO_Amount,
            'WO_Date'   => $request->WO_Date ?? $allocation->WO_Date,
            'Dpt_id'    => $request->Dpt_id ?? $allocation->Dpt_id,
            'Lg_Id'     => $request->Lg_Id ?? $allocation->Lg_Id,
            'Description'=> $request->Description ?? $allocation->Description,
                'Is_Active' => $request->has('Is_Active')
                    ? $request->Is_Active
                    : $allocation->Is_Active,
        ]);

        /*
        ===============================
        DOCUMENT MERGE LOGIC (LIKE TENDER)
        ===============================
        */

        // ✅ OLD DOCS
        $existingDocs = $allocation->WA_Documents ?? [];

        $newDocs = [];

        // ✅ Fnc_Id handling
        $existingFncId = DocumentLibrary::where('Rec_Id', $allocation->WA_Id)
                            ->value('Fnc_Id');

        $finalFncId = $request->Fnc_Id ?? $existingFncId ?? null;

        /*
        ===============================
        SAVE NEW BASE64 FILES
        ===============================
        */

        if (!empty($request->WA_Documents)) {

            $folderName = 'work_allocation_documents';
            $folderPath = public_path($folderName);

            if (!File::exists($folderPath)) {
                File::makeDirectory($folderPath, 0755, true, true);
            }

            foreach ($request->WA_Documents as $index => $base64File) {

                if (!$base64File) continue;

                if (strpos($base64File, 'base64,') !== false) {

                    [$meta, $content] = explode(',', $base64File);

                    preg_match('/data:(.*?);base64/', $meta, $matches);
                    $extension = isset($matches[1])
                        ? explode('/', $matches[1])[1]
                        : 'png';

                    $fileName = Str::uuid() . '.' . $extension;

                    file_put_contents(
                        $folderPath . '/' . $fileName,
                        base64_decode($content)
                    );

                    $fullUrl = url($folderName . '/' . $fileName);

                    // ✅ DESCRIPTION
                    $docDescription = $request->WA_Documents_description[$index] ?? null;

                    // ✅ SERIAL NUMBER CONTINUE FROM OLD
                    $serialNo = count($existingDocs) + count($newDocs) + 1;

                    $docRecord = DocumentLibrary::create([
                        'Fnc_Id'      => $finalFncId,
                        'Rec_Id'      => $allocation->WA_Id,
                        'Description' => $docDescription,
                        'Doc_Upload'  => $fullUrl,
                        'Serial_No'   => $serialNo
                    ]);

                    $newDocs[] = [
                        'doc_lib_id' => $docRecord->Doc_Lib,
                        'name'       => 'Document_' . $serialNo,
                        'description'=> $docDescription,
                        'url'        => $fullUrl,
                        'type'       => $extension
                    ];
                }
            }
        }

        /*
        ===============================
        MERGE OLD + NEW
        ===============================
        */

        if (!empty($newDocs)) {

            $finalDocs = array_merge($existingDocs, $newDocs);

            $allocation->update([
                'WA_Documents' => $finalDocs
            ]);
        }

        DB::commit();

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

    } catch (\Exception $e) {

        DB::rollBack();

        return response()->json([
            'success' => false,
            'message' => 'Something went wrong. Please try again later.'
        ], 500);
    }
}


public function destroy($id)
{
    try {

        $allocation = WorkAllocationBook::findOrFail($id);
        $allocation->delete();

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

    } catch (\Exception $e) {

        return response()->json([
            'success'=>false,
            'message'=>'Something went wrong. Please try again later.'
        ],500);
    }
}


public function getAll(Request $request)
{
    try {

        $query = WorkAllocationBook::with([
            'subledger',
            'tender',
            'department',
            'ledger'
        ])->orderBy('WA_Id','desc');

        if ($request->filled('Dpt_Id')) {
            $query->whereHas('tender',function($q)use($request){
                $q->where('Dpt_Id',$request->Dpt_Id);
            });
        }

        if ($request->filled('Lg_Id')) {
            $query->whereHas('tender',function($q)use($request){
                $q->where('Lg_Id',$request->Lg_Id);
            });
        }

        if ($request->filled('SL_Id')) {
            $query->where('SL_Id',$request->SL_Id);
        }

        if ($request->filled('TE_Id')) {
            $query->where('TE_Id',$request->TE_Id);
        }

        $allocations = $query->get();

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

    } catch (\Exception $e) {

        return response()->json([
            'success'=>false,
            'message'=>'Something went wrong. Please try again later.'
        ],500);
    }
}


public function getBySubledger($id)
{
    $allocations = WorkAllocationBook::with([
            'subledger',
            'tender',
              'department',
            'ledger'
        ])
        ->where('SL_Id', $id)
        ->orderBy('WA_Id', 'desc')
        ->get();

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

public function getSubledgerWiseTenders()
{
    try {

        $allocations = WorkAllocationBook::with([
                'subledger',
                'tender',
                'department',
        'ledger',
            ])
            ->get()
            ->groupBy('SL_Id');   // Group by Subledger

        $formattedData = $allocations->map(function ($items, $subledgerId) {

            $subledger = $items->first()->subledger;

            return [

                'SL_Id' => $subledgerId,

                'subledger_details' => $subledger ? [
                    'SL_Code' => $subledger->SL_Code,
                    'SL_Name' => $subledger->SL_Name,
                ] : null,

                'total_tenders' => $items->pluck('TE_Id')->unique()->count(),

                'tenders' => $items->pluck('tender')
                    ->unique('TE_Id')
                    ->map(function ($tender) {

                        return [

                            'TE_Id' => $tender->TE_Id,
                            'Proposal_Amount' => $tender->Proposal_Amount,
                            'Approved_Amount' => $tender->Approved_Amount,
                            'Tnd_Date'        => $tender->Tnd_Date,
                            'Description'     => $tender->Description,

                            'formatted_proposal_amount' =>
                                number_format($tender->Proposal_Amount ?? 0, 2),

                            'formatted_approved_amount' =>
                                number_format($tender->Approved_Amount ?? 0, 2),
                        ];

                    })->values()

            ];

        })->values();

        return response()->json([
            'success' => true,
            'message' => 'Subledger wise tenders fetched successfully',
            'total_unique_subledgers' => $formattedData->count(),
            'data' => $formattedData
        ]);

    } catch (\Exception $e) {

        return response()->json([
            'success' => false,
            'message' => 'Failed to fetch data',
            'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
        ], 500);
    }
}

public function deleteDocument($doc_id)
{
    DB::beginTransaction();

    try {

        // 1. Find document
        $doc = DocumentLibrary::find($doc_id);

        if (!$doc) {
            return response()->json([
                'success' => false,
                'message' => 'Document not found'
            ], 404);
        }

        // 2. Get Work Allocation record
        $allocation = WorkAllocationBook::find($doc->Rec_Id);

        // 3. Delete file from folder
        if ($doc->Doc_Upload) {

            $relativePath = parse_url($doc->Doc_Upload, PHP_URL_PATH);
            $filePath = public_path($relativePath);

            if (File::exists($filePath)) {
                File::delete($filePath);
            }
        }

        // 4. Delete from DocumentLibrary
        $doc->delete();

        // 5. Update WA_Documents JSON
        if ($allocation && is_array($allocation->WA_Documents)) {

            $updatedDocs = collect($allocation->WA_Documents)
                ->filter(function ($item) use ($doc_id) {
                    return $item['doc_lib_id'] != $doc_id;
                })
                ->values()
                ->toArray();

            $allocation->update([
                'WA_Documents' => $updatedDocs
            ]);
        }

        DB::commit();

        return response()->json([
            'success' => true,
            'message' => 'Work allocation document deleted successfully'
        ]);

    } catch (\Exception $e) {

        DB::rollBack();

        return response()->json([
            'success' => false,
            'message' => 'Something went wrong. Please try again later.'
        ], 500);
    }
}
}
