<?php
declare(strict_types=1);
namespace App\Controllers;

use App\Core\Controller;
use App\Core\SessionAuth;
use App\Repositories\CustomerRepository;
use App\Repositories\SettingRepository;
use App\Repositories\StudioRepository;
use App\Services\AuditService;
use App\Services\WhatsAppService;

final class StudioController extends Controller {
    private function auth(): SessionAuth {
        return app()->get(SessionAuth::class);
    }

    private function ensureStudioAccess(): void {
        $auth = $this->auth();
        $auth->requireLogin();
        if (!$auth->canAccess('studio_store') && !$auth->canAccess('studio_update') && !$auth->canAccess('studio_delete')) {
            $auth->requirePageAccess('studio');
        }
    }

    public function index(): void {
        $this->ensureStudioAccess();
        $q = trim((string)($_GET['q'] ?? ''));
        $date = trim((string)($_GET['date'] ?? ''));
        if ($date === '') $date = date('Y-m-d');

        $repo = new StudioRepository();
        $rows = $repo->searchBookings($q, $date);
        $settings = (new SettingRepository())->allAssoc();
        $canCreate = $this->auth()->canAccess('studio_store');
        $canManage = $this->auth()->canAccess('studio_update') || $this->auth()->canAccess('studio_delete');
        $editing = null;
        $editId = (int)($_GET['edit_id'] ?? 0);
        if ($editId > 0 && ($this->auth()->canAccess('studio_update') || $this->auth()->canAccess('studio_delete'))) {
            $editing = $repo->findBooking($editId);
        }

        $bookedSlots = $repo->bookedSlotsByDate($date);
        $this->view('studio/index', compact('rows', 'q', 'date', 'settings', 'canCreate', 'canManage', 'editing', 'bookedSlots'));
    }

    public function store(): void {
        $this->auth()->requirePageAccess('studio_store');
        verify_csrf();

        try {
            $payload = $this->collectPayload();
        } catch (\RuntimeException $e) {
            flash('error', $e->getMessage());
            redirect(base_url('?page=studio'));
        }
        $customerRepo = new CustomerRepository();
        $existingCustomer = $customerRepo->findByIdentifier($payload['identifier']);
        if ($existingCustomer && (int)($existingCustomer['is_blacklisted'] ?? 0) === 1) {
            flash('error', 'هذا العميل محظور ولا يمكن حجز الاستوديو له' . (!empty($existingCustomer['blacklist_reason']) ? ' — ' . $existingCustomer['blacklist_reason'] : ''));
            redirect(base_url('?page=studio'));
        }

        $customerId = $customerRepo->createOrUpdate([
            'full_name' => $payload['full_name'],
            'phone' => $payload['phone'],
            'civil_id' => $payload['civil_id'],
        ]);

        $repo = new StudioRepository();
        try {
            $bookingId = $repo->createBooking($customerId, $payload['booking_date'], $payload['start_time'], (float)$payload['price'], (int)(current_user()['id'] ?? 1));
        } catch (\RuntimeException $e) {
            flash('error', $e->getMessage());
            redirect(base_url('?page=studio&date=' . urlencode($payload['booking_date'])));
        }

        $booking = $repo->findBooking($bookingId);
        $this->sendBookingMessage($booking, 'create');
        (new AuditService())->log('studio', 'create', $bookingId, [
            'customer_id' => $customerId,
            'booking_date' => $payload['booking_date'],
            'start_time' => $payload['start_time'],
            'price' => $payload['price'],
        ]);

        flash('success', 'تم حجز الاستوديو بنجاح وإرسال الإشعار للعميل');
        redirect(base_url('?page=studio&date=' . urlencode($payload['booking_date'])));
    }

    public function update(): void {
        $this->auth()->requirePageAccess('studio_update');
        verify_csrf();
        $id = (int)($_POST['id'] ?? 0);
        if ($id <= 0) {
            flash('error', 'الحجز غير صالح');
            redirect(base_url('?page=studio'));
        }

        $repo = new StudioRepository();
        $existingBooking = $repo->findBooking($id);
        if (!$existingBooking) {
            flash('error', 'الحجز غير موجود');
            redirect(base_url('?page=studio'));
        }

        try {
            $payload = $this->collectPayload();
        } catch (\RuntimeException $e) {
            flash('error', $e->getMessage());
            redirect(base_url('?page=studio&edit_id=' . $id));
        }

        $customerRepo = new CustomerRepository();
        $existingCustomer = $customerRepo->findByIdentifier($payload['identifier']);
        if ($existingCustomer && (int)($existingCustomer['is_blacklisted'] ?? 0) === 1 && (int)$existingCustomer['id'] !== (int)$existingBooking['customer_id']) {
            flash('error', 'هذا العميل محظور ولا يمكن حجز الاستوديو له' . (!empty($existingCustomer['blacklist_reason']) ? ' — ' . $existingCustomer['blacklist_reason'] : ''));
            redirect(base_url('?page=studio&edit_id=' . $id . '&date=' . urlencode($payload['booking_date'])));
        }

        $customerId = $customerRepo->createOrUpdate([
            'full_name' => $payload['full_name'],
            'phone' => $payload['phone'],
            'civil_id' => $payload['civil_id'],
        ]);

        try {
            $repo->updateBooking($id, $customerId, $payload['booking_date'], $payload['start_time'], (float)$payload['price'], (int)(current_user()['id'] ?? 1));
        } catch (\RuntimeException $e) {
            flash('error', $e->getMessage());
            redirect(base_url('?page=studio&edit_id=' . $id . '&date=' . urlencode($payload['booking_date'])));
        }

        $booking = $repo->findBooking($id);
        $this->sendBookingMessage($booking, 'update');
        (new AuditService())->log('studio', 'update', $id, [
            'customer_id' => $customerId,
            'booking_date' => $payload['booking_date'],
            'start_time' => $payload['start_time'],
            'price' => $payload['price'],
        ]);

        flash('success', 'تم تعديل الحجز بنجاح وإرسال التحديث للعميل');
        redirect(base_url('?page=studio&date=' . urlencode($payload['booking_date'])));
    }

