# Project Reconstruction Plan (PRP) for AI StyleGallery

This document outlines the architecture, functionality, and implementation details of the "AI StyleGallery" web application. It is intended to serve as a comprehensive guide for another AI agent or LLM to understand and potentially reconstruct a similar system.

## 1. Application Overview

**Primary Goal:** AI StyleGallery is a web application designed to allow users to transform their uploaded images by applying various AI-generated artistic styles. Users can manage their image gallery, apply styles via external AI services, and save or discard the results.

**Core Functionality:**
- **Image Upload:** Users can upload their own images to the gallery.
- **Style Application:** Users can select an image and choose from a predefined set of AI styles to apply.
- **AI Processing Integration:** The application interacts with external AI web services (e.g., ComfyUI, RunwareAI) to perform image transformations.
- **Gallery Management:** Users can view their original and styled images, and decide to keep (make permanent) or discard (delete) styled images.
- **Admin Panel:** An administrative interface for managing AI models, API providers, styles, users, and roles.

## 2. Core Technologies & Stack

*   **Languages:** PHP 8.3, JavaScript
*   **Frameworks & Runtimes:** Laravel 12.21.0, Vue.js 3.5.18, Inertia.js 1.3.0, Livewire 3.6.4, Vite 5.4.19
*   **Databases:** SQLite. Redis is used for caching.
*   **Key PHP Libraries/Dependencies:**
    *   Filament 3.3.34 (for the admin panel)
    *   Guzzle 7.9.3 (for HTTP requests)
    *   Laravel Sanctum 4.2.0 (for API authentication)
    *   Laravel Breeze 2.3.8 (authentication scaffolding)
    *   Laravel Pint 1.24.0 (code formatter)
    *   Laravel Prompts 0.3.6 (CLI prompts)
    *   Laravel Sail 1.44.0 (Docker development environment)
    *   Laravel Serializable Closure 2.0.4
    *   Laravel Tinker 2.10.1
    *   nesbot/carbon 3.10.2 (date/time library)
    *   predis/predis 3.1.0 (Redis client)
    *   phpunit/php-code-coverage 12.3.2
    *   phpunit/php-file-iterator 6.0.0
    *   phpunit/php-invoker 6.0.0
    *   phpunit/php-text-template 5.0.0
    *   phpunit/php-timer 8.0.0
    *   phpunit/phpunit 12.3.0
    *   ramsey/uuid 4.9.0 (UUID generation)
    *   spatie/laravel-package-tools 1.92.7
    *   tightenco/ziggy 2.5.3 (Laravel routes in JS)
    *   symfony/clock 7.3.0
    *   symfony/console 7.3.2
    *   symfony/css-selector 7.3.0
    *   symfony/deprecation-contracts 3.6.0
    *   symfony/error-handler 7.3.2
    *   symfony/event-dispatcher 7.3.0
    *   symfony/event-dispatcher-contracts 3.6.0
    *   symfony/finder 7.3.2
    *   symfony/html-sanitizer 7.3.2
    *   symfony/http-foundation 7.3.2
    *   symfony/http-kernel 7.3.2
    *   symfony/mailer 7.3.2
    *   symfony/mime 7.3.2
    *   symfony/polyfill-ctype 1.32.0
    *   symfony/polyfill-intl-grapheme 1.32.0
    *   symfony/polyfill-intl-idn 1.32.0
    *   symfony/polyfill-intl-normalizer 1.32.0
    *   symfony/polyfill-mbstring 1.32.0
    *   symfony/polyfill-php80 1.32.0
    *   symfony/polyfill-php83 1.32.0
    *   symfony/polyfill-uuid 1.32.0
    *   symfony/process 7.3.0
    *   symfony/routing 7.3.2
    *   symfony/service-contracts 3.6.0
    *   symfony/string 7.3.2
    *   symfony/translation 7.3.2
    *   symfony/translation-contracts 3.6.0
    *   symfony/uid 7.3.1
    *   symfony/var-dumper 7.3.2
    *   symfony/yaml 7.3.2
*   **Key JavaScript Libraries/Dependencies:**
    *   axios 1.11.0 (for frontend HTTP requests)
    *   tailwindcss 3.4.17 (for styling)
    *   @inertiajs/vue3 1.3.0
    *   @vitejs/plugin-vue 5.2.4
    *   @tailwindcss/forms 0.5.10
    *   autoprefixer 10.4.21
    *   postcss 8.5.6
    *   laravel-echo 2.1.7 (WebSocket client)
    *   pusher-js 8.4.0 (Pusher client for WebSockets)
    *   @fortawesome/fontawesome-svg-core 7.0.0
    *   @fortawesome/free-solid-svg-icons 7.0.0
    *   @fortawesome/vue-fontawesome 3.1.1
    *   vanilla-lazyload 19.1.3 (lazy loading images)
