<?php

require_once BASE_PATH . '/app/models/Cart.php';
require_once BASE_PATH . '/app/models/CartItem.php';
require_once BASE_PATH . '/app/models/CustomerAddress.php';
require_once BASE_PATH . '/app/models/Order.php';

class CheckoutController
{
    private Cart $cartModel;
    private CartItem $cartItemModel;
    private CustomerAddress $addressModel;
    private Order $orderModel;

    public function __construct()
    {
        $this->cartModel =
            new Cart();

        $this->cartItemModel =
            new CartItem();

        $this->addressModel =
            new CustomerAddress();

        $this->orderModel =
            new Order();
    }

    // ========================================================
    // CHECKOUT PAGE
    // ========================================================

    public function index(): void
    {
        $this->requireCustomer();

        $customerId =
            (int)
            $_SESSION['user']['id'];

        $cart =
            $this->cartModel
                ->findByCustomerId(
                    $customerId
                );

        if (!$cart) {

            $this->redirectCart(
                'Giỏ hàng đang trống.'
            );
        }

        $items =
            $this->cartItemModel
                ->getItems(
                    (int) $cart['id']
                );

        if (empty($items)) {

            $this->redirectCart(
                'Giỏ hàng đang trống.'
            );
        }

        $subtotal = 0;

        foreach ($items as &$item) {

            $item['line_total'] =
                (float)
                $item['current_price']
                *
                (int)
                $item['quantity'];

            $subtotal +=
                $item['line_total'];
        }

        unset($item);

        $addresses =
            $this->addressModel
                ->getByUserId(
                    $customerId
                );

        require BASE_PATH
            . '/app/views/checkout/index.php';
    }

    // ========================================================
    // PLACE ORDER
    // ========================================================

    public function placeOrder(): void
    {
        $this->requireCustomer();
        $this->requirePost();
        $this->validateCsrf();

        $customerId =
            (int)
            $_SESSION['user']['id'];

        $cart =
            $this->cartModel
                ->findByCustomerId(
                    $customerId
                );

        if (!$cart) {

            $this->redirectCart(
                'Giỏ hàng đang trống.'
            );
        }

        // ====================================================
        // ADDRESS
        // ====================================================

        $addressId =
            (int)
            ($_POST['address_id'] ?? 0);

        if ($addressId > 0) {

            $savedAddress =
                $this->addressModel
                    ->findOwned(
                        $addressId,
                        $customerId
                    );

            if (!$savedAddress) {

                $this->checkoutError(
                    'Địa chỉ giao hàng không hợp lệ.'
                );
            }

            $shipping = [
                'recipient_name' =>
                    $savedAddress['recipient_name'],

                'phone' =>
                    $savedAddress['phone'],

                'full_address' =>
                    $this->buildFullAddress(
                        $savedAddress
                    )
            ];

        } else {

            $recipientName =
                trim(
                    $_POST['recipient_name']
                    ?? ''
                );

            $phone =
                trim(
                    $_POST['phone']
                    ?? ''
                );

            $addressLine =
                trim(
                    $_POST['address_line']
                    ?? ''
                );

            $ward =
                trim(
                    $_POST['ward']
                    ?? ''
                );

            $district =
                trim(
                    $_POST['district']
                    ?? ''
                );

            $province =
                trim(
                    $_POST['province']
                    ?? ''
                );

            if (
                $recipientName === ''
                || $phone === ''
                || $addressLine === ''
            ) {

                $this->checkoutError(
                    'Vui lòng nhập đầy đủ người nhận, số điện thoại và địa chỉ.'
                );
            }

            if (
                !preg_match(
                    '/^[0-9+\s]{8,20}$/',
                    $phone
                )
            ) {

                $this->checkoutError(
                    'Số điện thoại không hợp lệ.'
                );
            }

            $addressData = [
                'recipient_name' =>
                    $recipientName,

                'phone' =>
                    $phone,

                'address_line' =>
                    $addressLine,

                'ward' =>
                    $ward,

                'district' =>
                    $district,

                'province' =>
                    $province,

                'is_default' =>
                    isset(
                        $_POST['is_default']
                    )
                    ? 1
                    : 0
            ];

            if (
                isset(
                    $_POST['save_address']
                )
            ) {

                $this->addressModel
                    ->create(
                        $customerId,
                        $addressData
                    );
            }

            $shipping = [
                'recipient_name' =>
                    $recipientName,

                'phone' =>
                    $phone,

                'full_address' =>
                    $this->buildFullAddress(
                        $addressData
                    )
            ];
        }

        // ====================================================
        // PAYMENT
        // ====================================================

        $paymentMethod =
            $_POST['payment_method']
            ?? 'cod';

        if (
            !in_array(
                $paymentMethod,
                [
                    'cod',
                    'bank_transfer'
                ],
                true
            )
        ) {

            $this->checkoutError(
                'Phương thức thanh toán không hợp lệ.'
            );
        }

        $promotionCode =
            trim(
                $_POST['promotion_code']
                ?? ''
            );

        $customerNote =
            trim(
                $_POST['customer_note']
                ?? ''
            );

        try {

            $order =
                $this->orderModel
                    ->createFromCart(
                        $customerId,
                        (int) $cart['id'],
                        $shipping,
                        $paymentMethod,
                        $promotionCode !== ''
                            ? $promotionCode
                            : null,
                        $customerNote !== ''
                            ? $customerNote
                            : null
                    );

            $_SESSION['cart_count'] = 0;

            header(
                'Location: '
                . BASE_URL
                . '/?url=order/success&code='
                . urlencode(
                    $order['order_code']
                )
            );

            exit;

        } catch (RuntimeException $e) {

            $this->checkoutError(
                $e->getMessage()
            );

        } catch (Throwable $e) {

            error_log(
                $e->getMessage()
            );

            $this->checkoutError(
                'Không thể tạo đơn hàng. Vui lòng thử lại.'
            );
        }
    }

