<?php

namespace App\Http\Controllers\Api\V1;

use App\Http\Controllers\Api\V1\Concerns\RespondsWithApi;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\OtpService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

class AuthController extends Controller
{
    use RespondsWithApi;

    public function sendOtp(Request $request, OtpService $otpService)
    {
        $data = $request->validate([
            'phone' => ['required', 'string', 'max:32'],
            'purpose' => ['nullable', 'string', 'max:40'],
        ]);

        return $this->ok($otpService->send($data['phone'], $data['purpose'] ?? 'login', $request->ip()), 'OTP sent.');
    }

    public function verifyOtp(Request $request, OtpService $otpService)
    {
        $data = $request->validate([
            'phone' => ['required', 'string', 'max:32'],
            'otp' => ['required', 'string', 'min:4', 'max:8'],
            'name' => ['nullable', 'string', 'max:120'],
            'purpose' => ['nullable', 'string', 'max:40'],
            'device_type' => ['nullable', 'string', 'max:20'],
            'device_token' => ['nullable', 'string', 'max:255'],
        ]);

        if (! $otpService->verify($data['phone'], $data['otp'], $data['purpose'] ?? 'login')) {
            return $this->fail('OTP_INVALID', 'OTP invalid or expired.', [], 422);
        }

        $user = User::firstOrCreate(
            ['phone' => $data['phone']],
            [
                'name' => $data['name'] ?? 'Customer',
                'phone_country_code' => '+91',
                'role' => 'customer',
                'status' => 'active',
            ]
        );

        $user->forceFill([
            'name' => $data['name'] ?? $user->name,
            'last_login_at' => now(),
        ])->save();

        if (! empty($data['device_token'])) {
            DB::table('user_devices')->insert([
                'user_id' => $user->id,
                'device_type' => $data['device_type'] ?? 'android',
                'device_token' => $data['device_token'],
                'last_seen_at' => now(),
                'created_at' => now(),
                'updated_at' => now(),
            ]);
        }

        $token = $user->createToken($data['device_type'] ?? 'mobile')->plainTextToken;

        return $this->ok([
            'token_type' => 'Bearer',
            'token' => $token,
            'user' => $user,
        ], 'Login successful.');
    }

    public function adminLogin(Request $request)
    {
        $data = $request->validate([
            'login' => ['required', 'string', 'max:150'],
            'password' => ['required', 'string', 'max:120'],
        ]);

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

        if (! $user || ! $user->isAdmin() || ! Hash::check($data['password'], $user->password ?? '')) {
            return $this->fail('ADMIN_LOGIN_FAILED', 'Invalid admin credentials.', [], 401);
        }

        if ($user->status !== 'active') {
            return $this->fail('ADMIN_INACTIVE', 'Admin account is not active.', [], 423);
        }

        $user->forceFill(['last_login_at' => now()])->save();

        return $this->ok([
            'token_type' => 'Bearer',
            'token' => $user->createToken('admin-panel')->plainTextToken,
            'user' => $user,
        ], 'Admin login successful.');
    }

    public function me(Request $request)
    {
        return $this->ok($request->user());
    }

    public function updateMe(Request $request)
    {
        $data = $request->validate([
            'name' => ['nullable', 'string', 'max:120'],
            'email' => ['nullable', 'email', 'max:150'],
            'gender' => ['nullable', 'string', 'max:32'],
            'date_of_birth' => ['nullable', 'date'],
        ]);

        $request->user()->update($data);

        return $this->ok($request->user()->fresh(), 'Profile updated.');
    }

    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()?->delete();

        return $this->ok([], 'Logged out.');
    }

    public function logoutAll(Request $request)
    {
        $request->user()->tokens()->delete();

        return $this->ok([], 'All sessions logged out.');
    }

    public function registerDevice(Request $request)
    {
        $data = $request->validate([
            'device_type' => ['required', 'string', 'max:20'],
            'device_token' => ['required', 'string', 'max:255'],
            'app_version' => ['nullable', 'string', 'max:40'],
            'os_version' => ['nullable', 'string', 'max:80'],
        ]);

        $data['user_id'] = $request->user()->id;
        $data['last_seen_at'] = now();
        $data['created_at'] = now();
        $data['updated_at'] = now();

        $id = DB::table('user_devices')->insertGetId($data);

        return $this->ok(DB::table('user_devices')->where('id', $id)->first(), 'Device registered.', [], 201);
    }

    public function deleteAccountRequest(Request $request)
    {
        $data = $request->validate([
            'reason' => ['nullable', 'string', 'max:500'],
        ]);

        $id = DB::table('account_deletion_requests')->insertGetId([
            'user_id' => $request->user()->id,
            'phone' => $request->user()->phone,
            'status' => 'requested',
            'reason' => $data['reason'] ?? null,
            'requested_at' => now(),
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return $this->ok(DB::table('account_deletion_requests')->where('id', $id)->first(), 'Account deletion request submitted.');
    }
}
