<?php

require_once BASE_PATH . '/app/controllers/owner/OwnerBaseController.php';
require_once BASE_PATH . '/app/models/BusinessHour.php';
require_once BASE_PATH . '/app/models/BlockedSlot.php';
require_once BASE_PATH . '/app/models/SpaActivityLog.php';

class OwnerScheduleController extends OwnerBaseController
{
    private BusinessHour $hours;
    private BlockedSlot $blocks;
    private SpaActivityLog $activityLog;

    public function __construct()
    {
        $this->requireOwner();
        $this->hours = new BusinessHour();
        $this->blocks = new BlockedSlot();
        $this->activityLog = new SpaActivityLog();
    }

    public function index(): void
    {
        $hours = $this->hours->getWeek();
        $blocks = $this->blocks->getForOwner(date('Y-m-d'));
        require BASE_PATH . '/app/views/owner/schedule/index.php';
    }

    public function updateHours(): void
{
    $this->requirePost();

    $this->validateCsrf();


    $input =
        $_POST['hours']
        ?? [];


    $dayNames = [
        0 => 'Chủ nhật',
        1 => 'Thứ hai',
        2 => 'Thứ ba',
        3 => 'Thứ tư',
        4 => 'Thứ năm',
        5 => 'Thứ sáu',
        6 => 'Thứ bảy'
    ];


    /*
    |--------------------------------------------------------------------------
    | DỮ LIỆU CŨ
    |--------------------------------------------------------------------------
    */

    $before = [];


    foreach (
        $this->hours->getWeek()
        as $hour
    ) {

        $before[
            (int) $hour['day_of_week']
        ] = $hour;
    }


    $hours = [];


    try {

        /*
        |--------------------------------------------------------------------------
        | KIỂM TRA 7 NGÀY
        |--------------------------------------------------------------------------
        */

        foreach (
            range(0, 6)
            as $day
        ) {

            $row =
                $input[$day]
                ?? [];


            $isOpen =
                isset(
                    $row['is_open']
                )
                ? 1
                : 0;


            $start =
                trim(
                    (string) (
                        $row['open_time']
                        ?? ''
                    )
                );


            $end =
                trim(
                    (string) (
                        $row['close_time']
                        ?? ''
                    )
                );


            /*
             * Ngày đóng cửa không cần giờ.
             */
            if (!$isOpen) {

                $hours[] = [
                    'day_of_week' =>
                        $day,

                    'is_open' =>
                        0,

                    'open_time' =>
                        null,

                    'close_time' =>
                        null
                ];

                continue;
            }


            /*
            |--------------------------------------------------------------------------
            | NGÀY MỞ CỬA PHẢI CÓ GIỜ
            |--------------------------------------------------------------------------
            */

            if (
                !preg_match(
                    '/^(?:[01]\d|2[0-3]):[0-5]\d$/',
                    $start
                )
            ) {

                throw new InvalidArgumentException(
                    $dayNames[$day]
                    . ': giờ mở cửa không hợp lệ.'
                );
            }


            if (
                !preg_match(
                    '/^(?:[01]\d|2[0-3]):[0-5]\d$/',
                    $end
                )
            ) {

                throw new InvalidArgumentException(
                    $dayNames[$day]
                    . ': giờ đóng cửa không hợp lệ.'
                );
            }


            /*
             * Chuyển sang phút để so sánh.
             */
            [$startHour, $startMinute] =
                array_map(
                    'intval',
                    explode(
                        ':',
                        $start
                    )
                );


            [$endHour, $endMinute] =
                array_map(
                    'intval',
                    explode(
                        ':',
                        $end
                    )
                );


            $startMinutes =
                ($startHour * 60)
                + $startMinute;


            $endMinutes =
                ($endHour * 60)
                + $endMinute;


            if (
                $startMinutes
                >=
                $endMinutes
            ) {

                throw new InvalidArgumentException(
                    $dayNames[$day]
                    . ': giờ đóng cửa phải sau giờ mở cửa.'
                );
            }


            $hours[] = [

                'day_of_week' =>
                    $day,

                'is_open' =>
                    1,

                'open_time' =>
                    $start . ':00',

                'close_time' =>
                    $end . ':00'

            ];
        }


        /*
        |--------------------------------------------------------------------------
        | LƯU DB
        |--------------------------------------------------------------------------
        */

        $this->hours
            ->updateWeek(
                $hours
            );


        /*
        |--------------------------------------------------------------------------
        | ACTIVITY LOG
        |--------------------------------------------------------------------------
        */

        $changes = [];


        foreach (
            $hours
            as $hour
        ) {

            $day =
                (int) $hour[
                    'day_of_week'
                ];


            $old =
                $before[$day]
                ?? [];


            $oldOpen =
                (int) (
                    $old['is_open']
                    ?? 0
                );


            $oldStart =
                !empty(
                    $old['open_time']
                )
                    ? substr(
                        (string) $old[
                            'open_time'
                        ],
                        0,
                        8
                    )
                    : null;


            $oldEnd =
                !empty(
                    $old['close_time']
                )
                    ? substr(
                        (string) $old[
                            'close_time'
                        ],
                        0,
                        8
                    )
                    : null;


            if (
                $oldOpen
                    !==
                $hour['is_open']

                ||

                $oldStart
                    !==
                $hour['open_time']

                ||

                $oldEnd
                    !==
                $hour['close_time']
            ) {

                $changes[] = [

                    'day_of_week' =>
                        $day,

                    'old' => [

                        'is_open' =>
                            $oldOpen,

                        'open_time' =>
                            $oldStart,

                        'close_time' =>
                            $oldEnd
                    ],

                    'new' => [

                        'is_open' =>
                            $hour[
                                'is_open'
                            ],

                        'open_time' =>
                            $hour[
                                'open_time'
                            ],

                        'close_time' =>
                            $hour[
                                'close_time'
                            ]
                    ]
                ];
            }
        }


        try {

            $this->activityLog
                ->record(
                    (int) $_SESSION[
                        'user'
                    ]['id'],

                    'owner.business_hours.update',

                    'business_hours',

                    null,

                    [
                        'changes' =>
                            $changes
                    ]
                );

        } catch (Throwable $e) {

            /*
             * Log lỗi không được làm mất
             * kết quả lưu giờ phục vụ.
             */
        }


        $this->flashSuccess(
            'Đã cập nhật giờ phục vụ thành công.'
        );


    } catch (Throwable $e) {

        $this->flashError(
            $e->getMessage()
        );
    }


    $this->redirect(
        'owner/schedule'
    );
}

