<?php

namespace Modules\Services\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\Session;
use core\Security;
use Modules\Services\Models\Service;

class PackageController extends Controller
{
    private Service $serviceModel;

    public function __construct()
    {
        parent::__construct();
        $this->serviceModel = new Service();
    }

    public function index(): void
    {
        $this->requirePermission('services_view');

        $db = Database::getInstance();
        $page = max(1, (int)$this->request->get('page', 1));
        $perPage = PAGINATION_LIMIT;

        $packages = $db->table('packages p')
            ->select('p.*,
                (SELECT COUNT(*) FROM package_services ps WHERE ps.package_id = p.id) as service_count,
                (SELECT COALESCE(SUM(s.price), 0) FROM package_services ps
                 INNER JOIN services s ON s.id = ps.service_id
                 WHERE ps.package_id = p.id) as total_value')
            ->where('p.deleted_at', 'IS', null)
            ->orderBy('p.created_at', 'DESC')
            ->paginate($perPage, $page);

        $this->view('Services/packages/index', [
            'title' => 'Packages',
            'breadcrumb' => ['Packages' => url('packages')],
            'packages' => $packages,
        ]);
    }

    public function create(): void
    {
        $this->requirePermission('services_create');

        $services = $this->serviceModel->getActive();
        $db = Database::getInstance();
        $categories = $db->table('service_categories')
            ->where('is_active', 1)
            ->where('deleted_at', 'IS', null)
            ->orderBy('sort_order', 'ASC')
            ->get();

        $this->view('Services/packages/create', [
            'title' => 'Add New Package',
            'breadcrumb' => [
                'Packages' => url('packages'),
                'Add New' => url('packages/create'),
            ],
            'services' => $services,
            'categories' => $categories,
        ]);
    }

    public function store(): void
    {
        $this->requirePermission('services_create');

        $validated = $this->validate([
            'name' => 'required|max_length:255',
            'description' => 'max_length:2000',
            'price' => 'required|numeric|min:0',
            'tax_percent' => 'numeric|min:0|max:100',
            'validity_days' => 'integer|min:1',
            'max_visits' => 'integer|min:1',
            'is_active' => 'in:0,1',
            'service_ids' => 'required|array',
            'quantities' => 'array',
        ]);

        $db = Database::getInstance();
        $db->beginTransaction();

        try {
            $slug = strtolower(trim(preg_replace('/[^a-zA-Z0-9]+/', '-', $validated['name']), '-'));
            $existing = $db->table('packages')->where('slug', 'LIKE', $slug . '%')->count();
            if ($existing > 0) {
                $slug .= '-' . $existing;
            }

            $packageId = $db->table('packages')->insert([
                'name' => $validated['name'],
                'slug' => $slug,
                'description' => $validated['description'] ?? null,
                'price' => $validated['price'],
                'tax_percent' => $validated['tax_percent'] ?? 0,
                'validity_days' => $validated['validity_days'] ?? 30,
                'max_visits' => $validated['max_visits'] ?? 1,
                'is_active' => $validated['is_active'] ?? 1,
                'created_at' => date(DATE_TIME_FORMAT),
                'updated_at' => date(DATE_TIME_FORMAT),
            ]);

            $serviceIds = $validated['service_ids'] ?? [];
            $quantities = $validated['quantities'] ?? [];

            foreach ($serviceIds as $serviceId) {
                $qty = (int)($quantities[$serviceId] ?? 1);
                if ($qty < 1) {
                    $qty = 1;
                }
                $db->table('package_services')->insert([
                    'package_id' => $packageId,
                    'service_id' => (int)$serviceId,
                    'quantity' => $qty,
                    'created_at' => date(DATE_TIME_FORMAT),
                ]);
            }

            $db->commit();

            $this->logActivity('create', 'Created package: ' . $validated['name']);
            $this->logAudit('create', 'packages', $packageId, null, $validated);

            $this->redirectWith(url('packages'), 'success', 'Package created successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            $this->redirectWith(url('packages/create'), 'error', 'Failed to create package: ' . $e->getMessage());
        }
    }

    public function edit(int $id): void
    {
        $this->requirePermission('services_edit');

        $db = Database::getInstance();
        $package = $db->table('packages')->find($id);
        if (!$package) {
            $this->redirectWith(url('packages'), 'error', 'Package not found.');
        }

        $packageServices = $db->table('package_services')
            ->where('package_id', $id)
            ->get();

        $services = $this->serviceModel->getActive();

        $categories = $db->table('service_categories')
            ->where('is_active', 1)
            ->where('deleted_at', 'IS', null)
            ->orderBy('sort_order', 'ASC')
            ->get();

        $this->view('Services/packages/edit', [
            'title' => 'Edit Package',
            'breadcrumb' => [
                'Packages' => url('packages'),
                'Edit' => url('packages/edit/' . $id),
            ],
            'package' => $package,
            'packageServices' => $packageServices,
            'services' => $services,
            'categories' => $categories,
        ]);
    }

    public function update(int $id): void
    {
        $this->requirePermission('services_edit');

        $db = Database::getInstance();
        $package = $db->table('packages')->find($id);
        if (!$package) {
            $this->redirectWith(url('packages'), 'error', 'Package not found.');
        }

        $oldValues = (array)$package;

        $validated = $this->validate([
            'name' => 'required|max_length:255',
            'description' => 'max_length:2000',
            'price' => 'required|numeric|min:0',
            'tax_percent' => 'numeric|min:0|max:100',
            'validity_days' => 'integer|min:1',
            'max_visits' => 'integer|min:1',
            'is_active' => 'in:0,1',
            'service_ids' => 'required|array',
            'quantities' => 'array',
        ]);

        $db->beginTransaction();

        try {
            $updateData = [
                'name' => $validated['name'],
                'description' => $validated['description'] ?? null,
                'price' => $validated['price'],
                'tax_percent' => $validated['tax_percent'] ?? 0,
                'validity_days' => $validated['validity_days'] ?? 30,
                'max_visits' => $validated['max_visits'] ?? 1,
                'is_active' => $validated['is_active'] ?? 0,
                'updated_at' => date(DATE_TIME_FORMAT),
            ];

            if ($validated['name'] !== $package->name) {
                $slug = strtolower(trim(preg_replace('/[^a-zA-Z0-9]+/', '-', $validated['name']), '-'));
                $existing = $db->table('packages')
                    ->where('slug', 'LIKE', $slug . '%')
                    ->where('id', '!=', $id)
                    ->count();
                if ($existing > 0) {
                    $slug .= '-' . $existing;
                }
                $updateData['slug'] = $slug;
            }

            $db->table('packages')
                ->where('id', $id)
                ->update($updateData);

            $db->table('package_services')
                ->where('package_id', $id)
                ->delete();

            $serviceIds = $validated['service_ids'] ?? [];
            $quantities = $validated['quantities'] ?? [];

            foreach ($serviceIds as $serviceId) {
                $qty = (int)($quantities[$serviceId] ?? 1);
                if ($qty < 1) {
                    $qty = 1;
                }
                $db->table('package_services')->insert([
                    'package_id' => $id,
                    'service_id' => (int)$serviceId,
                    'quantity' => $qty,
                    'created_at' => date(DATE_TIME_FORMAT),
                ]);
            }

            $db->commit();

            $this->logActivity('update', 'Updated package: ' . $validated['name']);
            $this->logAudit('update', 'packages', $id, $oldValues, $validated);

            $this->redirectWith(url('packages'), 'success', 'Package updated successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            $this->redirectWith(url('packages/edit/' . $id), 'error', 'Failed to update package: ' . $e->getMessage());
        }
    }

    public function delete(int $id): void
    {
        $this->requirePermission('services_delete');

        $db = Database::getInstance();
        $package = $db->table('packages')->find($id);
        if (!$package) {
            $this->redirectWith(url('packages'), 'error', 'Package not found.');
        }

        $db->beginTransaction();
        try {
            $db->table('package_services')
                ->where('package_id', $id)
                ->delete();

            $db->table('packages')
                ->where('id', $id)
                ->update(['deleted_at' => date(DATE_TIME_FORMAT)]);

            $db->commit();

            $this->logActivity('delete', 'Deleted package: ' . $package->name);
            $this->logAudit('delete', 'packages', $id, (array)$package, null);

            $this->redirectWith(url('packages'), 'success', 'Package deleted successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            $this->redirectWith(url('packages'), 'error', 'Failed to delete package.');
        }
    }
}
