<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use App\Models\User;
use OpenApi\Attributes as OA;

class AuthController extends Controller
{
    #[OA\Post(
        path: "/api/auth/login",
        tags: ["Authentication"],
        summary: "Login with email and password"
    )]
    #[OA\RequestBody(
        required: true,
        content: new OA\JsonContent(
            required: ["email", "password"],
            properties: [
                new OA\Property(property: "email", type: "string", format: "email", example: "user@example.com"),
                new OA\Property(property: "password", type: "string", format: "password", example: "password")
            ]
        )
    )]
    #[OA\Response(
        response: 200,
        description: "Login successful",
        content: new OA\JsonContent(
            properties: [
                new OA\Property(property: "success", type: "boolean", example: true),
                new OA\Property(property: "message", type: "string", example: "Login successful"),
                new OA\Property(
                    property: "data",
                    type: "object",
                    properties: [
                        new OA\Property(property: "access_token", type: "string"),
                        new OA\Property(property: "user", type: "object")
                    ]
                )
            ]
        )
    )]
    #[OA\Response(
        response: 401,
        description: "Invalid credentials"
    )]
    public function login(Request $request)
    {
        $data = $request->validate([
            'email' => ['required','email'],
            'password' => ['required'],
        ]);

        $user = User::where('email', $data['email'])->first();
        if (! $user || ! Hash::check($data['password'], $user->password_hash)) {
            return response()->json(['success' => false, 'message' => 'اطلاعات ورود نامعتبر است'], 401);
        }

        // create token
        $token = bin2hex(random_bytes(40));
        $expires = now()->addDays(30);

        DB::table('api_tokens')->insert([
            'user_id' => $user->id,
            'token' => $token,
            'expires_at' => $expires,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'ورود موفق',
            'data' => [
                'access_token' => $token,
                'user' => $this->formatUser($user),
            ]
        ]);
    }

    #[OA\Post(
        path: "/api/auth/send-otp",
        tags: ["Authentication"],
        summary: "Send OTP code"
    )]
    #[OA\RequestBody(
        required: true,
        content: new OA\JsonContent(
            required: ["email_or_phone", "type"],
            properties: [
                new OA\Property(property: "email_or_phone", type: "string", example: "user@example.com"),
                new OA\Property(property: "type", type: "string", enum: ["register", "login", "reset_password"])
            ]
        )
    )]
    #[OA\Response(
        response: 200,
        description: "OTP sent"
    )]
    #[OA\Response(
        response: 404,
        description: "User not found"
    )]
    public function sendOtp(Request $request)
    {
        $data = $request->validate([
            'email_or_phone' => ['required','string'],
            'type' => ['required','in:register,login,reset_password'],
        ]);

        $identifier = trim($data['email_or_phone']);
        $isPhone = preg_match('/^[0-9+\s\-]{8,15}$/', $identifier);

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

        // Auto-register new users so that "ورود یا ثبت‌نام" works for first-time users.
        if (! $user) {
            $referralCode = strtoupper(substr(bin2hex(random_bytes(4)), 0, 8));
            $user = User::create([
                'phone'         => $isPhone ? $identifier : null,
                'email'         => $isPhone ? null : $identifier,
                'full_name'     => null,
                'password_hash' => null,
                'status'        => 'active',
                'phone_verified'=> false,
                'email_verified'=> false,
                'wallet_balance'=> 0,
                'points'        => 0,
                'level'         => 1,
                'experience'    => 0,
                'referral_code' => $referralCode,
                'created_at'    => now(),
                'updated_at'    => now(),
            ]);
        }

        $code = str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);

        DB::table('otp_codes')->insert([
            'user_id'    => $user->id,
            'email'      => $user->email,
            'phone'      => $user->phone,
            'code'       => $code,
            'type'       => $data['type'],
            'expires_at' => now()->addMinutes(10),
            'verified'   => false,
            'ip_address' => $request->ip(),
            'created_at' => now(),
        ]);

        // NOTE: In production send via SMS/Email. For now we return a success message.
        // For dev convenience, include the OTP code in the response so the Flutter app can be tested.
        $responseData = ['success' => true, 'message' => 'کد تأیید ارسال شد'];
        if (app()->isLocal()) {
            $responseData['dev_otp'] = $code;
        }
        return response()->json($responseData);
    }

    #[OA\Post(
        path: "/api/auth/verify-otp",
        tags: ["Authentication"],
        summary: "Verify OTP code"
    )]
    #[OA\RequestBody(
        required: true,
        content: new OA\JsonContent(
            required: ["email_or_phone", "code", "type"],
            properties: [
                new OA\Property(property: "email_or_phone", type: "string", example: "user@example.com"),
                new OA\Property(property: "code", type: "string", example: "123456"),
                new OA\Property(property: "type", type: "string", enum: ["register", "login", "reset_password"])
            ]
        )
    )]
    #[OA\Response(
        response: 200,
        description: "OTP Verified",
        content: new OA\JsonContent(
            properties: [
                new OA\Property(property: "success", type: "boolean", example: true),
                new OA\Property(property: "message", type: "string"),
                new OA\Property(
                    property: "data",
                    type: "object",
                    properties: [
                        new OA\Property(property: "access_token", type: "string"),
                        new OA\Property(property: "user", type: "object")
                    ]
                )
            ]
        )
    )]
    #[OA\Response(
        response: 400,
        description: "Invalid OTP"
    )]
    public function verifyOtp(Request $request)
    {
        $data = $request->validate([
            'email_or_phone' => ['required','string'],
            'code' => ['required','string'],
            'type' => ['required','in:register,login,reset_password'],
        ]);

        $user = User::where('email', $data['email_or_phone'])
            ->orWhere('phone', $data['email_or_phone'])
            ->first();

        if (! $user) {
            return response()->json(['success' => false, 'message' => 'کاربر یافت نشد'], 404);
        }

        $otp = DB::table('otp_codes')
            ->where('user_id', $user->id)
            ->where('code', $data['code'])
            ->where('type', $data['type'])
            ->where('verified', false)
            ->where('expires_at', '>', now())
            ->latest()
            ->first();

        if (! $otp) {
            return response()->json(['success' => false, 'message' => 'کد OTP نامعتبر یا منقضی است'], 400);
        }

        DB::table('otp_codes')->where('id', $otp->id)->update(['verified' => true]);

        // create token
        $token = bin2hex(random_bytes(40));
        $expires = now()->addDays(30);

        DB::table('api_tokens')->insert([
            'user_id' => $user->id,
            'token' => $token,
            'expires_at' => $expires,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'message' => 'کد تأیید صحیح است',
            'data' => [
                'access_token' => $token,
                'user' => $this->formatUser($user),
            ]
        ]);
    }

    /**
     * Authenticate using a personal access token (printed/distributed to the
     * user). Looks up the token in the `api_tokens` table directly — no
     * password / OTP is required. This satisfies the "private token login"
     * requirement of Hooshi.
     */
    #[OA\Post(
        path: "/api/auth/token-login",
        tags: ["Authentication"],
        summary: "Login with a personal access token (8–12 chars)"
    )]
    public function tokenLogin(Request $request)
    {
        $data = $request->validate([
            'token' => ['required','string','min:6','max:64'],
        ]);

        $token = trim($data['token']);

        $tokenRecord = DB::table('api_tokens')
            ->where('token', $token)
            ->where('expires_at', '>', now())
            ->first();

        if (! $tokenRecord) {
            return response()->json(['success' => false, 'message' => 'توکن نامعتبر یا منقضی شده است'], 401);
        }

        $user = User::find($tokenRecord->user_id);
        if (! $user || $user->status !== 'active') {
            return response()->json(['success' => false, 'message' => 'حساب کاربری در دسترس نیست'], 403);
        }

        // refresh last_login
        $user->update(['last_login' => now()]);

        return response()->json([
            'success' => true,
            'message' => 'ورود موفق با توکن',
            'data' => [
                'access_token' => $token,
                'user' => $this->formatUser($user),
            ]
        ]);
    }

    /**
     * Validate a token without consuming OTP — returns whether the supplied
     * bearer token is still active. Useful to bootstrap saved sessions.
     */
    public function validateToken(Request $request)
    {
        $token = preg_replace('/^Bearer\s+/i', '', $request->header('Authorization') ?: '');
        if (! $token) {
            return response()->json(['success' => false, 'valid' => false], 200);
        }

        $rec = DB::table('api_tokens')->where('token', $token)->where('expires_at', '>', now())->first();
        return response()->json(['success' => (bool) $rec, 'valid' => (bool) $rec]);
    }

    /**
     * Revoke the current token.
     */
    public function logout(Request $request)
    {
        $token = preg_replace('/^Bearer\s+/i', '', $request->header('Authorization') ?: '');
        if ($token) {
            DB::table('api_tokens')->where('token', $token)->delete();
        }
        return response()->json(['success' => true, 'message' => 'خروج موفق']);
    }

    protected function formatUser(User $user)
    {
        return [
            'id' => $user->id,
            'email' => $user->email,
            'phone' => $user->phone,
            'full_name' => $user->full_name,
            'avatar' => $user->avatar,
            'status' => $user->status,
            'email_verified' => (bool) $user->email_verified,
            'phone_verified' => (bool) $user->phone_verified,
            'wallet_balance' => (float) $user->wallet_balance,
            'points' => (int) $user->points,
            'level' => (int) $user->level,
            'experience' => (int) $user->experience,
            'referral_code' => $user->referral_code,
            'created_at' => $user->created_at,
        ];
    }
}
