<?php

namespace App\Http\Controllers\Manager;

use App\Http\Controllers\Controller;
use App\Models\EmployeeAttendance;
use Illuminate\Http\Request;
use App\Models\EmployeeDetails;
use App\Models\EmployeeSalaryDetail;
use Illuminate\Support\Facades\Storage;
use Yajra\DataTables\Facades\DataTables;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Illuminate\Support\Facades\DB;
use App\Models\EmployeeLeave;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use Illuminate\Support\Carbon;

class ManagerEmployeeController extends Controller
{

    public function employeeDetails()
    {
        $employees = EmployeeDetails::all();
        return view('manager.employee.employeedetails', compact('employees'));
    }

    public function employeeAttendance()
    {
        $employees = EmployeeDetails::all();
        $attendances = EmployeeAttendance::orderByDesc('id')->get();
        return view('manager.employee.employeeattendance', compact('employees', 'attendances'));
    }

    // Store
    public function storeEmployeeAttendance(Request $request)
    {
        $request->validate([
            'month_year' => 'required',
            'employee_id' => 'required',
            'employee_name' => 'required',
            // ...other validations
        ]);
        EmployeeAttendance::create($request->all());
        return back()->with('success', 'Attendance added.');
    }

    // Get for edit
    public function getEmployeeAttendance($id)
    {
        $attendance = EmployeeAttendance::findOrFail($id);
        return response()->json($attendance);
    }

    // Update
    public function updateEmployeeAttendance(Request $request, $id)
    {
        $attendance = EmployeeAttendance::findOrFail($id);
        $attendance->update($request->all());
        return back()->with('success', 'Attendance updated.');
    }

    // Delete
    public function destroyEmployeeAttendance($id)
    {
        EmployeeAttendance::destroy($id);
        return back()->with('success', 'Attendance deleted.');
    }

    public function getEmployeeAttendanceEmployee($employee_id)
    {
        // Assuming employee_id is something like "EMP1001"
        $employee = \App\Models\EmployeeDetails::where('employee_id', $employee_id)->first();
        if ($employee) {
            return response()->json([
                'name' => $employee->name,
                'gender' => $employee->gender,
                'dob' => $employee->dob,
                'doj' => $employee->doj,
                'department' => $employee->department,
                'designation' => $employee->designation,
            ]);
        }
        return response()->json([
            'name' => '',
            'gender' => '',
            'dob' => '',
            'doj' => '',
            'department' => '',
            'designation' => ''
        ]);
    }


    public function employeeDailyReport()
    {
        return view('manager.employee.employeedailyreport');
    }

    public function employeeCalendar()
    {
        $employees = EmployeeDetails::all();
        return view('manager.employee.employeecalendar', compact('employees'));
    }
    public function list()
    {
        $employees = \App\Models\EmployeeDetails::select('id', 'employee_id', 'name')->get();
        return response()->json($employees);
    }

    public function index()
    {
        $employees = EmployeeDetails::all();
        return view('manager.employee.index', compact('employees'));
    }
    public function store(Request $request)
    {
        try {
            Log::info('Storing employee data', $request->all());
            $validated = $request->validate([
                'employee_id' => 'required|unique:employees,employee_id',
                'name' => 'required',
                'gender' => 'required',
                'department' => 'nullable',
                'designation' => 'nullable',
                'dob' => 'nullable|date',
                'doj' => 'nullable|date',
                'mobile' => 'nullable|digits:10',
                'aadhar_number' => 'nullable|digits:12',
                'category' => 'nullable|in:E,M,O',
                'status' => 'nullable|in:ACTIVE,INACTIVE',
                'profile_picture' => 'nullable|image|max:2048',
            ]);

            if ($request->hasFile('profile_picture')) {
                $validated['profile_picture'] = $request->file('profile_picture')->store('employees', 'public');
            }

            EmployeeDetails::create($validated);

            return back()->with('success', 'Employee added successfully.');
        } catch (\Exception $e) {
            Log::error('Error storing employee: ' . $e->getMessage());
            return back()->with('error', 'Failed to add employee. Please check the logs.');
        }
    }

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

