<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\EmployeeMaster;
use App\Models\EmpLangMaster;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class EmployeeMasterController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        try {
            $perPage = $request->get('per_page', 10);
            $search  = $request->get('search');

            $query = EmployeeMaster::with([
                'employeeCategory',
                'quota',
                'employeeType',
                'user'
            ]);

            if ($search) {
                $query->where(function ($q) use ($search) {
                    $q->where('Emp_Code', 'like', "%$search%")
                        ->orWhere('First_Name', 'like', "%$search%")
                        ->orWhere('Last_Name', 'like', "%$search%");
                });
            }

            $employees = $query->orderByDesc('Emp_Id')->paginate($perPage);

            $employees->getCollection()->transform(function ($emp) {
                $emp->languages = EmpLangMaster::whereIn('ELg_Id', $emp->ELg_Id ?? [])->get();
                $emp->emp_category_name = optional($emp->employeeCategory)->ECt_Name;
                $emp->emp_type_name = optional($emp->employeeType)->ETy_Name;

                
                $emp->departments = $emp->department_list;

                return $emp;
            });

            return response()->json([
                'status' => true,
                'message' => 'Employee list fetched',
                'data' => $employees
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Error fetching employees',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function store(Request $request): JsonResponse
    {
        try {
            $validator = Validator::make($request->all(), [
                'First_Name' => 'required|string|max:50',
                'Email_Id' => 'nullable|email|max:100',
                'Phone' => 'nullable|string|max:15',
                'Ect_Id' => 'nullable|exists:emp_cat_master,ECt_Id',
                'ETy_Id' => 'nullable|exists:emp_type_master,ETy_Id',
                'Dpt_Id' => 'nullable|array',       
                'Dpt_Id.*' => 'exists:dept_master,Dpt_id'
            ]);

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

            $employee = EmployeeMaster::create([
                'Emp_Code' => $request->Emp_Code,
                'First_Name' => $request->First_Name,
                'Last_Name' => $request->Last_Name,
                'Dpt_Id' => $request->Dpt_Id,        
                'Qut_Id' => $request->Qut_Id,
                'Ect_Id' => $request->Ect_Id,
                'ETy_Id' => $request->ETy_Id,
                'Usr_Id' => $request->Usr_Id,
                'ELg_Id' => $request->ELg_Id,
                'Phone' => $request->Phone,
                'Email_Id' => $request->Email_Id,
                'Alt_Phone' => $request->Alt_Phone,
                'F_M' => $request->F_M,
                'Emp_Add1' => $request->Emp_Add1,
                'Emp_Add2' => $request->Emp_Add2,
                'Emp_Add3' => $request->Emp_Add3,
                'Birth_Date' => $request->Birth_Date,
                'Bank_AcNo' => $request->Bank_AcNo,
                'Bank_Name' => $request->Bank_Name,
                'Bank_Br_Name' => $request->Bank_Br_Name,
                'BkAc_Type' => $request->BkAc_Type,
                'Gpf_AcNo_Pref' => $request->Gpf_AcNo_Pref,
                'Gpf_AcNo' => $request->Gpf_AcNo,
                'Cpf_AcNo' => $request->Cpf_AcNo,
                'Inc_TxNo' => $request->Inc_TxNo,
                'UID_AdharNo' => $request->UID_AdharNo,
                'Is_Active' => $request->Is_Active ?? 1,
            ]);

            return $this->show($employee->Emp_Id);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Create failed',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function show($id): JsonResponse
    {
        try {
            $employee = EmployeeMaster::with([
                'employeeCategory',
                'quota',
                'employeeType',
                'user'
            ])->findOrFail($id);

            $employee->languages = EmpLangMaster::whereIn('ELg_Id', $employee->ELg_Id ?? [])->get();

            
            $employee->departments = $employee->department_list;

            return response()->json([
                'status' => true,
                'data' => $employee
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Employee not found',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 404);
        }
    }

    public function update(Request $request, $id): JsonResponse
    {
        try {
            $employee = EmployeeMaster::findOrFail($id);

            $validator = Validator::make($request->all(), [
                'First_Name' => 'sometimes|string|max:50',
                'Email_Id' => 'nullable|email|max:100',
                'Phone' => 'nullable|string|max:15',
                'Emp_Code' => 'sometimes|string|max:20|unique:employee_master,Emp_Code,' . $id . ',Emp_Id',
                'Ect_Id' => 'nullable|exists:emp_cat_master,ECt_Id',
                'ETy_Id' => 'nullable|exists:emp_type_master,ETy_Id',
                'Dpt_Id' => 'nullable|array',        
                'Dpt_Id.*' => 'exists:dept_master,Dpt_id'
            ]);

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

            $data = $request->only([
                'Emp_Code',
                'First_Name',
                'Last_Name',
                'Dpt_Id',
                'Qut_Id',
                'Ect_Id',
                'ETy_Id',
                'Usr_Id',
                'ELg_Id',
                'Phone',
                'Email_Id',
                'Alt_Phone',
                'F_M',
                'Emp_Add1',
                'Emp_Add2',
                'Emp_Add3',
                'Birth_Date',
                'Bank_AcNo',
                'Bank_Name',
                'Bank_Br_Name',
                'BkAc_Type',
                'Gpf_AcNo_Pref',
                'Gpf_AcNo',
                'Cpf_AcNo',
                'Inc_TxNo',
                'UID_AdharNo',
                'Is_Active'
            ]);

            $employee->update($data);

            return $this->show($employee->Emp_Id);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Update failed',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function edit($id): JsonResponse
    {
        try {
            $employee = EmployeeMaster::with([
                'employeeCategory',
                'quota',
                'employeeType',
                'user'
            ])->findOrFail($id);

            $editData = [
                'employee' => $employee,
                'languages' => EmpLangMaster::whereIn('ELg_Id', $employee->ELg_Id ?? [])->get(),
                'departments' => $employee->department_list, 
                'edit_mode' => true
            ];

            return response()->json([
                'status' => true,
                'message' => 'Employee data ready for editing',
                'data' => $editData
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Employee not found for editing',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 404);
        }
    }

    public function destroy($id): JsonResponse
    {
        try {
            $employee = EmployeeMaster::findOrFail($id);
            $employee->delete();

            return response()->json([
                'status' => true,
                'message' => 'Employee deleted successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Delete failed',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function all(): JsonResponse
    {
        try {
            $employees = EmployeeMaster::with([
                'employeeCategory',
                'quota',
                'employeeType',
                'user'
            ])->orderByDesc('Emp_Id')->get();

            $employees->transform(function ($emp) {
                $emp->languages = EmpLangMaster::whereIn('ELg_Id', $emp->ELg_Id ?? [])->get();
                $emp->departments = $emp->department_list; 
                return $emp;
            });

            return response()->json([
                'status' => true,
                'data' => $employees
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Fetch failed',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function profile(Request $request)
    {
        try {
            $user = $request->user();

            if (!$user) {
                return response()->json([
                    'status' => false,
                    'message' => 'Unauthorized'
                ], 401);
            }

            $employee = EmployeeMaster::where('Usr_Id', $user->Usr_Id)
                ->with([
                    'employeeCategory',
                    'quota',
                    'employeeType',
                    'user',
                    'personalProfile.designation'
                ])
                ->first();

            if (!$employee) {
                return response()->json([
                    'status' => false,
                    'message' => 'Employee profile not found'
                ], 404);
            }

            $employee->languages = $employee->languagesData();
            $employee->departments = $employee->department_list;  

            return response()->json([
                'status' => true,
                'data' => $employee
            ], 200);

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

    public function updateProfile(Request $request)
    {
        try {
            $user = $request->user();

            if (!$user) {
                return response()->json([
                    'status' => false,
                    'message' => 'Unauthorized'
                ], 401);
            }

            $employee = EmployeeMaster::where('Usr_Id', $user->Usr_Id)->first();

            if (!$employee) {
                return response()->json([
                    'status' => false,
                    'message' => 'Employee profile not found'
                ], 404);
            }

            $validated = $request->validate([
                'First_Name' => 'nullable|string|max:50',
                'Last_Name'  => 'nullable|string|max:50',
                'Phone'      => 'nullable|max:15',
                'Email_Id'   => 'nullable|email|max:100',
                'Alt_Phone'  => 'nullable|max:15',
                'Emp_Add1'   => 'nullable|string|max:255',
                'Emp_Add2'   => 'nullable|string|max:255',
                'Emp_Add3'   => 'nullable|string|max:255',
                'Birth_Date' => 'nullable|date',
                'Bank_AcNo'  => 'nullable|string|max:50',
                'Bank_Name'  => 'nullable|string|max:100',
                'Bank_Br_Name' => 'nullable|string|max:100',
                'BkAc_Type'  => 'nullable|string|max:20',
                'UID_AdharNo' => 'nullable|max:20'
            ]);

            $employee->update($validated);

            return response()->json([
                'status' => true,
                'message' => 'Employee profile updated successfully',
                'data' => $employee
            ], 200);

        } catch (\Exception $e) {
            return response()->json([
                'status' => false,
                'message' => 'Profile update failed',
                'error' => env('Development_Mode') == 'Prod' 
        ? 'Something went wrong. Please try again later.' 
        : $e->getMessage()
            ], 500);
        }
    }

    public function getEmployeesByDepartment($deptId)
    {
        try {
            $employees = EmployeeMaster::whereJsonContains('Dpt_Id', (string)$deptId)
                ->with(['employeeCategory', 'employeeType', 'user'])
                ->get();

            $employees->transform(function ($emp) {
                $emp->departments = $emp->department_list;
                return $emp;
            });

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

    public function getAllEmployeeData(Request $request)
    {
        try {
            $pBillNo = $request->get('p_bill_no', 1);

            $employees = DB::table('employee_master as em')
                ->join('emppers_profile as ep', 'ep.Emp_Id', '=', 'em.Emp_Id')
                ->join('dept_master as dm', 'dm.Dpt_id', '=', 'ep.Dpt_id')
                ->join('designation_master as dsm', 'dsm.Dsg_id', '=', 'ep.Dsg_Id')
                ->join('emp_grade_master as egm', 'egm.EGM_Id', '=', 'ep.EGM_Id')
                ->join('pay_band_master as pbm', 'pbm.PB_Id', '=', 'egm.PB_ID')
                ->join('darate_master as drm', function($join) {
                    $join->on('drm.PC_Id', '=', 'pbm.PC_Id')
                         ->whereDate('drm.Fr_Date', '<=', now())
                         ->whereDate('drm.To_Date', '>=', now());
                })
                ->join('city_hracla as hrcl', function($join) {
                    $join->on('hrcl.CGR_Id', '=', 'ep.CityCode')
                         ->whereColumn('ep.Basic', '>=', 'hrcl.Basic_From')
                         ->whereColumn('ep.Basic', '<=', 'hrcl.Basic_To');
                })
                ->where('ep.PBillNo', $pBillNo)
                ->select(
                    'em.Emp_Code',
                    'em.First_Name',
                    'dm.Dpt_Name',
                    'dsm.Dsg_Title',
                    'ep.Basic as Basic_Pay',
                    'egm.EGM_Name',
                    'egm.PB_ID',
                    'pbm.PB_Code',
                    'drm.Da_Rate',
                    DB::raw('(ep.Basic * drm.Da_Rate / 100 * ep.DA) as daamount'),
                    'hrcl.HRA_1',
                    DB::raw("CASE
                        WHEN ep.Basic BETWEEN hrcl.Basic_From AND hrcl.Basic_To
                        THEN (ep.Basic * hrcl.HRA_1 / 100) * ep.HRA
                        ELSE 0
                    END as HRA"),
                    'hrcl.HRA_7th as CLA',
                    'em.*',
                    'ep.*',
                    'dm.*'
                )
                ->orderBy('ep.Emp_Id')
                ->get();

            return response()->json([
                'success' => true,
                'data' => $employees,
                'message' => 'Employee data retrieved successfully',
                'total_records' => $employees->count()
            ], 200);

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

    public function getEmployeeById($id)
    {
        try {
            $employee = DB::table('employee_master as em')
                ->join('emppers_profile as ep', 'ep.Emp_Id', '=', 'em.Emp_Id')
                ->join('dept_master as dm', 'dm.Dpt_id', '=', 'ep.Dpt_id')
                ->join('designation_master as dsm', 'dsm.Dsg_id', '=', 'ep.Dsg_Id')
                ->join('emp_grade_master as egm', 'egm.EGM_Id', '=', 'ep.EGM_Id')
                ->join('pay_band_master as pbm', 'pbm.PB_Id', '=', 'egm.PB_ID')
                ->join('darate_master as drm', function($join) {
                    $join->on('drm.PC_Id', '=', 'pbm.PC_Id')
                         ->whereDate('drm.Fr_Date', '<=', now())
                         ->whereDate('drm.To_Date', '>=', now());
                })
                ->join('city_hracla as hrcl', function($join) {
                    $join->on('hrcl.CGR_Id', '=', 'ep.CityCode')
                         ->whereColumn('ep.Basic', '>=', 'hrcl.Basic_From')
                         ->whereColumn('ep.Basic', '<=', 'hrcl.Basic_To');
                })
                ->where('em.Emp_Id', $id)
                ->select(
                    'em.Emp_Code',
                    'em.First_Name',
                    'dm.Dpt_Name',
                    'dsm.Dsg_Title',
                    'ep.Basic as Basic_Pay',
                    'egm.EGM_Name',
                    'egm.PB_ID',
                    'pbm.PB_Code',
                    'drm.Da_Rate',
                    DB::raw('(ep.Basic * drm.Da_Rate / 100 * ep.DA) as daamount'),
                    'hrcl.HRA_1',
                    DB::raw("CASE
                        WHEN ep.Basic BETWEEN hrcl.Basic_From AND hrcl.Basic_To
                        THEN (ep.Basic * hrcl.HRA_1 / 100) * ep.HRA
                        ELSE 0
                    END as HRA"),
                    'hrcl.HRA_7th as CLA',
                    'em.*',
                    'ep.*',
                    'dm.*'
                )
                ->first();

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

            return response()->json([
                'success' => true,
                'data' => $employee,
                'message' => 'Employee data retrieved successfully'
            ], 200);

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