<?php

// Public JSON API for customer account auth in the CurryPot ordering PWA.
// Uses distinct session keys (customer_id, customer_name, customer_phone) so it never
// collides with the admin panel's Auth session (user_id, role_id, etc) — same PHP session,
// separate namespace, no conflict even if both are open in the same browser.
class CustomerAuthController extends Controller
{
    private function jsonInput(): array
    {
        $raw = file_get_contents('php://input');
        $data = json_decode($raw, true);
        return is_array($data) ? $data : [];
    }

    public function register(): void
    {
        $body = $this->jsonInput();
        $name = trim($body['name'] ?? '');
        $phone = trim($body['phone'] ?? '');
        $password = (string) ($body['password'] ?? '');
        $email = trim($body['email'] ?? '') ?: null;

        if ($name === '' || $phone === '' || $password === '') {
            $this->json(['success' => false, 'message' => 'Name, phone, and password are required.'], 422);
            return;
        }
        if (strlen($password) < 6) {
            $this->json(['success' => false, 'message' => 'Password must be at least 6 characters.'], 422);
            return;
        }

        $customerModel = new Customer();
        $result = $customerModel->register($name, $phone, $password, $email);
        if (!$result['success']) {
            $this->json(['success' => false, 'message' => $result['message']], 422);
            return;
        }

        $customer = $customerModel->find($result['customer_id']);
        $this->startCustomerSession($customer);
        $this->json(['success' => true, 'customer' => $this->publicCustomer($customer)]);
    }

    public function login(): void
    {
        $body = $this->jsonInput();
        $phone = trim($body['phone'] ?? '');
        $password = (string) ($body['password'] ?? '');

        if ($phone === '' || $password === '') {
            $this->json(['success' => false, 'message' => 'Please enter your phone number and password.'], 422);
            return;
        }

        $customerModel = new Customer();
        $customer = $customerModel->verifyLogin($phone, $password);
        if (!$customer) {
            $this->json(['success' => false, 'message' => 'Incorrect phone number or password.'], 401);
            return;
        }

        $this->startCustomerSession($customer);
        $this->json(['success' => true, 'customer' => $this->publicCustomer($customer)]);
    }

    public function logout(): void
    {
        unset($_SESSION['customer_id'], $_SESSION['customer_name'], $_SESSION['customer_phone']);
        $this->json(['success' => true]);
    }

    public function me(): void
    {
        if (empty($_SESSION['customer_id'])) {
            $this->json(['success' => true, 'loggedIn' => false]);
            return;
        }
        $customerModel = new Customer();
        $customer = $customerModel->find((int) $_SESSION['customer_id']);
        if (!$customer) {
            unset($_SESSION['customer_id'], $_SESSION['customer_name'], $_SESSION['customer_phone']);
            $this->json(['success' => true, 'loggedIn' => false]);
            return;
        }
        $customerModel->touchLastActive((int) $customer['id']);
        $stats = $customerModel->getStats((int) $customer['id']);
        $this->json([
            'success'  => true,
            'loggedIn' => true,
            'customer' => $this->publicCustomer($customer),
            'stats'    => ['order_count' => (int) $stats['order_count'], 'total_spent' => (float) $stats['total_spent']],
        ]);
    }

    public function changePassword(): void
    {
        if (empty($_SESSION['customer_id'])) {
            $this->json(['success' => false, 'message' => 'Please log in first.'], 401);
            return;
        }
        $body = $this->jsonInput();
        $current = (string) ($body['current_password'] ?? '');
        $new = (string) ($body['new_password'] ?? '');

        if ($current === '' || $new === '') {
            $this->json(['success' => false, 'message' => 'Please fill in both password fields.'], 422);
            return;
        }
        if (strlen($new) < 6) {
            $this->json(['success' => false, 'message' => 'New password must be at least 6 characters.'], 422);
            return;
        }

        $customerModel = new Customer();
        $result = $customerModel->changePassword((int) $_SESSION['customer_id'], $current, $new);
        if (!$result['success']) {
            $this->json($result, 422);
            return;
        }
        $this->json(['success' => true]);
    }

