<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Customer;
use App\Mail\VerifyCustomerEmailCodeMail;
use App\Mail\ResetCustomerPasswordMail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    /**
     * Admin Login
     * POST /api/v1/login
     */
    public function login(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        $user = User::where('email', $request->email)->first();

        if (!$user || !Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['As credenciais fornecidas estão incorretas.'],
            ]);
        }

        if (!$user->is_active) {
            return response()->json([
                'success' => false,
                'message' => 'Usuário inativo. Entre em contato com o administrador.',
            ], 403);
        }

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

        $token = $user->createToken('api-token')->plainTextToken;

        return response()->json([
            'success' => true,
            'message' => 'Login realizado com sucesso',
            'data' => [
                'user' => $user->load('store'),
                'token' => $token,
                'token_type' => 'Bearer',
            ],
        ]);
    }

    /**
     * Customer Login (Phone/Password)
     * POST /api/v1/customer/login
     */
    public function customerLogin(Request $request)
    {
        Log::info('📥 Customer Login - Dados recebidos:', [
            'phone' => $request->phone,
            'has_password' => !empty($request->password),
        ]);

        $request->validate([
            'phone' => 'required|string',
            'password' => 'required|string',
        ], [
            'phone.required' => 'O telefone é obrigatório.',
            'password.required' => 'A senha é obrigatória.',
        ]);

        // Normalize and search by phone OR email
        $identifier = trim($request->phone);
        $rawPhone   = preg_replace('/\s+/', '', $identifier);
        $candidate  = str_starts_with($rawPhone, '+') ? $rawPhone : '+' . $rawPhone;
        $stripped   = preg_replace('/^\+258/', '', $candidate);

        $customer = Customer::where('email', strtolower($identifier))
            ->orWhere('phone', $rawPhone)
            ->orWhere('phone', $candidate)
            ->orWhere('phone', '+258' . $stripped)
            ->first();

        if (!$customer || !Hash::check($request->password, $customer->password)) {
            Log::warning('❌ Credenciais inválidas no login do cliente', [
                'phone' => $request->phone,
                'customer_exists' => !is_null($customer),
            ]);

            throw ValidationException::withMessages([
                'phone' => ['As credenciais fornecidas estão incorretas.'],
            ]);
        }

        if (!$customer->is_active) {
            return response()->json([
                'success' => false,
                'message' => 'Conta inativa. Entre em contato com o suporte.',
            ], 403);
        }

        $customer->update([
            'last_login_at' => now(),
        ]);

        $token = $customer->createToken('customer-token')->plainTextToken;

        return response()->json([
            'success' => true,
            'message' => 'Login realizado com sucesso',
            'data' => [
                'user' => $this->transformCustomer($customer),
                'token' => $token,
                'token_type' => 'Bearer',
            ],
        ]);
    }

    /**
     * Customer Register
     * POST /api/v1/customer/register
     */
    public function customerRegister(Request $request)
    {
        Log::info('📥 Customer Register - Dados recebidos:', $request->except([
            'password',
            'password_confirmation',
        ]));

        $request->validate([
            'name' => 'required|string|max:255',
            'phone' => 'required|string|unique:customers,phone',
            'email' => 'required|email|unique:customers,email',
            'password' => 'required|string|min:6|confirmed',
            'terms_accepted' => 'required|boolean|accepted',
        ], [
            'name.required' => 'O nome é obrigatório.',
            'phone.required' => 'O telefone é obrigatório.',
            'phone.unique' => 'Este telefone já está cadastrado.',
            'email.required' => 'O email é obrigatório.',
            'email.email' => 'Email inválido.',
            'email.unique' => 'Este email já está cadastrado.',
            'password.required' => 'A senha é obrigatória.',
            'password.min' => 'A senha deve ter pelo menos 6 caracteres.',
            'password.confirmed' => 'As senhas não conferem.',
            'terms_accepted.required' => 'Você deve aceitar os termos de uso.',
            'terms_accepted.accepted' => 'Você deve aceitar os termos de uso.',
        ]);

        DB::beginTransaction();

        try {
            $nameParts = preg_split('/\s+/', trim($request->name), 2);
            $firstName = $nameParts[0] ?? '';
            $lastName = $nameParts[1] ?? '';

            $verificationCode = (string) random_int(100000, 999999);

            $normalizedPhone = preg_replace('/\s+/', '', $request->phone);
            if (!str_starts_with($normalizedPhone, '+')) {
                $normalizedPhone = '+' . $normalizedPhone;
            }

            $customer = Customer::create([
                'first_name' => $firstName,
                'last_name' => $lastName,
                'phone' => $normalizedPhone,
                'email' => strtolower(trim($request->email)),
                'password' => Hash::make($request->password),
                'is_active' => true,
                'email_verification_code' => $verificationCode,
                'email_verification_expires_at' => now()->addMinutes(10),
            ]);

            Mail::to($customer->email)->send(
                new VerifyCustomerEmailCodeMail($customer, $verificationCode)
            );

            DB::commit();

            Log::info('✅ Cliente criado com sucesso, aguardando verificação', [
                'customer_id' => $customer->id,
                'email' => $customer->email,
                'phone' => $customer->phone,
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Conta criada com sucesso. Enviámos um código de verificação para o seu email.',
                'data' => [
                    'requires_verification' => true,
                    'email' => $customer->email,
                    'phone' => $customer->phone,
                ],
            ], 201);
        } catch (\Throwable $e) {
            DB::rollBack();

            Log::error('❌ Erro ao registrar cliente', [
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
            ]);

            return response()->json([
                'success' => false,
                'message' => 'Erro ao criar conta.',
                'error' => config('app.debug') ? $e->getMessage() : null,
            ], 500);
        }
    }

    /**
     * Verify customer email
     * POST /api/v1/customer/email/verify
     */
    public function verifyCustomerEmail(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'code' => 'required|string|size:6',
        ], [
            'email.required' => 'O email é obrigatório.',
            'code.required' => 'O código é obrigatório.',
            'code.size' => 'O código deve ter 6 dígitos.',
        ]);

        $customer = Customer::where('email', strtolower(trim($request->email)))->first();

        if (!$customer) {
            throw ValidationException::withMessages([
                'email' => ['Conta não encontrada.'],
            ]);
        }

        if (!is_null($customer->email_verified_at)) {
            $token = $customer->createToken('customer-token')->plainTextToken;

            return response()->json([
                'success' => true,
                'message' => 'Email já verificado.',
                'data' => [
                    'user' => $this->transformCustomer($customer),
                    'token' => $token,
                    'token_type' => 'Bearer',
                ],
            ]);
        }

        if (
            $customer->email_verification_code !== $request->code ||
            !$customer->email_verification_expires_at ||
            now()->greaterThan($customer->email_verification_expires_at)
        ) {
            throw ValidationException::withMessages([
                'code' => ['Código inválido ou expirado.'],
            ]);
        }

        $customer->update([
            'email_verified_at' => now(),
            'email_verification_code' => null,
            'email_verification_expires_at' => null,
        ]);

        $token = $customer->createToken('customer-token')->plainTextToken;

        return response()->json([
            'success' => true,
            'message' => 'Email verificado com sucesso.',
            'data' => [
                'user' => $this->transformCustomer($customer->fresh()),
                'token' => $token,
                'token_type' => 'Bearer',
            ],
        ]);
    }

    /**
     * Resend customer email verification code
     * POST /api/v1/customer/email/resend
     */
    public function resendCustomerVerificationCode(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
        ], [
            'email.required' => 'O email é obrigatório.',
        ]);

        $customer = Customer::where('email', strtolower(trim($request->email)))->first();

        if (!$customer) {
            throw ValidationException::withMessages([
                'email' => ['Conta não encontrada.'],
            ]);
        }

        if (!is_null($customer->email_verified_at)) {
            return response()->json([
                'success' => false,
                'message' => 'Este email já foi verificado.',
            ], 422);
        }

        $verificationCode = (string) random_int(100000, 999999);

        $customer->update([
            'email_verification_code' => $verificationCode,
            'email_verification_expires_at' => now()->addMinutes(10),
        ]);

        Mail::to($customer->email)->send(
            new VerifyCustomerEmailCodeMail($customer, $verificationCode)
        );

        return response()->json([
            'success' => true,
            'message' => 'Código reenviado com sucesso.',
        ]);
    }

    /**
     * Forgot customer password
     * POST /api/v1/customer/forgot-password
     */
    public function customerForgotPassword(Request $request)
    {
        $request->validate([
            'identifier' => 'required|string',
        ], [
            'identifier.required' => 'Informe o telefone ou email.',
        ]);

        $identifier = trim($request->identifier);

        $customer = Customer::where('phone', $identifier)
            ->orWhere('email', strtolower($identifier))
            ->first();

        if (!$customer || empty($customer->email)) {
            return response()->json([
                'success' => true,
                'message' => 'Se existir uma conta associada, enviámos instruções para o email cadastrado.',
            ]);
        }

        $plainToken = Str::random(64);

        $customer->update([
            'password_reset_token' => hash('sha256', $plainToken),
            'password_reset_expires_at' => now()->addMinutes(30),
        ]);

        Mail::to($customer->email)->send(
            new ResetCustomerPasswordMail($customer, $plainToken)
        );

        return response()->json([
            'success' => true,
            'message' => 'Se existir uma conta associada, enviámos instruções para o email cadastrado.',
        ]);
    }

    /**
     * Reset customer password
     * POST /api/v1/customer/reset-password
     */
    public function customerResetPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'token' => 'required|string',
            'password' => 'required|string|min:6|confirmed',
        ], [
            'email.required' => 'O email é obrigatório.',
            'token.required' => 'O token é obrigatório.',
            'password.required' => 'A nova senha é obrigatória.',
            'password.min' => 'A senha deve ter pelo menos 6 caracteres.',
            'password.confirmed' => 'As senhas não conferem.',
        ]);

        $customer = Customer::where('email', strtolower(trim($request->email)))->first();

        if (
            !$customer ||
            !$customer->password_reset_token ||
            !$customer->password_reset_expires_at ||
            now()->greaterThan($customer->password_reset_expires_at) ||
            !hash_equals($customer->password_reset_token, hash('sha256', $request->token))
        ) {
            throw ValidationException::withMessages([
                'token' => ['Token inválido ou expirado.'],
            ]);
        }

        $customer->update([
            'password' => Hash::make($request->password),
            'password_reset_token' => null,
            'password_reset_expires_at' => null,
        ]);

        return response()->json([
            'success' => true,
            'message' => 'Senha redefinida com sucesso.',
        ]);
    }

    /**
     * Logout
     * POST /api/v1/logout
     */
    public function logout(Request $request)
    {
        $request->user()->currentAccessToken()?->delete();

        return response()->json([
            'success' => true,
            'message' => 'Logout realizado com sucesso',
        ]);
    }

    /**
     * Customer Logout
     * POST /api/v1/customer/logout
     */
    public function customerLogout(Request $request)
    {
        $request->user()->currentAccessToken()?->delete();

        return response()->json([
            'success' => true,
            'message' => 'Logout realizado com sucesso',
        ]);
    }

    /**
     * Get authenticated user
     * GET /api/v1/me
     */
    public function me(Request $request)
    {
        return response()->json([
            'success' => true,
            'data' => $request->user()->load('store'),
        ]);
    }

    /**
     * Get authenticated customer
     * GET /api/v1/customer/me
     */
    public function customerMe(Request $request)
    {
        /** @var \App\Models\Customer $customer */
        $customer = $request->user();

        return response()->json([
            'success' => true,
            'data' => [
                'user' => $this->transformCustomer($customer),
            ],
        ]);
    }

    /**
     * Update profile
     * PUT /api/v1/profile
     */
    public function updateProfile(Request $request)
    {
        $user = $request->user();

        $validated = $request->validate([
            'name'                  => 'sometimes|string|max:255',
            'phone'                 => 'sometimes|string|max:20',
            'avatar'                => 'sometimes|string|max:255',
            'current_password'      => 'required_with:new_password|string',
            'new_password'          => 'nullable|string|min:8|confirmed',
            'new_password_confirmation' => 'nullable|string',
        ]);

        if (!empty($validated['new_password'])) {
            if (!Hash::check($validated['current_password'], $user->password)) {
                return response()->json([
                    'success' => false,
                    'message' => 'A palavra-passe atual está incorreta',
                    'errors'  => ['current_password' => ['A palavra-passe atual está incorreta']],
                ], 422);
            }
            $user->update(['password' => Hash::make($validated['new_password'])]);
        }

        $profileData = array_filter(
            array_intersect_key($validated, array_flip(['name', 'phone', 'avatar'])),
            fn($v) => $v !== null
        );

        if (!empty($profileData)) {
            $user->update($profileData);
        }

        return response()->json([
            'success' => true,
            'message' => 'Perfil atualizado com sucesso',
            'data'    => $user->fresh(),
        ]);
    }

    /**
     * Update customer profile
     * PUT /api/v1/customer/profile
     */
    public function updateCustomerProfile(Request $request)
    {
        /** @var \App\Models\Customer $customer */
        $customer = $request->user();

        $validated = $request->validate([
            'first_name' => 'sometimes|string|max:255',
            'last_name' => 'sometimes|string|max:255',
            'email' => 'sometimes|email|unique:customers,email,' . $customer->id,
            'phone' => 'sometimes|string|unique:customers,phone,' . $customer->id,
            'avatar' => 'sometimes|string|max:255',
        ]);

        if (array_key_exists('email', $validated) && $validated['email'] !== $customer->email) {
            $validated['email_verified_at'] = null;
            $validated['email_verification_code'] = (string) random_int(100000, 999999);
            $validated['email_verification_expires_at'] = now()->addMinutes(10);
        }

        $customer->update($validated);

        if (isset($validated['email']) && !empty($validated['email'])) {
            Mail::to($customer->email)->send(
                new VerifyCustomerEmailCodeMail($customer->fresh(), $customer->fresh()->email_verification_code)
            );
        }

        return response()->json([
            'success' => true,
            'message' => 'Perfil atualizado com sucesso.',
            'data' => [
                'user' => $this->transformCustomer($customer->fresh()),
            ],
        ]);
    }

    /**
     * Normaliza o retorno do cliente
     */
    private function transformCustomer(Customer $customer): array
    {
        return [
            'id' => $customer->id,
            'name' => trim($customer->first_name . ' ' . $customer->last_name),
            'first_name' => $customer->first_name,
            'last_name' => $customer->last_name,
            'email' => $customer->email,
            'phone' => $customer->phone,
            'avatar' => $customer->avatar,
            'email_verified' => !is_null($customer->email_verified_at),
            'is_active' => (bool) $customer->is_active,
            'accepts_marketing' => (bool) $customer->accepts_marketing,
            'total_orders' => (int) $customer->total_orders,
            'total_spent' => $customer->total_spent,
        ];
    }
}