<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\ApiBaseController;
use App\Models\FaceRegistration;
use App\Models\StaffMember;
use App\Models\User;
use Examyou\RestAPI\ApiResponse;
use Examyou\RestAPI\Exceptions\ApiException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use App\Classes\Common;
use App\Classes\CommonHrm;

class FaceController extends ApiBaseController
{
    /**
     * Ensure the logged-in manager/admin can access the given user.
     */
    protected function ensureManagerCanAccessUser(int $userId): StaffMember
    {
        $loggedUser = user();

        if (
            (!$loggedUser->is_manager && !$loggedUser->ability('admin', 'users_edit')) ||
            !$loggedUser->role
        ) {
            throw new ApiException("Don't have valid permission");
        }

        $userQuery = StaffMember::where('id', $userId)
            ->where('company_id', company()->id);

        $userQuery = CommonHrm::applyVisibility($userQuery);

        $user = $userQuery->first();

        if (!$user) {
            throw new ApiException('User not found or not accessible', null, 404, 404);
        }

        return $user;
    }

    /**
     * GET /api/users/missing-faces
     * Return users without face_id data
     */
    public function missingFaces(Request $request)
    {
        try {
            $companyId = company()->id;
            
            // Get users who don't have face registrations
            $usersWithoutFaces = User::where('company_id', $companyId)
                ->where('user_type', 'staff_members')
                ->whereDoesntHave('faceRegistrations', function ($query) use ($companyId) {
                    $query->where('company_id', $companyId);
                })
                ->with(['company', 'location', 'designation','department'])
                ->select('id', 'name', 'location_id', 'designation_id','department_id','email', 'employee_number', 'profile_image', 'company_id')
                ->get()
                ->map(function ($user) {
                    return [
                        'id' => $user->xid,
                        'company_id' => $user->company?->xid ?? null,
                        'location_id' => $user->location?->xid ?? null,
                        'designation_id' => $user->designation?->xid ?? null,
                        'department_id' => $user->department?->xid ?? null,
                        'name' => $user->name,
                        'email' => $user->email,
                        'employee_number' => $user->employee_number,
                        'profile_image_url' => $user->profile_image_url,
                        'location' => $user->location?->name ?? null,
                        'designation' => $user->designation?->name ?? null,
                        'department' => $user->department?->name ?? null,
                    ];
                });

            return ApiResponse::make('Success', [
                'users' => $usersWithoutFaces,
                'count' => $usersWithoutFaces->count()
            ]);
        } catch (\Exception $e) {
            throw new ApiException('Failed to fetch users without faces', null, 500, 500, $e);
        }
    }

    /**
     * GET /api/face/sync
     * Return all face registration data for a company
     */
    public function sync(Request $request)
    {
        try {
            $companyId = company()->id;
            
            $faceRegistrations = FaceRegistration::where('company_id', $companyId)
                ->with(['user:id,name,email,employee_number'])
                ->get()
                ->map(function ($registration) {
                    return [
                        'id' => $registration->xid,
                        'user_id' => $registration->user?->xid ?? null,
                        'company_id' => $registration->company?->xid ?? null,
                        'face_data' => $registration->getDecryptedFaceData(),
                        'user' => $registration->user ? [
                            'id' => $registration->user->xid ?? null,
                            'company_id' => $registration->company?->xid ?? null,
                            'name' => $registration->user->name,
                            'email' => $registration->user->email,
                            'employee_number' => $registration->user->employee_number,
                        ] : null,
                        'created_at' => $registration->created_at,
                        'updated_at' => $registration->updated_at,
                    ];
                });

            return ApiResponse::make('Success', [
                'faces' => $faceRegistrations,
                'count' => $faceRegistrations->count()
            ]);
        } catch (\Exception $e) {
            throw new ApiException('Failed to sync face data', null, 500, 500, $e);
        }
    }

