<?php

namespace Modules\Employees\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\User;
use App\Services\PlanPricingService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class EmployeeController extends Controller
{
    public function index(Request $request): JsonResponse
    {
        $query = User::forActiveDirectory()
            ->with(['department', 'designation', 'location']);
        if ($request->user()->company_id) {
            $query->where('company_id', $request->user()->company_id);
        }
        $employees = $query->paginate($request->input('per_page', 15));

        return response()->json($employees);
    }

    public function store(Request $request): JsonResponse
    {
        $company = Company::with('subscriptionPlan')->find($request->user()->company_id);
        if ($company && ! $company->canAddEmployees(1)) {
            $pricing = app(PlanPricingService::class);
            $next = $pricing->suggestNextPlan($company);
            $payload = [
                'message' => 'Employee seat limit reached for your plan.',
                'seat_limit' => $company->employeeSeatLimit(),
                'upgrade_url' => route('subscription.request'),
            ];
            if ($next) {
                $quote = $pricing->canUpgradeTo($company, $next)
                    ? $pricing->calculateUpgradeQuote($company, $next)
                    : $pricing->calculateYearlyTotal($next, null, $company);
                $payload['suggested_plan'] = $next->only(['id', 'name', 'employee_limit']);
                $payload['suggested_payable'] = $quote['total'];
            }

            return response()->json($payload, 422);
        }

        $companyId = $request->user()->company_id;
        $validated = $request->validate([
            'name' => 'required|string|max:191',
            'email' => [
                'required',
                'email',
                Rule::unique('users', 'email')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'password' => 'required|string|min:8',
            'employee_number' => 'nullable|string',
            'department_id' => [
                'nullable',
                Rule::exists('departments', 'id')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'designation_id' => [
                'nullable',
                Rule::exists('designations', 'id')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'location_id' => [
                'nullable',
                Rule::exists('locations', 'id')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'attendance_mode' => ['nullable', Rule::in(['tenant_default', 'normal', 'office_geofence', 'remote', 'hybrid'])],
        ]);

        if (($validated['attendance_mode'] ?? null) === 'tenant_default') {
            $validated['attendance_mode'] = null;
        }

        $employee = new User;
        $employee->fill([
            'name' => $validated['name'],
            'email' => $validated['email'],
            'password' => $validated['password'],
            'employee_number' => $validated['employee_number'] ?? null,
            'department_id' => $validated['department_id'] ?? null,
            'designation_id' => $validated['designation_id'] ?? null,
            'location_id' => $validated['location_id'] ?? null,
            'attendance_mode' => $validated['attendance_mode'] ?? null,
        ]);
        $employee->forceFill([
            'company_id' => $companyId,
            'user_type' => User::USER_TYPE_STAFF,
            'status' => User::STATUS_ACTIVE,
            'allow_login' => true,
            'is_superadmin' => false,
        ])->save();

        return response()->json($employee->load(['department', 'designation']), 201);
    }

    public function show(Request $request, string $employee): JsonResponse
    {
        $user = User::where('company_id', $request->user()->company_id)
            ->forTenantDirectory()
            ->findOrFail($employee);

        return response()->json($user->load(['department', 'designation', 'location', 'shift', 'reportingManager']));
    }

    public function update(Request $request, string $employee): JsonResponse
    {
        $user = User::where('company_id', $request->user()->company_id)
            ->forTenantDirectory()
            ->findOrFail($employee);
        $companyId = $request->user()->company_id;
        $validated = $request->validate([
            'name' => 'sometimes|string|max:191',
            'email' => [
                'sometimes',
                'email',
                Rule::unique('users', 'email')
                    ->ignore($user->id)
                    ->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'department_id' => [
                'nullable',
                Rule::exists('departments', 'id')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'designation_id' => [
                'nullable',
                Rule::exists('designations', 'id')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'location_id' => [
                'nullable',
                Rule::exists('locations', 'id')->where(fn ($q) => $q->where('company_id', $companyId)),
            ],
            'attendance_mode' => ['nullable', Rule::in(['tenant_default', 'normal', 'office_geofence', 'remote', 'hybrid'])],
        ]);
        if (($validated['attendance_mode'] ?? null) === 'tenant_default') {
            $validated['attendance_mode'] = null;
        }
        $user->update($validated);

        return response()->json($user->fresh());
    }

    public function destroy(Request $request, string $employee): JsonResponse
    {
        $user = User::where('company_id', $request->user()->company_id)
            ->forTenantDirectory()
            ->findOrFail($employee);
        $user->delete();

        return response()->json(null, 204);
    }
}
