<?php
declare(strict_types=1);

namespace App\Modules\Rentals\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Rentals\Models\RentalEntity;
use App\Modules\Rentals\Models\RentalContract;
use App\Modules\Rentals\Models\RentalBooking;
use App\Modules\Rentals\Services\RentalContractService;
use App\Modules\Rentals\Services\RentalDepositService;
use App\Modules\Facilities\Models\Facility;

class RentalController extends Controller
{
    // ─── Contracts ───────────────────────────────────────────────

    /**
     * List contracts with status tabs, entity filter, facility filter, search, pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'           => trim((string) $request->get('q', '')),
            'status'      => trim((string) $request->get('status', '')),
            'entity_id'   => trim((string) $request->get('entity_id', '')),
            'facility_id' => trim((string) $request->get('facility_id', '')),
        ];

        $page   = max(1, (int) $request->get('page', 1));
        $result = RentalContract::search($filters, 25, $page);

        // Load entities and facilities for filter dropdowns
        $entities   = RentalEntity::search([], 1000, 1)['data'] ?? [];
        $facilities = Facility::allActive();

        // Load entity names map for display
        $entityMap = [];
        foreach ($entities as $e) {
            $entityMap[(int) $e['id']] = $e['name_ar'];
        }

        // Load facility names map for display
        $facilityMap = [];
        foreach ($facilities as $f) {
            $facilityMap[(int) $f['id']] = $f['name_ar'];
        }

        return $this->view('Rentals.Views.index', [
            'contracts'   => $result['data'],
            'pagination'  => $result['pagination'],
            'filters'     => $filters,
            'statuses'    => RentalContract::getStatuses(),
            'entities'    => $entities,
            'facilities'  => $facilities,
            'entityMap'   => $entityMap,
            'facilityMap' => $facilityMap,
        ]);
    }

    // ─── Entities ────────────────────────────────────────────────

    /**
     * List rental entities.
     */
    public function entities(Request $request): Response
    {
        $filters = [
            'q'           => trim((string) $request->get('q', '')),
            'entity_type' => trim((string) $request->get('entity_type', '')),
            'status'      => trim((string) $request->get('status', '')),
        ];

        $page   = max(1, (int) $request->get('page', 1));
        $result = RentalEntity::search($filters, 25, $page);

        return $this->view('Rentals.Views.entities', [
            'entities'    => $result['data'],
            'pagination'  => $result['pagination'],
            'filters'     => $filters,
            'entityTypes' => RentalEntity::getEntityTypes(),
            'statuses'    => RentalEntity::getStatuses(),
        ]);
    }

    /**
     * Show the create entity form.
     */
    public function createEntity(Request $request): Response
    {
        return $this->view('Rentals.Views.entity_form', [
            'entity'      => null,
            'entityTypes' => RentalEntity::getEntityTypes(),
            'statuses'    => RentalEntity::getStatuses(),
        ]);
    }

    /**
     * Validate and store a new rental entity.
     */
    public function storeEntity(Request $request): Response
    {
        $data = $this->extractEntityData($request);
        $errors = $this->validateEntityData($data);

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/rentals/entities/create');
        }

        $entity = RentalEntity::create($data);