    /**
     * POST /api/face/register
     * Register user face data
     */
    public function register(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'user_id' => 'required',
                'company_id' => 'required',
                'face_data' => 'required|string',
            ]);

            if ($validator->fails()) {
                throw new ApiException('Validation failed', null, 422, 422, null, $validator->errors()->toArray());
            }

            $userId = Common::getIdFromHash($request->user_id);
            $companyId = Common::getIdFromHash($request->company_id);
            $faceData = $request->face_data;

            // Verify user belongs to company

            $user = User::where('id', $userId)
                ->where('company_id', $companyId)
                ->first();

            if (!$user) {
                throw new ApiException('User not found or does not belong to company', null, 404, 404);
            }

            // Check if face registration already exists
            $existingRegistration = FaceRegistration::where('user_id', $userId)
                ->where('company_id', $companyId)
                ->first();

            if ($existingRegistration) {
                // Update existing registration
                $existingRegistration->face_data = $faceData;
                $existingRegistration->save();
                
                return ApiResponse::make('Face data updated successfully', [
                    'face_registration' => [
                        'id' => $existingRegistration->xid,
                        'user_id' => $existingRegistration->user?->xid ?? null,
                        'company_id' => $existingRegistration->company?->xid ?? null,
                        'created_at' => $existingRegistration->created_at,
                        'updated_at' => $existingRegistration->updated_at,
                    ]
                ]);
            } else {
                // Create new registration
                $faceRegistration = new FaceRegistration();
                $faceRegistration->user_id = $userId;
                $faceRegistration->company_id = $companyId;
                $faceRegistration->face_data = $faceData;
                $faceRegistration->save();

                return ApiResponse::make('Face data registered successfully', [
                    'face_registration' => [
                        'id' => $faceRegistration->xid,
                        'user_id' => $faceRegistration->user?->xid ?? null,
                        'company_id' => $faceRegistration->company?->xid ?? null,
                        'created_at' => $faceRegistration->created_at,
                        'updated_at' => $faceRegistration->updated_at,
                    ]
                ]);
            }
        } catch (ApiException $e) {
            throw $e;
        } catch (\Exception $e) {
            throw new ApiException('Failed to register face data', null, 500, 500, $e);
        }
    }

    /**
     * GET /api/face/registration/{user_id}
     * Fetch face registration status for a specific user
     */
    public function showUserFaceRegistration(string $xUserId)
    {
        try {
            $userId = Common::getIdFromHash($xUserId);
            $this->ensureManagerCanAccessUser($userId);

            $companyId = company()->id;
            $faceRegistration = FaceRegistration::where('user_id', $userId)
                ->where('company_id', $companyId)
                ->first();

            return ApiResponse::make('Success', [
                'registered' => (bool) $faceRegistration,
                'face_registration' => $faceRegistration ? [
                    'id' => $faceRegistration->xid,
                    'user_id' => $faceRegistration->user?->xid,
                    'company_id' => $faceRegistration->company?->xid,
                    'created_at' => $faceRegistration->created_at,
                    'updated_at' => $faceRegistration->updated_at,
                ] : null,
            ]);
        } catch (ApiException $e) {
            throw $e;
        } catch (\Exception $e) {
            throw new ApiException('Failed to fetch face registration', null, 500, 500, $e);
        }
    }

    /**
     * DELETE /api/face/registration/{user_id}
     * Clear face registration for a specific user
     */
    public function clearUserFaceRegistration(string $xUserId)
    {
        try {
            $userId = Common::getIdFromHash($xUserId);
            $user = $this->ensureManagerCanAccessUser($userId);

            $companyId = company()->id;

            $existingRegistration = FaceRegistration::where('user_id', $userId)
                ->where('company_id', $companyId)
                ->first();

            if (!$existingRegistration) {
                return ApiResponse::make('No face registration found', [
                    'cleared' => false,
                    'face_registration' => null,
                ]);
            }

            DB::transaction(function () use ($existingRegistration) {
                $existingRegistration->delete();
            });

            return ApiResponse::make('Face registration cleared successfully', [
                'cleared' => true,
                'face_registration' => null,
                'user' => [
                    'id' => $user->xid,
                ],
            ]);
        } catch (ApiException $e) {
            throw $e;
        } catch (\Exception $e) {
            throw new ApiException('Failed to clear face registration', null, 500, 500, $e);
        }
    }
}

