<?php

namespace App\Http\Controllers\Modules\Employee;

use App\Http\Controllers\Controller;
use App\Http\Traits\HasRoleViews;
use App\Models\EmployeeDetails;
use App\Models\EmployeeSalaryDetail;
use App\Services\Employee\EmployeeService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Yajra\DataTables\Facades\DataTables;

/**
 * Unified Employee Controller
 *
 * Handles employee management for all roles.
 * Views are automatically resolved based on the logged-in user's role.
 */
class EmployeeController extends Controller
{
    use HasRoleViews;

    protected EmployeeService $employeeService;

    public function __construct(EmployeeService $employeeService)
    {
        $this->employeeService = $employeeService;
    }

    /**
     * Display the employee list page
     */
    public function index()
    {
        $employees = $this->employeeService->getAll();
        return $this->roleView('employee.employeedetails', compact('employees'));
    }

    /**
     * Alias for index - backward compatibility
     */
    public function employeeDetails()
    {
        return $this->index();
    }

    /**
     * Get employees for DataTable
     */
    public function list()
    {
        $employees = $this->employeeService->getAll();
        return DataTables::of($employees)
            ->addIndexColumn()
            ->addColumn('action', function ($row) {
                return $this->getActionButtons($row);
            })
            ->rawColumns(['action'])
            ->make(true);
    }

    /**
     * Generate action buttons
     */
    protected function getActionButtons($row): string
    {
        $editRoute = route($this->resolveRoute('employee.edit'), $row->id);
        $showRoute = route($this->resolveRoute('employee.show'), $row->id);

        return '
            <a href="' . $showRoute . '" class="btn btn-info btn-sm" title="View">
                <i class="fas fa-eye"></i>
            </a>
            <a href="' . $editRoute . '" class="btn btn-primary btn-sm" title="Edit">
                <i class="fas fa-edit"></i>
            </a>
            <button class="btn btn-danger btn-sm delete-btn" data-id="' . $row->id . '" title="Delete">
                <i class="fas fa-trash"></i>
            </button>
        ';
    }

    /**
     * Display the add employee form
     */
    public function create()
    {
        $employeeId = $this->employeeService->generateEmployeeId();
        return $this->roleView('employee.addemployee', compact('employeeId'));
    }

    /**
     * Store a newly created employee
     */
    public function store(Request $request)
    {
        $validated = $request->validate($this->getValidationRules());

        try {
            if ($request->hasFile('photo')) {
                $validated['photo'] = $request->file('photo')->store('employee-photos', 'public');
            }

            $employee = $this->employeeService->create($validated);

            return $this->redirectToRoute('employee.employeedetails')
                ->with('success', 'Employee added successfully.');
        } catch (\Exception $e) {
            Log::error('Employee creation failed: ' . $e->getMessage());
            return back()->withInput()->with('error', 'Failed to add employee: ' . $e->getMessage());
        }
    }

    /**
     * Display the specified employee
     */
    public function show(int $id)
    {
        $employee = $this->employeeService->findById($id);

        if (!$employee) {
            return $this->redirectToRoute('employee.employeedetails')
                ->with('error', 'Employee not found.');
        }

        return $this->roleView('employee.employeeview', compact('employee'));
    }

    /**
     * Display the edit form
     */
    public function edit(int $id)
    {
        $employee = $this->employeeService->findById($id);

        if (!$employee) {
            return $this->redirectToRoute('employee.employeedetails')
                ->with('error', 'Employee not found.');
        }

        return $this->roleView('employee.editemployee', compact('employee'));
    }

