<?php

namespace Modules\ClinicStaffPortal\Http\Controllers\Api;

use App\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Hash;
use Modules\ClinicStaffPortal\Entities\CsStaffToken;

/**
 * Staff/doctor authentication. Validates against the existing ERP `users`
 * table â€” no parallel account store. On success issues a bearer token the PWA
 * stores and replays on every request.
 */
class AuthController extends Controller
{
    /** Username (or email) + password. */
    public function password(Request $request): JsonResponse
    {
        $data = $request->validate([
            'username' => 'required|string|max:191',
            'password' => 'required|string|max:191',
        ]);

        $login = trim($data['username']);

        $user = User::where('username', $login)
            ->orWhere('email', $login)
            ->first();

        if (! $user || ! Hash::check($data['password'], $user->password)) {
            // Generic message â€” don't reveal whether the username exists.
            return response()->json(['message' => 'Invalid username or password.'], 422);
        }

        if (isset($user->status) && $user->status !== 'active') {
            return response()->json(['message' => 'This account is not active.'], 422);
        }

        // Authorise: must have clinic access.
        auth()->setUser($user);
        if (! $user->can('clinic.access_module')) {
            return response()->json(['message' => 'You do not have access to the clinic.'], 403);
        }

        return $this->issue($user, $request);
    }

    /** DEV-only: log in as the first clinic-capable user without a password. */
    public function dev(Request $request): JsonResponse
    {
        if (! self::devEnabled()) {
            return response()->json(['message' => 'Not found'], 404);
        }

        $user = User::where('status', 'active')->orderBy('id')->get()
            ->first(function ($u) {
                auth()->setUser($u);
                return $u->can('clinic.access_module');
            });

        if (! $user) {
            return response()->json(['message' => 'No clinic-capable user to log in as.'], 404);
        }

        return $this->issue($user, $request);
    }

    public function logout(Request $request): JsonResponse
    {
        CsStaffToken::revoke($request->bearerToken() ?? '');
        return response()->json(['ok' => true]);
    }

    /* â”€â”€ helpers â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€ */

    private function issue(User $user, Request $request): JsonResponse
    {
        $bearer = CsStaffToken::issue($user, $request->userAgent(), $request->ip());

        return response()->json([
            'token' => $bearer,
            'me'    => $this->mePayload($user),
        ]);
    }

    private function mePayload(User $user): array
    {
        $doctor = self::doctorForUser($user);
        return [
            'id'         => $user->id,
            'name'       => trim(($user->surname ? $user->surname . ' ' : '') . $user->first_name . ' ' . $user->last_name) ?: $user->username,
            'username'   => $user->username,
            'email'      => $user->email,
            'is_doctor'  => (bool) $doctor,
            'doctor_id'  => $doctor?->id,
            'business_id'=> $user->business_id,
            'can'        => [
                'manage_appointments' => $user->can('clinic.manage_appointments'),
                'view_appointments'   => $user->can('clinic.view_appointments'),
                'manage_admissions'   => $user->can('vet_admission.manage_admissions'),
                'view_admissions'     => $user->can('vet_admission.view_admissions') || $user->can('vet_admission.manage_admissions'),
                'log_care'            => $user->can('vet_admission.log_care'),
            ],
        ];
    }

    /** The ClcDoctor row linked to this ERP user (if they're a doctor). */
    public static function doctorForUser(User $user)
    {
        try {
            return \Modules\ClinicCore\Entities\ClcDoctor::where('business_id', $user->business_id)
                ->where('user_id', $user->id)->first();
        } catch (\Throwable $e) {
            return null;
        }
    }

    public static function devEnabled(): bool
    {
        $flag = config('clinicstaffportal.dev_login', null);
        return $flag === null ? (bool) config('app.debug') : (bool) $flag;
    }
}