        $validated = $request->validate([
            'employee_id' => 'required|unique:employees,employee_id,' . $employee->id,
            'name' => 'required',
            'gender' => 'required',
            'department' => 'nullable',
            'designation' => 'nullable',
            'dob' => 'nullable|date',
            'doj' => 'nullable|date',
            'mobile' => 'nullable|digits:10',
            'aadhar_number' => 'nullable|digits:12',
            'category' => 'nullable|in:E,M,O',
            'status' => 'nullable|in:ACTIVE,INACTIVE',
            'profile_picture' => 'nullable|image|max:2048',
        ]);

        if ($request->hasFile('profile_picture')) {
            // Delete the old profile picture if it exists
            if ($employee->profile_picture && Storage::disk('public')->exists($employee->profile_picture)) {
                Storage::disk('public')->delete($employee->profile_picture);
            }
            // Store the new profile picture and update the path
            $validated['profile_picture'] = $request->file('profile_picture')->store('employees', 'public');
        } else {
            // Prevent profile_picture field from being set to null if no file was uploaded
            unset($validated['profile_picture']);
        }

        $employee->update($validated);

        return back()->with('success', 'Employee updated successfully.');
    }
    public function destroy($id)
    {
        $employee = EmployeeDetails::findOrFail($id);
        if ($employee->profile_picture) {
            Storage::disk('public')->delete($employee->profile_picture);
        }
        $employee->delete();
        return back()->with('success', 'Employee deleted successfully.');
    }

    public function show($id)
    {
        $employee = EmployeeDetails::find($id);
        if ($employee) {
            return response()->json($employee);
        } else {
            return response()->json(['error' => 'Employee not found'], 404);
        }
    }
    // List Salary Details
    public function salaryDetails()
    {
        $employees = EmployeeDetails::all();
        $salaryDetails = EmployeeSalaryDetail::with('employee')->orderByDesc('id')->get();
        return view('manager.employee.employeepayroll', compact('employees', 'salaryDetails'));
    }

    // Store Salary Detail
    public function storeSalaryDetail(Request $request)
    {
        $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'month_year' => 'required',
            // Add validation for other fields as needed
        ]);
        EmployeeSalaryDetail::create($request->all());
        return redirect()->back()->with('success', 'Salary details added successfully.');
    }

    // AJAX: Get Employee Name by ID
    public function getEmployeeById($id)
    {
        $employee = EmployeeDetails::find($id);
        if ($employee) {
            return response()->json(['name' => $employee->name]);
        }
        return response()->json(['name' => ''], 404);
    }
    // AJAX: Fetch single salary detail
    public function getSalaryDetail($id)
    {
        $salary = EmployeeSalaryDetail::findOrFail($id);
        $employee = $salary->employee;
        return response()->json([
            'month_year' => $salary->month_year,
            'employee_id' => $salary->employee_id,
            'employee_name' => $employee ? $employee->name : '',
            'basic_da' => $salary->basic_da,
            'hra' => $salary->hra,
            'conveyance' => $salary->conveyance,
            'washing_allowance' => $salary->washing_allowance,
            'fixed_salary' => $salary->fixed_salary,
            'no_of_days_worked' => $salary->no_of_days_worked,
            'leave_given' => $salary->leave_given,
            'total_days_for_salary' => $salary->total_days_for_salary,
            'drawn_salary' => $salary->drawn_salary,
            'incentive_hrs' => $salary->incentive_hrs,
            'incentive_rate' => $salary->incentive_rate,
            'incentive_amount' => $salary->incentive_amount,
            'attendance_bonus' => $salary->attendance_bonus,
            'gross_salary' => $salary->gross_salary,
            'esi' => $salary->esi,
            'pf' => $salary->pf,
            'pt' => $salary->pt,
            'advance_deduction' => $salary->advance_deduction,
            'net_salary' => $salary->net_salary,
            'payment_mode' => $salary->payment_mode,
        ]);
    }

    // Update salary detail
    public function updateSalaryDetail(Request $request, $id)
    {
        $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'month_year' => 'required',
            // other validation...
        ]);
        $salary = EmployeeSalaryDetail::findOrFail($id);
        $salary->update($request->all());
        return redirect()->route('manager.employee.employeepayroll')->with('success', 'Salary detail updated successfully.');
    }

    // Delete salary detail
    public function destroySalaryDetail($id)
    {
        $salary = EmployeeSalaryDetail::findOrFail($id);
        $salary->delete();
        return redirect()->route('manager.employee.employeepayroll')->with('success', 'Salary detail deleted successfully.');
    }
    // List leave requests
    public function employeeLeave()
    {
        $employees = \App\Models\EmployeeDetails::all();
        $leaves = \App\Models\EmployeeLeave::orderBy('id', 'desc')->get();
        return view('manager.employee.employeeleave', compact('employees', 'leaves'));
    }

    // Store leave request
    public function storeEmployeeLeave(Request $request)
    {
        $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'leave_type' => 'required',
            'leave_from' => 'required|date',
            'leave_to' => 'required|date',
            'number_of_days' => 'required|numeric|min:0.5',
            'duration_type' => 'required',
            'status' => 'required',
            'reason' => 'required',
            // add other validations if needed
        ]);
        $employee = \App\Models\EmployeeDetails::find($request->employee_id);
        \App\Models\EmployeeLeave::create([
            'employee_id' => $employee->id,
            'employee_name' => $employee->name,
            'department' => $employee->department,
            'leave_type' => $request->leave_type,
            'leave_from' => $request->leave_from,
            'leave_to' => $request->leave_to,
            'number_of_days' => $request->number_of_days,
            'duration_type' => $request->duration_type,
            'status' => $request->status,
            'reason' => $request->reason,
            'requested_on' => now(),
            'approved_by' => $request->approved_by,
            'approval_date' => $request->approval_date,
        ]);
        return redirect()->back()->with('success', 'Leave request added successfully.');
    }

    // Get leave for editing (AJAX)
    public function getEmployeeLeave($id)
    {
        $leave = \App\Models\EmployeeLeave::with('employee')->findOrFail($id);
        return response()->json([
            'employee_id' => $leave->employee_id,
            'employee_name' => $leave->employee_name,
            'department' => $leave->department,
            'leave_type' => $leave->leave_type,
            'leave_from' => $leave->leave_from ? $leave->leave_from->format('Y-m-d') : null,
            'leave_to' => $leave->leave_to ? $leave->leave_to->format('Y-m-d') : null,
            'number_of_days' => $leave->number_of_days,
            'duration_type' => $leave->duration_type,
            'status' => $leave->status,
            'reason' => $leave->reason,
            'approved_by' => $leave->approved_by,
            'approval_date' => $leave->approval_date ? \Carbon\Carbon::parse($leave->approval_date)->format('Y-m-d') : null,
        ]);
    }

    // Update leave
    public function updateEmployeeLeave(Request $request, $id)
    {
        $request->validate([
            'employee_id' => 'required|exists:employees,id',
            'leave_type' => 'required',
            'leave_from' => 'required|date',
            'leave_to' => 'required|date',
            'number_of_days' => 'required|numeric|min:0.5',
            'duration_type' => 'required',
            'status' => 'required',
            'reason' => 'required',
            // add other validations if needed
        ]);
        $leave = \App\Models\EmployeeLeave::findOrFail($id);
        $employee = \App\Models\EmployeeDetails::find($request->employee_id);
        $leave->update([
            'employee_id' => $employee->id,
            'employee_name' => $employee->name,
            'department' => $employee->department,
            'leave_type' => $request->leave_type,
            'leave_from' => $request->leave_from,
            'leave_to' => $request->leave_to,
            'number_of_days' => $request->number_of_days,
            'duration_type' => $request->duration_type,
            'status' => $request->status,
            'reason' => $request->reason,
            'approved_by' => $request->approved_by,
            'approval_date' => $request->approval_date,
        ]);
        return redirect()->route('manager.employee.employeeleave')->with('success', 'Leave request updated successfully.');
    }

    // Delete leave
    public function destroyEmployeeLeave($id)
    {
        $leave = EmployeeLeave::findOrFail($id);
        $leave->delete();
        return redirect()->route('manager.employee.employeeleave')->with('success', 'Leave request deleted successfully.');
    }

    // AJAX: Get Employee Name & Department
    public function getEmployeeNameDept($id)
    {
        $employee = \App\Models\EmployeeDetails::find($id);
        if ($employee) {
            return response()->json([
                'name' => $employee->name,
                'department' => $employee->department,
            ]);
        }
        return response()->json(['name' => '', 'department' => ''], 404);
    }
    public function importEmployees(Request $request)
    {
        $request->validate([
            'excel_file' => 'required|file|mimes:xlsx'
        ]);

        $file = $request->file('excel_file');
        Log::info('Bulk employee import started.', [
            'user_id' => auth()->id(),
            'filename' => $file->getClientOriginalName()
        ]);

        try {
            $spreadsheet = IOFactory::load($file->getRealPath());
            $worksheet = $spreadsheet->getActiveSheet();
            $rows = $worksheet->toArray(null, true, true, true);

            // Headers as values
            $headerRow = array_map('strtolower', array_map('trim', array_values($rows[1])));
            $expectedHeaders = [
                'employee_id',
                'name',
                'gender',
                'department',
                'designation',
                'dob',
                'doj',
                'mobile',
                'aadhar_number',
                'category',
                'status'
            ];

            if ($headerRow !== $expectedHeaders) {
                Log::error('Bulk employee import: header mismatch.', [
                    'provided' => $headerRow,
                    'expected' => $expectedHeaders
                ]);
                return back()->with('error', 'Invalid template format. Please use the provided sample template.');
            }

            $successCount = 0;
            $errorCount = 0;
            $errorRows = [];
            DB::beginTransaction();

            foreach (array_slice($rows, 1) as $index => $row) {
                if ($index == 0) continue; // Skip header
                $rowData = array_combine($expectedHeaders, array_map('trim', array_values($row)));
                // Fix dates
                foreach (['dob', 'doj'] as $dateField) {
                    if (!empty($rowData[$dateField])) {
                        try {
                            // Try to convert Excel/US/ISO/other date formats to Y-m-d
                            $rowData[$dateField] = Carbon::parse($rowData[$dateField])->format('Y-m-d');
                        } catch (\Exception $e) {
                            // If parsing fails, keep as is, validation will catch it
                        }
                    } else {
                        $rowData[$dateField] = null; // Optional: set empty dates to null
                    }
                }
                $validator = Validator::make($rowData, [
                    'employee_id'    => 'required|unique:employees,employee_id',
                    'name'           => 'required',
                    'gender'         => 'required|in:Male,Female,Other',
                    'department'     => 'nullable',
                    'designation'    => 'nullable',
                    'dob'            => 'nullable|date',
                    'doj'            => 'nullable|date',
                    'mobile'         => 'nullable|digits:10',
                    'aadhar_number'  => 'nullable|digits:12',
                    'category'       => 'nullable',
                    'status'         => 'required|in:ACTIVE,INACTIVE,active,inactive'
                ]);

                if ($validator->fails()) {
                    $errorCount++;
                    $errorRows[] = "Row " . ($index + 1) . ": " . implode('; ', $validator->errors()->all());
                    Log::warning('Bulk employee import: validation failed.', [
                        'row_number' => $index + 1,
                        'errors' => $validator->errors()->all(),
                        'data' => $rowData
                    ]);
                    continue;
                }

                try {
                    // Adjust status to uppercase (optional)
                    $rowData['status'] = strtoupper($rowData['status']);
                    \App\Models\EmployeeDetails::create($rowData); // Change model name if needed
                    $successCount++;
                } catch (\Exception $e) {
                    $errorCount++;
                    $errorRows[] = "Row " . ($index + 1) . ": " . $e->getMessage();
                    Log::error('Bulk employee import: DB insert failed.', [
                        'row_number' => $index + 1,
                        'exception' => $e->getMessage(),
                        'data' => $rowData
                    ]);
                }
            }
            DB::commit();

            $message = "{$successCount} employees imported.";
            if ($errorCount > 0) {
                $message .= " {$errorCount} errors. See below.";
                Log::warning('Bulk employee import completed with errors.', ['errors' => $errorRows]);
                return back()->with('success', $message)->with('errorRows', $errorRows);
            }
            return back()->with('success', $message);
        } catch (\Exception $e) {
            Log::critical('Bulk employee import failed.', ['exception' => $e->getMessage()]);
            return back()->with('error', 'Failed to import: ' . $e->getMessage());
        }
    }
}