        return $this->redirect('/rentals/entities/' . $entity->id)->withSuccess('تم إضافة الجهة المستأجرة بنجاح');
    }

    /**
     * Show entity detail page.
     */
    public function showEntity(Request $request, string $id): Response
    {
        $entity = RentalEntity::find((int) $id);
        if (!$entity) {
            return $this->redirect('/rentals/entities')->withError('الجهة المستأجرة غير موجودة');
        }

        $contracts = RentalContract::getForEntity((int) $id);

        return $this->view('Rentals.Views.entity_show', [
            'entity'    => $entity,
            'contracts' => $contracts,
        ]);
    }

    /**
     * Show edit form for an entity.
     */
    public function editEntity(Request $request, string $id): Response
    {
        $entity = RentalEntity::find((int) $id);
        if (!$entity) {
            return $this->redirect('/rentals/entities')->withError('الجهة المستأجرة غير موجودة');
        }

        return $this->view('Rentals.Views.entity_form', [
            'entity'      => $entity,
            'entityTypes' => RentalEntity::getEntityTypes(),
            'statuses'    => RentalEntity::getStatuses(),
        ]);
    }

    /**
     * Validate and update an existing entity.
     */
    public function updateEntity(Request $request, string $id): Response
    {
        $entity = RentalEntity::find((int) $id);
        if (!$entity) {
            return $this->redirect('/rentals/entities')->withError('الجهة المستأجرة غير موجودة');
        }

        $data = $this->extractEntityData($request);
        $errors = $this->validateEntityData($data);

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/rentals/entities/' . $id . '/edit');
        }

        $entity->update($data);

        return $this->redirect('/rentals/entities/' . $id)->withSuccess('تم تحديث الجهة المستأجرة بنجاح');
    }

    // ─── Contracts CRUD ──────────────────────────────────────────

    /**
     * Show the create contract form.
     */
    public function createContract(Request $request): Response
    {
        $entities   = RentalEntity::search(['status' => 'active'], 1000, 1)['data'] ?? [];
        $facilities = Facility::allActive();

        return $this->view('Rentals.Views.contract_form', [
            'contract'   => null,
            'entities'   => $entities,
            'facilities' => $facilities,
            'statuses'   => RentalContract::getStatuses(),
        ]);
    }

    /**
     * Validate and store a new rental contract.
     */
    public function storeContract(Request $request): Response
    {
        $entityId          = (int) $request->post('entity_id', 0);
        $facilityId        = (int) $request->post('facility_id', 0);
        $activityType      = trim((string) $request->post('activity_type', ''));
        $startDate         = trim((string) $request->post('start_date', ''));
        $endDate           = trim((string) $request->post('end_date', ''));
        $totalUnits        = (int) $request->post('total_units', 0);
        $unitRate          = (float) $request->post('unit_rate', 0);
        $timeTier          = trim((string) $request->post('time_tier', 'AM'));
        $depositPercentage = (float) $request->post('deposit_percentage', 0);
        $notes             = trim((string) $request->post('notes', ''));

        // Validation
        $errors = [];

        $entity = RentalEntity::find($entityId);
        if (!$entity) {
            $errors[] = 'يجب اختيار جهة مستأجرة صالحة';
        }

        $facility = Facility::find($facilityId);
        if (!$facility) {
            $errors[] = 'يجب اختيار مرفق صالح';
        }

        if ($startDate === '' || $endDate === '') {
            $errors[] = 'تاريخ البدء والانتهاء مطلوبان';
        } elseif ($startDate >= $endDate) {
            $errors[] = 'تاريخ الانتهاء يجب أن يكون بعد تاريخ البدء';
        }

        if ($totalUnits <= 0) {
            $errors[] = 'عدد الوحدات يجب أن يكون أكبر من صفر';
        }

        if ($unitRate <= 0) {
            $errors[] = 'سعر الوحدة يجب أن يكون أكبر من صفر';
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/rentals/contracts/create');
        }

        $contract = RentalContractService::createContract([
            'entity_id'          => $entityId,
            'facility_id'        => $facilityId,
            'activity_type'      => $activityType ?: null,
            'start_date'         => $startDate,
            'end_date'           => $endDate,
            'total_units'        => $totalUnits,
            'unit_rate'          => $unitRate,
            'time_tier'          => $timeTier,
            'deposit_percentage' => $depositPercentage,
            'notes'              => $notes ?: null,
        ]);

        return $this->redirect('/rentals/contracts/' . $contract->id)->withSuccess('تم إنشاء العقد بنجاح');
    }

    /**
     * Show contract detail page with bookings and deposit status.
     */
    public function showContract(Request $request, string $id): Response
    {
        $contract = RentalContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/rentals')->withError('العقد غير موجود');
        }

        $entityId   = (int) ($contract->entity_id ?? $contract['entity_id']);
        $facilityId = (int) ($contract->facility_id ?? $contract['facility_id']);

        $entity   = RentalEntity::find($entityId);
        $facility = Facility::find($facilityId);
        $bookings = RentalBooking::getForContract((int) $id);

        return $this->view('Rentals.Views.contract_show', [
            'contract' => $contract,
            'entity'   => $entity,
            'facility' => $facility,
            'bookings' => $bookings,
        ]);
    }

    /**
     * Approve a rental contract.
     */
    public function approveContract(Request $request, string $id): Response
    {
        $contract = RentalContract::find((int) $id);
        if (!$contract) {
            return $this->redirect('/rentals')->withError('العقد غير موجود');
        }

        $employee = App::getInstance()->currentEmployee();
        $contract->update([
            'status'      => 'approved',
            'approved_by' => $employee ? (int) $employee->id : null,
            'approved_at' => date('Y-m-d H:i:s'),
        ]);

        return $this->redirect('/rentals/contracts/' . $id)->withSuccess('تم اعتماد العقد بنجاح');
    }

    /**
     * Collect deposit for a contract.
     */
    public function collectDeposit(Request $request, string $id): Response
    {
        $paymentId = (int) $request->post('payment_id', 0);
        if ($paymentId <= 0) {
            return $this->redirect('/rentals/contracts/' . $id)->withError('رقم الدفعة مطلوب');
        }

        try {
            RentalDepositService::collectDeposit((int) $id, $paymentId);
            return $this->redirect('/rentals/contracts/' . $id)->withSuccess('تم تحصيل التأمين بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/rentals/contracts/' . $id)->withError($e->getMessage());
        }
    }

    /**
     * Refund deposit for a contract.
     */
    public function refundDeposit(Request $request, string $id): Response
    {
        $paymentId = (int) $request->post('payment_id', 0);

        try {
            if ($paymentId > 0) {
                RentalDepositService::processRefund((int) $id, $paymentId);
            } else {
                RentalDepositService::requestRefund((int) $id);
            }
            return $this->redirect('/rentals/contracts/' . $id)->withSuccess('تم معالجة استرداد التأمين بنجاح');
        } catch (\RuntimeException $e) {
            return $this->redirect('/rentals/contracts/' . $id)->withError($e->getMessage());
        }
    }

    // ─── Private helpers ─────────────────────────────────────────

    /**
     * Extract entity data from request.
     */
    private function extractEntityData(Request $request): array
    {
        return [
            'entity_type'              => trim((string) $request->post('entity_type', '')),
            'name_ar'                  => trim((string) $request->post('name_ar', '')),
            'name_en'                  => trim((string) $request->post('name_en', '')) ?: null,
            'contact_person'           => trim((string) $request->post('contact_person', '')) ?: null,
            'contact_phone'            => trim((string) $request->post('contact_phone', '')) ?: null,
            'contact_email'            => trim((string) $request->post('contact_email', '')) ?: null,
            'address'                  => trim((string) $request->post('address', '')) ?: null,
            'tax_number'               => trim((string) $request->post('tax_number', '')) ?: null,
            'official_letter_received' => (int) $request->post('official_letter_received', 0),
            'board_approved'           => (int) $request->post('board_approved', 0),
            'approval_date'            => trim((string) $request->post('approval_date', '')) ?: null,
            'status'                   => trim((string) $request->post('status', 'pending')),
            'notes'                    => trim((string) $request->post('notes', '')) ?: null,
        ];
    }

    /**
     * Validate entity data, return errors array.
     */
    private function validateEntityData(array $data): array
    {
        $errors = [];

        if (empty($data['name_ar']) || mb_strlen($data['name_ar']) < 2) {
            $errors[] = 'اسم الجهة بالعربي مطلوب (حرفان على الأقل)';
        }

        if (!array_key_exists($data['entity_type'], RentalEntity::getEntityTypes())) {
            $errors[] = 'نوع الجهة غير صالح';
        }

        if (!array_key_exists($data['status'], RentalEntity::getStatuses())) {
            $errors[] = 'الحالة غير صالحة';
        }

        return $errors;
    }
}
