<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Worker;
use App\Models\WorkerCategory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Str;

class WorkerAuthController extends Controller
{
    /**
     * Get system configuration and supported languages for worker onboarding.
     * Aligns with Step 2 "Select Language (HI / SW / TL / TA)".
     */
    public function config()
    {
        return response()->json([
            'success' => true,
            'languages' => [
                ['code' => 'HI', 'name' => 'Hindi (हिन्दी)'],
                ['code' => 'SW', 'name' => 'Swahili (Kiswahili)'],
                ['code' => 'TL', 'name' => 'Tagalog (Wikang Tagalog)'],
                ['code' => 'TA', 'name' => 'Tamil (தமிழ்)'],
            ]
        ], 200);
    }

    /**
     * Step 1: Send OTP to worker's mobile number or email.
     * Accepts: phone OR email (one is required).
     */
    public function sendOtp(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'phone' => 'required_without:email|nullable|string|max:50',
            'email' => 'required_without:phone|nullable|email|max:255',
        ], [
            'phone.required_without' => 'Please provide a mobile number or email address.',
            'email.required_without' => 'Please provide a mobile number or email address.',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error.',
                'errors' => $validator->errors()
            ], 422);
        }

        // Determine identifier (phone takes priority)
        $identifier = $request->phone ?? $request->email;
        $isPhone    = !empty($request->phone);

        // Generate OTP (always 111111 in local/dev, random in production)
        $otp = app()->environment('production') ? strval(rand(100000, 999999)) : '111111';

        // Cache OTP for 10 minutes
        Cache::put('worker_otp_' . $identifier, [
            'code'       => $otp,
            'expires_at' => now()->addMinutes(10)->timestamp,
        ], 600);

        // Send OTP via email if email provided (phone SMS would be handled by SMS gateway)
        if (!$isPhone && $request->email) {
            try {
                Mail::raw("Your Migrant Worker verification code is: {$otp}\n\nThis code expires in 10 minutes.", function ($m) use ($request, $otp) {
                    $m->to($request->email)
                      ->subject('Your Migrant Worker Verification Code');
                });
            } catch (\Exception $mailEx) {
                logger()->error('Worker OTP Mail Failure: ' . $mailEx->getMessage());
            }
        }

        return response()->json([
            'success'    => true,
            'message'    => $isPhone
                ? 'OTP sent to your mobile number.'
                : 'OTP sent to your email address.',
            'identifier' => $identifier,
            'otp'        => app()->environment('production') ? null : $otp, // Return OTP in response in non-prod for testing convenience
        ], 200);
    }

    /**
     * Step 2: Verify OTP sent to mobile/email.
     * Accepts: phone OR email, otp.
     */
    public function verifyOtp(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'phone'  => 'required_without:email|nullable|string|max:50',
            'email'  => 'required_without:phone|nullable|email|max:255',
            'otp'    => 'required|string|size:6',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors'  => $validator->errors()
            ], 422);
        }

        $identifier = $request->phone ?? $request->email;
        $cachedData = Cache::get('worker_otp_' . $identifier);

        if (!$cachedData || !isset($cachedData['code']) || !isset($cachedData['expires_at'])) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid or expired verification code.'
            ], 400);
        }

        // Handle any dirty/legacy cache objects gracefully
        if (is_object($cachedData['expires_at']) || $cachedData['expires_at'] instanceof \__PHP_Incomplete_Class) {
            Cache::forget('worker_otp_' . $identifier);
            return response()->json([
                'success' => false,
                'message' => 'Session expired. Please request a new verification code.'
            ], 400);
        }

        if ($cachedData['code'] !== $request->otp || now()->timestamp > $cachedData['expires_at']) {
            return response()->json([
                'success' => false,
                'message' => 'Invalid or expired verification code.'
            ], 400);
        }

        // Mark OTP as verified in cache (used as gate for profile setup step)
        Cache::put('worker_otp_verified_' . $identifier, true, 3600); // 1 hour grace
        Cache::forget('worker_otp_' . $identifier);

        return response()->json([
            'success'    => true,
            'message'    => 'Mobile number verified successfully. Please complete your profile.',
            'identifier' => $identifier,
        ], 200);
    }

    /**
     * Step 3: Complete basic profile setup after OTP verification.
     * Accepts: phone OR email, name, nationality, skills (array of skill IDs), language.
     */
    public function setupProfile(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'phone'       => 'required_without:email|nullable|string|max:50',
            'email'       => 'required_without:phone|nullable|email|max:255',
            'name'        => 'required|string|max:255',
            'nationality' => 'required|string|max:100',
            'language'    => 'nullable|string|in:HI,SW,TL,TA',
            'skills'      => 'nullable|array',
            'skills.*'    => 'integer|exists:skills,id',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'errors'  => $validator->errors()
            ], 422);
        }

        $identifier = $request->phone ?? $request->email;

        // Ensure OTP was verified in this session
        if (!Cache::get('worker_otp_verified_' . $identifier)) {
            return response()->json([
                'success' => false,
                'message' => 'OTP verification is required before profile setup.'
            ], 403);
        }

        // Check if already registered
        if ($request->phone && Worker::where('phone', $request->phone)->exists()) {
            return response()->json([
                'success' => false,
                'message' => 'This mobile number is already registered.'
            ], 409);
        }
        if ($request->email && Worker::where('email', $request->email)->exists()) {
            return response()->json([
                'success' => false,
                'message' => 'This email address is already registered.'
            ], 409);
        }

        try {
            // Build email for workers who registered by phone
            $email = $request->email;
            if (!$email && $request->phone) {
                $phoneClean = preg_replace('/[^0-9]/', '', $request->phone);
                $email = "worker.{$phoneClean}@migrant.ae";
                if (Worker::where('email', $email)->exists()) {
                    $email = "worker.{$phoneClean}." . rand(10, 99) . "@migrant.ae";
                }
            }

            $apiToken = Str::random(80);

            $worker = DB::transaction(function () use ($request, $email, $apiToken) {
                $worker = Worker::create([
                    'name'        => $request->name,
                    'email'       => $email,
                    'phone'       => $request->phone ?? null,
                    'language'    => $request->language ?? 'HI', // Default to Hindi if not selected
                    'password'    => Hash::make(Str::random(16)), // No password at this stage
                    'nationality' => $request->nationality,
                    'age'         => 25,   // Default — updated later in full profile
                    'salary'      => 1500, // Default AED — updated later
                    'availability'=> 'Immediate',
                    'experience'  => 'Not Specified',
                    'religion'    => 'Not Specified',
                    'bio'         => 'New worker on Migrant platform.',
                    'category_id' => 7,    // Default: General Helper
                    'verified'    => false,
                    'status'      => 'active',
                    'api_token'   => $apiToken,
                ]);

                // Sync skills if provided
                if (!empty($request->skills)) {
                    $worker->skills()->sync($request->skills);
                }

                return $worker;
            });

            // Clear the OTP verification gate
            Cache::forget('worker_otp_verified_' . $identifier);

            $worker->load(['category', 'skills']);

            return response()->json([
                'success' => true,
                'message' => 'Registration complete! Welcome to Migrant.',
                'data'    => [
                    'worker' => $worker,
                    'token'  => $apiToken,
                ]
            ], 201);

        } catch (\Exception $e) {
            logger()->error('Worker Profile Setup Failure: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Registration failed. Please try again.',
                'error'   => app()->environment('local', 'testing') ? $e->getMessage() : 'Internal Server Error'
            ], 500);
        }
    }

    /**
     * Unified registration — supports backward compatibility and multipart file registration.
     */
    public function register(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name'          => 'required|string|max:255',
            'phone'         => 'required|string|max:50|unique:workers,phone',
            'salary'        => 'required|numeric|min:0',
            'password'      => 'required|string|min:6',
            'passport_file' => 'required|file|mimes:jpeg,png,jpg,pdf|max:10240',
            'skills'        => 'nullable',
            'visa_file'     => 'nullable|file|mimes:jpeg,png,jpg,pdf|max:10240',
            'language'      => 'nullable|string|in:HI,SW,TL,TA',
            'nationality'   => 'nullable|string|max:100',
            'age'           => 'nullable|integer',
            'experience'    => 'nullable|string|max:100',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error.',
                'errors'  => $validator->errors()
            ], 422);
        }

        try {
            $phoneClean = preg_replace('/[^0-9]/', '', $request->phone);
            $email = "worker.{$phoneClean}@migrant.ae";
            if (Worker::where('email', $email)->exists()) {
                $email = "worker.{$phoneClean}." . rand(10, 99) . "@migrant.ae";
            }

            $skillsArray = [];
            if ($request->has('skills')) {
                $skillsInput = $request->skills;
                if (is_array($skillsInput)) {
                    $skillsArray = $skillsInput;
                } elseif (is_string($skillsInput)) {
                    $decoded = json_decode($skillsInput, true);
                    $skillsArray = (json_last_error() === JSON_ERROR_NONE && is_array($decoded))
                        ? $decoded
                        : array_filter(array_map('trim', explode(',', $skillsInput)));
                }
            }

            $destinationPath = public_path('uploads/documents');
            if (!file_exists($destinationPath)) {
                mkdir($destinationPath, 0755, true);
            }

            $passportPath = null;
            $visaPath     = null;

            if ($request->hasFile('passport_file')) {
                $file         = $request->file('passport_file');
                $fileName     = time() . '_passport_' . preg_replace('/[^a-zA-Z0-9_.-]/', '', $file->getClientOriginalName());
                $file->move($destinationPath, $fileName);
                $passportPath = 'uploads/documents/' . $fileName;
            }

            if ($request->hasFile('visa_file')) {
                $file     = $request->file('visa_file');
                $fileName = time() . '_visa_' . preg_replace('/[^a-zA-Z0-9_.-]/', '', $file->getClientOriginalName());
                $file->move($destinationPath, $fileName);
                $visaPath = 'uploads/documents/' . $fileName;
            }

            $apiToken = Str::random(80);

            $result = DB::transaction(function () use ($request, $email, $skillsArray, $passportPath, $visaPath, $apiToken) {
                $worker = Worker::create([
                    'name'        => $request->name,
                    'email'       => $email,
                    'phone'       => $request->phone,
                    'language'    => $request->language ?? 'HI',
                    'password'    => Hash::make($request->password),
                    'nationality' => $request->nationality ?? 'Not Specified',
                    'age'         => $request->age ?? 25,
                    'salary'      => $request->salary,
                    'availability'=> 'Immediate',
                    'experience'  => $request->experience ?? 'Not Specified',
                    'religion'    => 'Not Specified',
                    'bio'         => 'Hardworking and reliable General Helper available for immediate hire.',
                    'category_id' => 7,
                    'verified'    => false,
                    'status'      => 'active',
                    'api_token'   => $apiToken,
                ]);

                if (!empty($skillsArray)) {
                    $validSkillIds = DB::table('skills')->whereIn('id', $skillsArray)->pluck('id')->toArray();
                    if (!empty($validSkillIds)) {
                        $worker->skills()->sync($validSkillIds);
                    }
                }

                $worker->documents()->create([
                    'type'        => 'passport',
                    'number'      => 'P' . rand(100000, 999999),
                    'issue_date'  => now()->subYears(2)->toDateString(),
                    'expiry_date' => now()->addYears(8)->toDateString(),
                    'ocr_accuracy'=> 98.5,
                    'file_path'   => $passportPath,
                ]);

                $worker->documents()->create([
                    'type'        => 'visa',
                    'number'      => 'V' . rand(100000, 999999),
                    'issue_date'  => now()->subYear()->toDateString(),
                    'expiry_date' => now()->addYears(2)->toDateString(),
                    'ocr_accuracy'=> $visaPath ? 98.5 : 0.0,
                    'file_path'   => $visaPath,
                ]);

                return $worker;
            });

            $result->load(['category', 'skills', 'documents']);

            return response()->json([
                'success' => true,
                'message' => 'Worker registered and authenticated successfully.',
                'data'    => ['worker' => $result, 'token' => $apiToken]
            ], 201);

        } catch (\Exception $e) {
            logger()->error('Worker Registration Failure: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'An error occurred during worker registration. Please try again.',
                'error'   => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
            ], 500);
        }
    }

    /**
     * Authenticate a worker and return a secure Bearer token.
     */
    public function login(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'phone'    => 'required_without:email|nullable|string',
            'email'    => 'required_without:phone|nullable|email',
            'password' => 'required|string',
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation error.',
                'errors'  => $validator->errors()
            ], 422);
        }

        try {
            $worker = $request->phone
                ? Worker::where('phone', $request->phone)->first()
                : Worker::where('email', $request->email)->first();

            if (!$worker || !Hash::check($request->password, $worker->password)) {
                return response()->json([
                    'success' => false,
                    'message' => 'Invalid credentials.'
                ], 401);
            }

            $apiToken = Str::random(80);
            $worker->update(['api_token' => $apiToken]);

            return response()->json([
                'success' => true,
                'message' => 'Worker logged in successfully.',
                'data'    => [
                    'worker' => $worker->load(['category', 'skills', 'documents']),
                    'token'  => $apiToken
                ]
            ], 200);

        } catch (\Exception $e) {
            logger()->error('Worker Login Failure: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'An error occurred during login. Please try again.',
                'error'   => app()->environment('local') ? $e->getMessage() : 'Internal Server Error'
            ], 500);
        }
    }
}