    /**
     * Update the specified employee
     */
    public function update(Request $request, int $id)
    {
        $validated = $request->validate($this->getUpdateValidationRules($id));

        try {
            $employee = $this->employeeService->findById($id);

            if ($request->hasFile('photo')) {
                if ($employee->photo && Storage::disk('public')->exists($employee->photo)) {
                    Storage::disk('public')->delete($employee->photo);
                }
                $validated['photo'] = $request->file('photo')->store('employee-photos', 'public');
            }

            $this->employeeService->update($id, $validated);

            return $this->redirectToRoute('employee.employeedetails')
                ->with('success', 'Employee updated successfully.');
        } catch (\Exception $e) {
            Log::error('Employee update failed: ' . $e->getMessage());
            return back()->withInput()->with('error', 'Failed to update employee: ' . $e->getMessage());
        }
    }

    /**
     * Remove the specified employee
     */
    public function destroy(int $id): JsonResponse
    {
        if (!$this->isSuperAdmin() && !$this->isManager()) {
            return response()->json(['success' => false, 'message' => 'Unauthorized. Only SuperAdmin or Manager can delete employees.'], 403);
        }

        try {
            $employee = $this->employeeService->findById($id);

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

            if ($employee->photo && Storage::disk('public')->exists($employee->photo)) {
                Storage::disk('public')->delete($employee->photo);
            }

            $this->employeeService->delete($id);

            return response()->json(['success' => true, 'message' => 'Employee deleted successfully']);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Failed to delete employee'], 500);
        }
    }

    /**
     * Get employee data by employee_id (AJAX)
     */
    public function getByEmployeeId(string $employeeId): JsonResponse
    {
        $employee = EmployeeDetails::where('employee_id', $employeeId)->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' => '',
        ]);
    }

    /**
     * Import employees from Excel
     */
    public function import(Request $request)
    {
        $request->validate([
            'excel_file' => 'required|file|mimes:xlsx',
        ]);

        $file = $request->file('excel_file');

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

            $successCount = 0;
            $errorCount = 0;
            $errorRows = [];

            DB::beginTransaction();

            foreach (array_slice($rows, 1) as $index => $row) {
                if ($index == 0) continue;

                try {
                    EmployeeDetails::create([
                        'employee_id' => $row['A'],
                        'name' => $row['B'],
                        'gender' => $row['C'],
                        'dob' => $row['D'],
                        'doj' => $row['E'],
                        'department' => $row['F'],
                        'designation' => $row['G'],
                        'email' => $row['H'] ?? null,
                        'mobile' => $row['I'] ?? null,
                    ]);
                    $successCount++;
                } catch (\Exception $e) {
                    $errorCount++;
                    $errorRows[] = "Row " . ($index + 1) . ": " . $e->getMessage();
                }
            }

            DB::commit();

            $message = "{$successCount} employees imported.";
            if ($errorCount > 0) {
                $message .= " {$errorCount} errors.";
                return back()->with('success', $message)->with('errorRows', $errorRows);
            }

            return back()->with('success', $message);
        } catch (\Exception $e) {
            DB::rollback();
            Log::error('Employee import failed: ' . $e->getMessage());
            return back()->with('error', 'Failed to import: ' . $e->getMessage());
        }
    }

    /**
     * Get validation rules
     */
    protected function getValidationRules(): array
    {
        return [
            'employee_id' => 'required|string|unique:employee_details,employee_id',
            'name' => 'required|string|max:255',
            'gender' => 'required|in:Male,Female,Other',
            'dob' => 'required|date',
            'doj' => 'required|date',
            'department' => 'required|string|max:255',
            'designation' => 'required|string|max:255',
            'email' => 'nullable|email|max:255',
            'mobile' => 'nullable|digits:10',
            'photo' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
        ];
    }

    /**
     * Get update validation rules
     */
    protected function getUpdateValidationRules(int $id): array
    {
        return [
            'employee_id' => 'required|string|unique:employee_details,employee_id,' . $id,
            'name' => 'required|string|max:255',
            'gender' => 'required|in:Male,Female,Other',
            'dob' => 'required|date',
            'doj' => 'required|date',
            'department' => 'required|string|max:255',
            'designation' => 'required|string|max:255',
            'email' => 'nullable|email|max:255',
            'mobile' => 'nullable|digits:10',
            'photo' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
        ];
    }
}