    // ========================================================
    // SUCCESS
    // ========================================================

    public function success(): void
    {
        $this->requireCustomer();

        $orderCode =
            trim(
                $_GET['code']
                ?? ''
            );

        $customerId =
            (int)
            $_SESSION['user']['id'];

        $order =
            $this->orderModel
                ->findByCodeForCustomer(
                    $orderCode,
                    $customerId
                );

        if (!$order) {

            http_response_code(404);

            require BASE_PATH
                . '/app/views/errors/404.php';

            return;
        }

        $orderItems =
            $this->orderModel
                ->getItems(
                    (int) $order['id']
                );

        require BASE_PATH
            . '/app/views/orders/success.php';
    }

    // ========================================================
    // HELPERS
    // ========================================================

    private function buildFullAddress(
        array $address
    ): string {

        $parts = [
            $address['address_line'] ?? '',
            $address['ward'] ?? '',
            $address['district'] ?? '',
            $address['province'] ?? ''
        ];

        $parts =
            array_filter(
                array_map(
                    'trim',
                    $parts
                )
            );

        return implode(
            ', ',
            $parts
        );
    }

    private function requireCustomer(): void
    {
        if (
            !isset(
                $_SESSION['user']
            )
        ) {

            $_SESSION[
                'redirect_after_login'
            ] =
                BASE_URL
                . '/?url=checkout';

            header(
                'Location: '
                . BASE_URL
                . '/?url=login'
            );

            exit;
        }

        if (
            (
                $_SESSION['user']['role']
                ?? null
            )
            !== 'customer'
        ) {

            http_response_code(403);

            require BASE_PATH
                . '/app/views/errors/403.php';

            exit;
        }
    }

    private function requirePost(): void
    {
        if (
            $_SERVER['REQUEST_METHOD']
            !== 'POST'
        ) {

            http_response_code(405);

            exit(
                'Method Not Allowed'
            );
        }
    }

    private function validateCsrf(): void
    {
        $token =
            $_POST['_token']
            ?? '';

        $sessionToken =
            $_SESSION['csrf_token']
            ?? '';

        if (
            $token === ''
            || $sessionToken === ''
            || !hash_equals(
                $sessionToken,
                $token
            )
        ) {

            http_response_code(403);

            exit(
                'Yêu cầu không hợp lệ.'
            );
        }
    }

    private function checkoutError(
        string $message
    ): never {

        $_SESSION[
            'flash_error'
        ] =
            $message;

        header(
            'Location: '
            . BASE_URL
            . '/?url=checkout'
        );

        exit;
    }

    private function redirectCart(
        string $message
    ): never {

        $_SESSION[
            'flash_error'
        ] =
            $message;

        header(
            'Location: '
            . BASE_URL
            . '/?url=cart'
        );

        exit;
    }
}