    public function updateProfile(): void
    {
        if (empty($_SESSION['customer_id'])) {
            $this->json(['success' => false, 'message' => 'Please log in first.'], 401);
            return;
        }
        $body = $this->jsonInput();
        $name = trim($body['name'] ?? '');
        $email = trim($body['email'] ?? '') ?: null;
        $address = trim($body['address'] ?? '') ?: null;
        $dateOfBirth = trim($body['date_of_birth'] ?? '') ?: null;

        $customerModel = new Customer();
        try {
            $result = $customerModel->updateProfile((int) $_SESSION['customer_id'], $name, $email, $address, $dateOfBirth);
        } catch (\Throwable $e) {
            $this->json(['success' => false, 'message' => 'Server error saving profile. If this keeps happening, the "date_of_birth"/"profile_pic_path" columns may be missing — run migration 008.'], 500);
            return;
        }
        if (!$result['success']) {
            $this->json($result, 422);
            return;
        }

        $_SESSION['customer_name'] = $name;
        $customer = $customerModel->find((int) $_SESSION['customer_id']);
        $this->json(['success' => true, 'customer' => $this->publicCustomer($customer)]);
    }

    public function uploadProfilePic(): void
    {
        if (empty($_SESSION['customer_id'])) {
            $this->json(['success' => false, 'message' => 'Please log in first.'], 401);
            return;
        }
        $body = $this->jsonInput();
        $base64Data = $body['image_base64'] ?? '';

        if (!preg_match('/^data:image\/(png|jpe?g|webp);base64,(.+)$/', $base64Data, $matches)) {
            $this->json(['success' => false, 'message' => 'Invalid image format.'], 422);
            return;
        }
        $ext = $matches[1] === 'jpeg' ? 'jpg' : $matches[1];
        $binary = base64_decode($matches[2]);
        if ($binary === false || strlen($binary) > 4 * 1024 * 1024) {
            $this->json(['success' => false, 'message' => 'Image must be under 4MB.'], 422);
            return;
        }

        $uploadDir = ROOT_PATH . '/public/uploads/customer_profiles/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        $filename = 'customer_' . $_SESSION['customer_id'] . '_' . time() . '.' . $ext;
        file_put_contents($uploadDir . $filename, $binary);

        $customerModel = new Customer();
        try {
            $customerModel->updateProfilePic((int) $_SESSION['customer_id'], 'uploads/customer_profiles/' . $filename);
        } catch (\Throwable $e) {
            $this->json(['success' => false, 'message' => 'Server error saving photo. If this keeps happening, the "profile_pic_path" column may be missing — run migration 008.'], 500);
            return;
        }

        $customer = $customerModel->find((int) $_SESSION['customer_id']);
        $this->json(['success' => true, 'customer' => $this->publicCustomer($customer)]);
    }

    public function forgotPassword(): void
    {
        $body = $this->jsonInput();
        $phone = trim($body['phone'] ?? '');
        if ($phone === '') {
            $this->json(['success' => false, 'message' => 'Please enter your phone number.'], 422);
            return;
        }

        $customerModel = new Customer();
        $token = $customerModel->createResetToken($phone);

        // NOTE: no SMS/email gateway is wired up here yet, so for now the reset code is returned
        // directly in the API response so this flow is testable end-to-end locally. Once an SMS
        // gateway (e.g. SMSlenz, as used elsewhere) is connected, replace this with an actual send
        // and stop returning `debug_token` in the response.
        $this->json([
            'success' => true,
            'message' => $token
                ? 'A reset code has been generated.'
                : 'If an account exists for this number, a reset code has been generated.',
            'debug_token' => $token, // TEMPORARY — remove once SMS sending is wired up
        ]);
    }

    public function resetPassword(): void
    {
        $body = $this->jsonInput();
        $token = trim($body['token'] ?? '');
        $newPassword = (string) ($body['password'] ?? '');

        if ($token === '' || $newPassword === '') {
            $this->json(['success' => false, 'message' => 'Missing reset code or new password.'], 422);
            return;
        }
        if (strlen($newPassword) < 6) {
            $this->json(['success' => false, 'message' => 'Password must be at least 6 characters.'], 422);
            return;
        }

        $customerModel = new Customer();
        $ok = $customerModel->resetPasswordWithToken($token, $newPassword);
        if (!$ok) {
            $this->json(['success' => false, 'message' => 'This reset code is invalid or has expired.'], 422);
            return;
        }
        $this->json(['success' => true]);
    }

    private function startCustomerSession(array $customer): void
    {
        $_SESSION['customer_id']    = (int) $customer['id'];
        $_SESSION['customer_name']  = $customer['full_name'];
        $_SESSION['customer_phone'] = $customer['phone'];
    }

    private function publicCustomer(array $customer): array
    {
        return [
            'id'              => (int) $customer['id'],
            'name'            => $customer['full_name'],
            'phone'           => $customer['phone'],
            'email'           => $customer['email'] ?? null,
            'address'         => $customer['address'] ?? null,
            'date_of_birth'   => $customer['date_of_birth'] ?? null,
            'profile_pic_url' => !empty($customer['profile_pic_path']) ? BASE_URL . '/' . $customer['profile_pic_path'] : null,
        ];
    }
}