    public function delete(): void {
        $this->auth()->requirePageAccess('studio_delete');
        verify_csrf();
        $id = (int)($_POST['id'] ?? 0);
        if ($id <= 0) {
            flash('error', 'الحجز غير صالح');
            redirect(base_url('?page=studio'));
        }

        $repo = new StudioRepository();
        $booking = $repo->findBooking($id);
        if (!$booking) {
            flash('error', 'الحجز غير موجود');
            redirect(base_url('?page=studio'));
        }

        $repo->deleteBooking($id);
        (new AuditService())->log('studio', 'delete', $id, [
            'customer_id' => $booking['customer_id'] ?? null,
            'booking_date' => $booking['booking_date'] ?? '',
            'start_time' => $booking['start_time'] ?? '',
        ]);
        flash('success', 'تم حذف الحجز بنجاح');
        redirect(base_url('?page=studio&date=' . urlencode((string)($booking['booking_date'] ?? date('Y-m-d')))));
    }

    public function bookedSlots(): void {
        $this->ensureStudioAccess();
        header('Content-Type: application/json; charset=utf-8');
        $date = trim((string)($_GET['date'] ?? ''));
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
            echo json_encode([], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
            return;
        }
        $slots = (new StudioRepository())->bookedSlotsByDate($date);
        echo json_encode($slots, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    }

    private function collectPayload(): array {
        $identifier = trim((string)($_POST['identifier'] ?? ''));
        $fullName = trim((string)($_POST['full_name'] ?? ''));
        $phone = normalize_phone((string)($_POST['phone'] ?? ''));
        $civilId = trim((string)($_POST['civil_id'] ?? ''));
        $bookingDate = trim((string)($_POST['booking_date'] ?? ''));
        $startTime = trim((string)($_POST['start_time'] ?? ''));
        $price = number_format(max(0, (float)($_POST['price'] ?? (new SettingRepository())->get('studio_booking_price', '0.000'))), 3, '.', '');

        if ($identifier === '' && $phone === '' && $civilId === '') {
            throw new \RuntimeException('يرجى إدخال رقم الهاتف أو الرقم المدني');
        }
        if ($fullName === '') {
            throw new \RuntimeException('يرجى إدخال اسم العميل');
        }
        if ($phone === '') {
            throw new \RuntimeException('رقم الهاتف مطلوب لإرسال رسالة الحجز للعميل');
        }
        if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $bookingDate)) {
            throw new \RuntimeException('يرجى اختيار تاريخ الحجز');
        }
        if (!preg_match('/^([01]\d|2[0-3]):00$/', $startTime)) {
            throw new \RuntimeException('يرجى اختيار ساعة بدء صحيحة');
        }

        return [
            'identifier' => $identifier !== '' ? $identifier : ($phone !== '' ? $phone : $civilId),
            'full_name' => $fullName,
            'phone' => $phone,
            'civil_id' => $civilId,
            'booking_date' => $bookingDate,
            'start_time' => $startTime,
            'price' => $price,
        ];
    }

    private function sendBookingMessage(?array $booking, string $mode): void {
        if (!$booking || empty($booking['phone'])) return;
        $settings = new SettingRepository();
        $templateKey = $mode === 'update' ? 'studio_booking_update_template' : 'studio_booking_create_template';
        $default = $mode === 'update'
            ? 'مرحباً {name}، تم تحديث حجز استوديو التصوير بتاريخ {booking_date} من {start_time} إلى {end_time}. السعر: {price} {currency}.'
            : 'مرحباً {name}، تم تأكيد حجز استوديو التصوير بتاريخ {booking_date} من {start_time} إلى {end_time}. السعر: {price} {currency}.';
        $template = $settings->get($templateKey, $default);
        $wa = new WhatsAppService($settings);
        $message = $wa->renderTemplate($template, [
            'name' => (string)($booking['full_name'] ?? ''),
            'phone' => (string)($booking['phone'] ?? ''),
            'civil_id' => (string)($booking['civil_id'] ?? ''),
            'booking_date' => (string)($booking['booking_date'] ?? ''),
            'start_time' => substr((string)($booking['start_time'] ?? ''), 0, 5),
            'end_time' => substr((string)($booking['end_time'] ?? ''), 0, 5),
            'price' => number_format((float)($booking['price'] ?? 0), 3, '.', ''),
            'currency' => $settings->get('queue_currency', 'ر.ع'),
        ]);
        $wa->send((string)$booking['phone'], $message);
    }
}