    public function storeBlockedSlot(): void
    {
        $this->requirePost();
        $this->validateCsrf();
        $date = (string) ($_POST['blocked_date'] ?? '');
        $allDay = isset($_POST['is_all_day']);
        $start = trim((string) ($_POST['start_time'] ?? ''));
        $end = trim((string) ($_POST['end_time'] ?? ''));

        try {
            $valid = DateTimeImmutable::createFromFormat('!Y-m-d', $date);
            if (!$valid || $valid->format('Y-m-d') !== $date || $date < date('Y-m-d')) {
                throw new InvalidArgumentException('Ngày khóa không hợp lệ.');
            }
            if (!$allDay && (!preg_match('/^([01]\d|2[0-3]):[0-5]\d$/', $start)
                || !preg_match('/^([01]\d|2[0-3]):[0-5]\d$/', $end)
                || $start >= $end)) {
                throw new InvalidArgumentException('Khung giờ khóa không hợp lệ.');
            }
            $slotId = $this->blocks->create([
                'blocked_date' => $date,
                'start_time' => $allDay ? null : $start . ':00',
                'end_time' => $allDay ? null : $end . ':00',
                'reason' => trim((string) ($_POST['reason'] ?? '')) ?: null,
                'created_by' => (int) $_SESSION['user']['id']
            ]);
            $this->activityLog->record(
                (int) $_SESSION['user']['id'],
                'owner.blocked_slot.create',
                'blocked_slot',
                $slotId,
                ['blocked_date' => $date, 'is_all_day' => $allDay]
            );
            $this->flashSuccess('Đã khóa lịch.');
        } catch (Throwable $e) {
            $this->flashError($e->getMessage());
        }

        $this->redirect('owner/schedule');
    }

    public function deleteBlockedSlot(): void
    {
        $this->requirePost();
        $this->validateCsrf();
        $id = (int) ($_POST['blocked_slot_id'] ?? 0);
        $slot = $this->blocks->findById($id);
        if (!$slot) {
            $this->flashError('Khung giờ khóa không tồn tại.');
            $this->redirect('owner/schedule');
        }
        $this->blocks->delete($id);
        $this->activityLog->record(
            (int) $_SESSION['user']['id'],
            'owner.blocked_slot.delete',
            'blocked_slot',
            $id,
            ['blocked_date' => $slot['blocked_date'], 'is_all_day' => $slot['start_time'] === null]
        );
        $this->flashSuccess('Đã gỡ khóa lịch.');
        $this->redirect('owner/schedule');
    }
}