*   **Package Manager(s):** Composer for PHP, npm for JavaScript.

## 2. UI Structure (Frontend / Backend)


### 2.1. Frontend (Vue.js 3 with Inertia.js)

The frontend is a Single Page Application (SPA) built with Vue.js and Inertia.js, providing a dynamic user experience.

-   **Gallery View (`resources/js/Pages/Home.vue`):**
    -   Displays a grid of images (both original and styled).
    -   Images are fetched from `/api/images`.
    -   Includes pagination for large galleries.
    -   Periodically polls `/api/images` to refresh the gallery and show newly styled images.
-   **Image Context Menu (`resources/js/Components/ImageContextMenu.vue`):**
    -   Appears when a user taps on an image in the gallery.
    -   Provides options: "Drucken" (Print), "Stil ändern" (Change Style), "Schließen" (Close).
    -   Dynamically adjusts its position based on the tap location.
    -   Layout: Image preview (60% width) and options list (40% width).
-   **Style Selector (`resources/js/Components/StyleSelector.vue`):**
    -   Displayed when "Stil ändern" is selected from the context menu.
    -   Fetches and lists available AI styles from `/api/styles`.
    -   Allows users to select a style.
    -   Lazy loads style preview images using `IntersectionObserver` for performance.
    -   Includes a "back" arrow to return to the main context menu.
-   **Styled Image Display (Implicit):**
    -   Styled images appear in the main gallery after processing.
