<?php

declare(strict_types=1);

namespace App\Framework\Admin\Services;

use App\Framework\Admin\Factories\AdminFormFactory;
use App\Framework\Admin\ValueObjects\AdminFormConfig;
use App\Framework\Admin\ValueObjects\CrudConfig;
use App\Framework\Http\Method;
use App\Framework\Http\Request;
use App\Framework\Http\Responses\Redirect;
use App\Framework\Http\Responses\ViewResult;
use App\Framework\View\TemplateRenderer;

/**
 * CRUD Service
 *
 * Service for handling admin CRUD operations using composition
 */
final readonly class CrudService
{
    public function __construct(
        private TemplateRenderer $renderer,
        private AdminFormFactory $formFactory
    ) {
    }

    /**
     * Render index view
     */
    public function renderIndex(
        CrudConfig $config,
        array $items,
        Request $request,
        ?array $pagination = null
    ): ViewResult {
        $data = [
            ...$config->toArray(),
            'items' => $items,
            'pagination' => $pagination,
            'currentUrl' => $request->uri(),
            'createUrl' => "/admin/{$config->resource}/create",
            'editUrl' => "/admin/{$config->resource}/edit",
            'viewUrl' => "/admin/{$config->resource}/view",
            'deleteUrl' => "/admin/{$config->resource}/delete",
        ];

        return new ViewResult('crud-index', $data);
    }

    /**
     * Render create form
     */
    public function renderCreate(
        CrudConfig $config,
        array $formFields,
        ?array $defaultData = null,
        ?string $helpText = null
    ): ViewResult {
        $formConfig = new AdminFormConfig(
            resource: $config->resource,
            action: "/admin/{$config->resource}/store",
            method: Method::POST,
            fields: $formFields,
            data: $defaultData ?? []
        );

        $form = $this->formFactory->create($formConfig);

        $data = [
            'title' => "Create {$config->resourceName}",
            'subtitle' => "Add a new {$config->resourceName} to the system",
            'formTitle' => "{$config->resourceName} Details",
            'resourceName' => $config->resourceName,
            'form' => $form->build(),
            'formId' => $form->getId(),
            'backUrl' => "/admin/{$config->resource}",
            'saveAndContinue' => true,
            'helpText' => $helpText,
        ];

        return new ViewResult('crud-create', $data);
    }

    /**
     * Render edit form
     */
    public function renderEdit(
        CrudConfig $config,
        string $id,
        array $formFields,
        array $itemData,
        ?array $metadata = null,
        ?string $helpText = null
    ): ViewResult {
        $formConfig = new AdminFormConfig(
            resource: $config->resource,
            action: "/admin/{$config->resource}/update/{$id}",
            method: Method::PUT,
            fields: $formFields,
            data: $itemData
        );

        $form = $this->formFactory->create($formConfig);

        $data = [
            'title' => "Edit {$config->resourceName}",
            'subtitle' => "Update {$config->resourceName} information",
            'formTitle' => "{$config->resourceName} Details",
            'resourceName' => $config->resourceName,
            'form' => $form->build(),
            'formId' => $form->getId(),
            'backUrl' => "/admin/{$config->resource}",
            'viewUrl' => "/admin/{$config->resource}/view/{$id}",
            'deleteUrl' => "/admin/{$config->resource}/delete/{$id}",
            'canView' => $config->canView,
            'canDelete' => $config->canDelete,
            'saveAndView' => true,
            'metadata' => $metadata,
            'helpText' => $helpText,
        ];

        return new ViewResult('crud-edit', $data);
    }

    /**
     * Render show/detail view
     */
    public function renderShow(
        CrudConfig $config,
        string $id,
        array $fields,
        ?array $metadata = null,
        ?array $relatedItems = null,
        ?array $actions = null
    ): ViewResult {
        $data = [
            'title' => "{$config->resourceName} Details",
            'subtitle' => "View {$config->resourceName} information",
            'detailsTitle' => "{$config->resourceName} Information",
            'resourceName' => $config->resourceName,
            'fields' => $fields,
            'backUrl' => "/admin/{$config->resource}",
            'editUrl' => "/admin/{$config->resource}/edit/{$id}",
            'deleteUrl' => "/admin/{$config->resource}/delete/{$id}",
            'canEdit' => $config->canEdit,
            'canDelete' => $config->canDelete,
            'metadata' => $metadata,
            'relatedItems' => $relatedItems,
            'actions' => $actions,
        ];

        return new ViewResult('crud-show', $data);
    }

    /**
     * Create redirect for successful create
     */
    public function redirectAfterCreate(
        CrudConfig $config,
        Request $request,
        mixed $itemId
    ): Redirect {
        // Check if "save and continue" was requested
        if ($request->parsedBody->get('action') === 'save-and-continue') {
            return Redirect::to("/admin/{$config->resource}/create")
                ->withFlash('success', "{$config->resourceName} created successfully!");
        }

        return Redirect::to("/admin/{$config->resource}")
            ->withFlash('success', "{$config->resourceName} created successfully!");
    }

    /**
     * Create redirect for successful update
     */
    public function redirectAfterUpdate(
        CrudConfig $config,
        Request $request,
        string $itemId
    ): Redirect {
        // Check if "save and view" was requested
        if ($request->parsedBody->get('action') === 'save-and-view') {
            return Redirect::to("/admin/{$config->resource}/view/{$itemId}")
                ->withFlash('success', "{$config->resourceName} updated successfully!");
        }

        return Redirect::to("/admin/{$config->resource}")
            ->withFlash('success', "{$config->resourceName} updated successfully!");
    }

    /**
     * Create redirect for successful delete
     */
    public function redirectAfterDelete(CrudConfig $config): Redirect
    {
        return Redirect::to("/admin/{$config->resource}")
            ->withFlash('success', "{$config->resourceName} deleted successfully!");
    }

    /**
     * Create redirect for errors
     */
    public function redirectWithError(string $message, ?array $inputData = null): Redirect
    {
        $redirect = Redirect::back()->withFlash('error', $message);

        if ($inputData !== null) {
            $redirect = $redirect->withInput($inputData);
        }

        return $redirect;
    }
}
