<?php

declare(strict_types=1);

namespace App\Controllers\Api;

use App\Helpers\ActivityLogger;

final class AuthController extends BaseApiController
{
    // POST /api/v1/auth/register
    // Customer signup by phone (username). Collects name, phone, password, address.
    public function register(): void
    {
        $name    = trim((string)$this->post('name'));
        $phone   = trim((string)$this->post('phone'));
        $pass    = (string)$this->post('password');
        $address = trim((string)$this->post('address'));
        $lat     = $this->post('latitude')  !== '' ? (float)$this->post('latitude')  : null;
        $lng     = $this->post('longitude') !== '' ? (float)$this->post('longitude') : null;

        $digits = preg_replace('/\D/', '', $phone);
        if (strlen($name) < 2)      $this->fail('Name is required.');
        if (strlen($digits) < 7)    $this->fail('A valid phone number is required.');
        if (strlen($pass) < 6)      $this->fail('Password must be at least 6 characters.');

        // Phone is the username — must be unique among customers.
        $exists = $this->db->fetchValue(
            "SELECT u.id FROM users u JOIN roles r ON r.id = u.role_id
              WHERE u.phone = ? AND r.name = 'customer'", [$phone]);
        if ($exists) $this->fail('This phone number is already registered.');

        $roleId = (int)$this->db->fetchValue("SELECT id FROM roles WHERE name = 'customer'");
        $hash   = password_hash($pass, PASSWORD_BCRYPT, ['cost' => BCRYPT_COST]);
        // Synthetic email satisfies the NOT NULL UNIQUE column (email isn't collected).
        $email  = $digits . '@chineseclub.local';

        $userId = $this->db->insert('users', [
            'name'          => $name,
            'email'         => $email,
            'phone'         => $phone,
            'password_hash' => $hash,
            'role_id'       => $roleId,
            'is_active'     => 1,
        ]);
        $customerId = $this->db->insert('customers', ['user_id' => $userId]);

        // Save the signup address as the customer's default address.
        if ($address !== '') {
            $this->db->insert('customer_addresses', [
                'customer_id'  => $customerId,
                'label'        => 'Home',
                'address_line' => $address,
                'city'         => '',
                'latitude'     => $lat,
                'longitude'    => $lng,
                'is_default'   => 1,
            ]);
        }

        $token = $this->issueToken($userId, $this->post('device_id'));
        $this->ok(['token' => $token, 'name' => $name, 'email' => '', 'phone' => $phone],
            'Registered successfully.');
    }

    // POST /api/v1/auth/login   (phone is the username)
    public function login(): void
    {
        $phone = trim((string)$this->post('phone'));
        $pass  = (string)$this->post('password');

        $user = $this->db->fetchOne(
            "SELECT u.* FROM users u
               JOIN roles r ON r.id = u.role_id
              WHERE u.phone = ? AND u.is_active = 1 AND r.name = 'customer'",
            [$phone]
        );
        if (!$user || !password_verify($pass, $user['password_hash'])) {
            $this->fail('Invalid phone number or password.', 401);
        }

        $token = $this->issueToken($user['id'], $this->post('device_id'));
        try { ActivityLogger::log('login', 'Customer', $user['id'], $user['name'], 'API login'); } catch (\Throwable) {}
        $this->ok([
            'token' => $token,
            'name'  => $user['name'],
            'email' => '',
            'phone' => $user['phone'] ?? '',
        ], 'Login successful.');
    }

    // POST /api/v1/auth/logout
    public function logout(): void
    {
        $token = $this->bearerToken();
        if ($token) {
            $this->db->delete('api_tokens', ['token' => $token]);
        }
        $this->ok(null, 'Logged out.');
    }

    // GET /api/v1/auth/me
    public function me(): void
    {
        $user = $this->requireAuth();
        $cid  = $this->customerId($user);
        $orders = $cid > 0
            ? (int)$this->db->fetchValue(
                "SELECT COUNT(*) FROM orders WHERE customer_id = ?", [$cid])
            : 0;
        $this->ok([
            'name'         => $user['name'],
            'phone'        => $user['phone'] ?? '',
            'orders_count' => $orders,
            'is_first_order' => $orders === 0,
        ]);
    }

    // POST /api/v1/auth/profile
    public function updateProfile(): void
    {
        $user  = $this->requireAuth();
        $name  = trim((string)$this->post('name'));
        $phone = trim((string)$this->post('phone'));

        if (strlen($name) < 2) $this->fail('Name is required.');

        $this->db->update('users', ['name' => $name, 'phone' => $phone], ['id' => $user['id']]);
        $this->ok(['name' => $name, 'email' => $user['email'], 'phone' => $phone], 'Profile updated.');
    }

    // ── Token helper ──────────────────────────────────────────────────────────

    private function issueToken(int $userId, mixed $deviceId): string
    {
        // Revoke old tokens for this device
        if ($deviceId) {
            $this->db->fetchAll(
                "DELETE FROM api_tokens WHERE user_id = ? AND device = ?",
                [$userId, $deviceId]
            );
        }
        $token = bin2hex(random_bytes(32));
        $this->db->insert('api_tokens', [
            'user_id'    => $userId,
            'token'      => $token,
            'device'     => $deviceId ?: null,
            'expires_at' => date('Y-m-d H:i:s', strtotime('+30 days')),
        ]);
        return $token;
    }
}