-   **User Authentication/Profile:**
    -   Login/Logout functionality (handled by Laravel Breeze/Fortify and Inertia.js).
    -   User profile management (via Laravel's built-in features and Filament admin panel).

### 2.2. Backend (Laravel 12 with Filament Admin Panel)

The backend is a monolithic Laravel application, with Filament providing a powerful administrative interface.

-   **Filament Admin Panel:**
    -   Accessible via `/admin`.
    -   Provides CRUD (Create, Read, Update, Delete) operations for the following resources:
        -   **AI Models (`app/Filament/Resources/AiModelResource.php`):** Manage AI models, their IDs, types, associated API providers, and specific parameters (JSON).
        -   **API Providers (`app/Filament/Resources/ApiProviderResource.php`):** Configure connections to external AI services (API URL, authentication tokens/credentials, plugin type).
        -   **Styles (`app/Filament/Resources/StyleResource.php`):** Define AI styles, including their title, prompt, description, preview image, parameters (JSON), and associated AI model.
        -   **Images (via direct database interaction and synchronization):** While there's an `ImageResource`, image management is largely automated through synchronization.
        -   **Users (`app/Filament/Resources/UserResource.php`):** Manage user accounts and assign roles.
        -   **Roles (`app/Filament/Resources/RoleResource.php`):** Define user roles and permissions.
        -   **Settings (`app/Filament/Resources/SettingResource.php`):** Manage application-wide settings.

## 3. Resources/Entities (Models)

The application's core data structures are represented by Eloquent models:

-   **`App\Models\User`**: Represents a user account.
    -   `id` (PK)
    -   `name`
    -   `email`
    -   `password`
    -   `role_id` (FK to `roles` table)
    -   `two_factor_secret`, `two_factor_recovery_codes`, `two_factor_confirmed_at` (for 2FA)
    -   `settings` (JSON)
-   **`App\Models\Image`**: Stores metadata for both original and styled images.
    -   `id` (PK)
    -   `path` (string, file path relative to storage disk)
    -   `uuid` (string, unique identifier for tracking)
    -   `original_image_id` (FK to `images` table, for styled images)
    -   `style_id` (FK to `styles` table, for styled images)
    -   `is_temp` (boolean, true for temporary styled images)
    -   `is_public` (boolean, true for publicly visible images)
    -   `comfyui_prompt_id` (string, for tracking ComfyUI jobs)
    -   `created_at`, `updated_at`
-   **`App\Models\Style`**: Defines an AI style.
    -   `id` (PK)
    -   `title` (string)
    -   `prompt` (text, the base prompt for the AI model)
    -   `description` (text)
    -   `preview_image` (string, path to style preview image)
    -   `parameters` (JSON, additional parameters for the AI plugin, cast to array)
    -   `ai_model_id` (FK to `ai_models` table)
    -   `enabled` (boolean)
    -   `created_at`, `updated_at`
-   **`App\Models\AiModel`**: Represents a specific AI model (e.g., Stable Diffusion v1.5).
    -   `id` (PK)
    -   `name` (string)
    -   `model_id` (string, identifier used by the AI service)
    -   `model_type` (string, e.g., "Stable Diffusion")
    -   `enabled` (boolean)
    -   `parameters` (JSON, additional parameters for the AI plugin, cast to array)
    -   `created_at`, `updated_at`
-   **`App\Models\ApiProvider`**: Configures connection details for an external AI service.
    -   `id` (PK)
    -   `name` (string, e.g., "ComfyUI API")
    -   `api_url` (string, base URL of the AI service)
    -   `username` (string, nullable)
    -   `password` (string, nullable)
    -   `token` (string, nullable)
    -   `plugin` (string, identifies the plugin to use, e.g., "comfyui", "runwareai")
    -   `enabled` (boolean)
    -   `created_at`, `updated_at`
-   **`App\Models\Role`**: Defines user roles for access control.
    -   `id` (PK)
    -   `name` (string, e.g., "admin", "user")
    -   `created_at`, `updated_at`
-   **`App\Models\Setting`**: Stores application-wide key-value settings.
    -   `id` (PK)
    -   `key` (string)
    -   `value` (text)
    -   `created_at`, `updated_at`

## 4. Database Structure (Schema)

Key tables and their relevant columns:

-   **`users`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `name`: `varchar(255)`
    -   `email`: `varchar(255) unique`
    -   `password`: `varchar(255)`
    -   `role_id`: `bigint unsigned null` (FK to `roles.id`)
    -   `two_factor_secret`: `text null`
    -   `two_factor_recovery_codes`: `text null`
    -   `two_factor_confirmed_at`: `timestamp null`
    -   `settings`: `json null`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

-   **`images`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `path`: `varchar(255)`
    -   `uuid`: `char(36) unique`
    -   `original_image_id`: `bigint unsigned null` (FK to `images.id`)
    -   `style_id`: `bigint unsigned null` (FK to `styles.id`)
    -   `is_temp`: `tinyint(1) default 0`
    -   `is_public`: `tinyint(1) default 1`
    -   `comfyui_prompt_id`: `varchar(255) null`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

-   **`styles`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `title`: `varchar(255)`
    -   `prompt`: `longtext`
    -   `description`: `longtext`
    -   `preview_image`: `varchar(255)`
    -   `parameters`: `json null`
    -   `ai_model_id`: `bigint unsigned` (FK to `ai_models.id`)
    -   `enabled`: `tinyint(1) default 1`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

-   **`ai_models`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `name`: `varchar(255)`
    -   `model_id`: `varchar(255)`
    -   `model_type`: `varchar(255) null`
    -   `enabled`: `tinyint(1) default 1`
    -   `parameters`: `json null`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

-   **`api_providers`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `name`: `varchar(255)`
    -   `api_url`: `varchar(255)`
    -   `username`: `varchar(255) null`
    -   `password`: `varchar(255) null`
    -   `token`: `varchar(255) null`
    -   `plugin`: `varchar(255)`
    -   `enabled`: `tinyint(1) default 1`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

-   **`roles`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `name`: `varchar(255) unique`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

    -   `api_provider_id`: `bigint unsigned` (FK to `api_providers.id`)

-   **`settings`**
    -   `id`: `bigint unsigned auto_increment primary key`
    -   `key`: `varchar(255) unique`
    -   `value`: `longtext`
    -   `created_at`: `timestamp null`
    -   `updated_at`: `timestamp null`

## 5. User Interactions

### 5.1. Frontend User Interactions

-   **Image Upload:** Users can upload images via a dedicated interface (not explicitly detailed in provided context, but implied by gallery functionality).
-   **Image Selection:** Tapping on an image in the gallery opens a context menu.
-   **Context Menu Actions:**
    -   "Drucken" (Print): Placeholder for printing functionality.
    -   "Stil ändern" (Change Style): Navigates to the style selection interface.
    -   "Schließen" (Close): Closes the context menu.
-   **Style Selection:**
    -   Users browse a list of available styles.
    -   Selecting a style initiates the AI image transformation process.
    -   "Back" arrow: Returns to the image context menu.
-   **Gallery Refresh:** The gallery automatically updates to show newly processed images (polling every 5 seconds).
-   **Authentication:** Users can log in and out.

### 5.2. Backend (Admin Panel) User Interactions

-   **Resource Management:** Full CRUD operations for AI Models, API Providers, Styles, Users, and Roles.
-   **Toggle Status:** Enable/disable AI Models, API Providers, and Styles.
-   **Duplication:** Duplicate existing AI Models and Styles to quickly create new ones.
-   **Settings Management:** Update application-wide settings.

## 6. External System Interactions

### 6.1. AI Web Services

The application integrates with external AI services for image processing. The specific plugin used is determined by the `plugin` field in the `ApiProvider` model.

-   **ComfyUI (via `App\Api\Plugins\ComfyUi.php`):**
    -   **Image Upload:** Sends image data (base64 encoded) to the ComfyUI server's `/upload/image` endpoint.
    -   **Prompt Queuing:** Sends the constructed workflow JSON to the ComfyUI server's `/prompt` endpoint.
    -   **Result Fetching:** Polls the ComfyUI server's `/history/{prompt_id}` endpoint to check the status and retrieve the base64 encoded styled image.
-   **RunwareAI (via `App\Api\Plugins\RunwareAi.php`):**
    -   **Image Upload:** Sends image data (base64 encoded) to the RunwareAI API.
    -   **Style Change Request:** Sends a request with prompt, seed image UUID, model ID, and merged parameters to the RunwareAI API for image inference.

### 6.2. Authentication

-   **Laravel Sanctum:** Used for API authentication, securing routes that require user login (e.g., keeping/deleting images, admin panel access).

## 7. Call Structure and Access Rights

### 7.1. API Routes (`routes/api.php`)

-   **Publicly Accessible Routes:**
    -   `GET /api/images`: Retrieves a list of images (public and temporary for unauthenticated users, all for authenticated users). Handled by `ImageController@index`.
    -   `GET /api/styles`: Retrieves a list of available styles. Handled by `StyleController@index`.
    -   `POST /api/images/style-change`: Initiates an AI style change request. Handled by `ImageController@styleChangeRequest`.
    -   `GET /api/comfyui-url`: Retrieves the ComfyUI API URL. Handled by `ImageController@getComfyUiUrl`.
    -   `GET /api/images/fetch-styled/{prompt_id}`: Fetches the result of a styled image request. Handled by `ImageController@fetchStyledImage`.
-   **Authenticated Routes (requires `auth:sanctum` middleware):**
    -   `GET /api/user`: Retrieves authenticated user details.
    -   `POST /api/admin/navigation-state`: Stores admin navigation state. Handled by `NavigationStateController@store`.
    -   `POST /api/images/keep`: Marks a temporary styled image as permanent. Handled by `ImageController@keepImage`.
    -   `DELETE /api/images/{image}`: Deletes an image. Handled by `ImageController@deleteImage`.
    -   `GET /api/images/status`: Retrieves the status of an image (placeholder for future use). Handled by `ImageController@getStatus`.

### 7.2. Web Routes (`routes/web.php`)

-   Standard Laravel web routes for serving the Inertia.js frontend. The main application entry point is typically handled by a route that returns an Inertia response (e.g., `Route::get('/', ...)`).

### 7.3. Access Rights

-   **API Authentication:** Laravel Sanctum is used to protect API routes. Users must be authenticated to access certain functionalities.
-   **Filament Admin Panel:** Access to the `/admin` panel is controlled by Filament's built-in authentication and authorization system, typically based on user roles.
-   **Image Visibility:**
    -   `is_public` flag on `Image` model: Controls whether an image is visible to unauthenticated users.
    -   `is_temp` flag on `Image` model: Identifies temporary styled images. Unauthenticated users can see their own temporary images.
-   **Resource Status:**
    -   `enabled` flag on `AiModel`, `ApiProvider`, and `Style` models: Controls whether these resources are active and usable within the application.

## 8. Detailed Description of Key Logic/Flows

### 8.1. Image Styling Process

1.  **User Action (Frontend):** A user selects an image in the gallery and chooses a style from the `StyleSelector` component.
2.  **Frontend Request:** The `Home.vue` component sends an `axios.post` request to `/api/images/style-change`, including the `image_id` and `style_id`.
3.  **Backend (ImageController@styleChangeRequest):**
    -   Retrieves the `Image` and `Style` models based on the provided IDs.
    -   Retrieves the associated `AiModel` and `ApiProvider` from the `Style` model.
    -   Loads the appropriate AI plugin (e.g., `ComfyUi`, `RunwareAi`) using `PluginLoader::getPlugin()`.
    -   Calls the `processImageStyleChange()` method on the loaded plugin, passing the `Image` and `Style` models.
4.  **AI Plugin (`ComfyUi.php` or `RunwareAi.php`):**
    -   **Image Upload:** The plugin first uploads the original image to the external AI service.
    -   **Parameter Merging:**
        -   It retrieves `parameters` from both the `AiModel` and the `Style` models.
        -   These parameters (which are JSON objects) are deeply merged using `array_replace_recursive()`. This ensures that specific parameters from the style can override or extend parameters defined at the model level.
    -   **Prompt Construction:** The plugin constructs the final prompt/workflow for the AI service.
        -   For ComfyUI, it takes the merged parameters (workflow JSON) and performs string replacements for placeholders like `__PROMPT__` (from `Style->prompt`), `__FILENAME__` (uploaded image filename), and `__MODEL_ID__` (from `AiModel->model_id`).
        -   Crucially, values for placeholders are JSON-encoded and then stripped of outer quotes to ensure safe injection into the JSON workflow, preventing syntax errors.
    -   **API Call:** The plugin sends the prepared request (e.g., prompt to ComfyUI, inference request to RunwareAI) to the external AI service.
    -   **Response Handling:** The plugin waits for a response from the AI service (e.g., `prompt_id` from ComfyUI, base64 image data from RunwareAI).
5.  **Backend (ImageController@styleChangeRequest - continued):**
    -   Receives the initial response from the plugin (e.g., `prompt_id`).
    -   Updates the `Image` record with the `comfyui_prompt_id` and `style_id` for tracking.
    -   Returns a JSON response to the frontend with the `prompt_id` and `image_uuid`.
6.  **Frontend (Home.vue - Polling for Result):**
    -   Upon receiving the `prompt_id`, the frontend starts polling `/api/images/fetch-styled/{prompt_id}`.
7.  **Backend (ImageController@fetchStyledImage):**
    -   Retrieves the `Image` record using the `comfyui_prompt_id`.
    -   Loads the relevant AI plugin.
    -   Calls a method on the plugin (e.g., `waitForResult` for ComfyUI) to retrieve the final base64 encoded styled image data.
    -   Decodes the base64 image, saves it to `public/storage/uploads` (e.g., `styled_UUID.png`).
    -   Creates a new `Image` record in the database for the styled image, linking it to the original image and style, and setting `is_temp` to `true`.
    -   Returns a JSON response with the styled image's details.
8.  **Frontend (Home.vue - Gallery Refresh):**
    -   Upon successful fetching of the styled image, the frontend calls `fetchImages()` to refresh the gallery, which now includes the newly created styled image.

### 8.2. Image Synchronization

-   The `ImageController@index` method performs a synchronization between the `public/storage/uploads` directory and the `images` table in the database.
-   It adds new image files found on disk to the database.
-   It removes database entries for images that no longer exist on disk.
-   This ensures the gallery always reflects the actual files in storage.

### 8.3. Parameter Merging Logic

-   The `parameters` fields in `Style` and `AiModel` are stored as JSON in the database and automatically cast to PHP arrays by Eloquent.
-   In the AI plugins (`ComfyUi.php`, `RunwareAi.php`), when constructing the AI service request:
    -   `$modelParams = $style->aiModel->parameters ?? [];`
    -   `$styleParams = $style->parameters ?? [];`
    -   `$mergedParams = array_replace_recursive($modelParams, $styleParams);`
    -   This `array_replace_recursive` function is crucial for deep merging, allowing style-specific parameters to override or extend model-level parameters.
-   Placeholders (`__PROMPT__`, `__FILENAME__`, `__MODEL_ID__`) within the merged JSON are replaced with actual values. These values are first JSON-encoded and then trimmed of their outer quotes to ensure they are safely inserted into the JSON structure without breaking it.

### 8.4. File Storage Configuration

-   The application uses Laravel's filesystem configuration.
-   The `public` disk is configured in `config/filesystems.php` to point directly to `public_path('storage')`.
-   Images uploaded via Filament (e.g., style previews) are stored in `public/storage/style_previews`.
-   The `public/storage` directory is a symbolic link to `storage/app/public` (though the configuration was adjusted to point directly to `public/storage` for the `public` disk).

This detailed overview should provide a solid foundation for understanding and rebuilding the AI StyleGallery application.
