<?php

namespace App\Domain\Scraping\Infrastructure\ApiPlatform\Resource;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Post;
use ApiPlatform\OpenApi\Model\Operation as OpenApiOperation;
use ApiPlatform\OpenApi\Model\RequestBody;
use ApiPlatform\OpenApi\Model\Response as OpenApiResponse;
use App\Domain\Scraping\Infrastructure\ApiPlatform\State\Processor\TestScraperConfigurationStateProcessor;
use Symfony\Component\Validator\Constraints as Assert;

#[ApiResource(
    shortName: 'Scraping',
    operations: [
        new Post(
            uriTemplate: '/scraping/test-configuration',
            processor: TestScraperConfigurationStateProcessor::class,
            input: TestScraperConfigurationRequest::class,
            output: TestScraperConfigurationResource::class,
            status: 200,
            description: 'Teste une configuration de scraper sans l\'enregistrer',
            openapi: new OpenApiOperation(
                summary: 'Tester une configuration de scraper',
                description: 'Teste une configuration de scraper en temps réel sans l\'enregistrer dans la base de données. Cette API permet de valider les paramètres de scraping et de voir immédiatement les URLs d\'images qui seraient extraites.',
                tags: ['Scraping', 'Configuration'],
                requestBody: new RequestBody(
                    description: 'Configuration du scraper à tester',
                    content: new \ArrayObject([
                        'application/json' => [
                            'schema' => [
                                'type' => 'object',
                                'properties' => [
                                    'baseUrl' => [
                                        'type' => 'string',
                                        'format' => 'uri',
                                        'description' => 'URL de base du site web source',
                                        'example' => 'https://mangasite.example.com'
                                    ],
                                    'chapterUrlFormat' => [
                                        'type' => 'string',
                                        'description' => 'Format d\'URL pour accéder aux chapitres avec placeholders {slug} et {chapter}',
                                        'example' => 'https://mangasite.example.com/manga/{slug}/chapter/{chapter}'
                                    ],
                                    'scrapingType' => [
                                        'type' => 'string',
                                        'enum' => ['html', 'javascript'],
                                        'description' => 'Type de scraping à utiliser (html pour les sites statiques, javascript pour les sites dynamiques)',
                                        'example' => 'html'
                                    ],
                                    'testUrl' => [
                                        'type' => 'string',
                                        'format' => 'uri',
                                        'description' => 'URL complète d\'un chapitre existant à utiliser pour le test',
                                        'example' => 'https://mangasite.example.com/manga/one-piece/chapter/1'
                                    ],
                                    'mangaSlug' => [
                                        'type' => 'string',
                                        'description' => 'Slug du manga utilisé dans les URLs (sera utilisé pour construire les URLs futures)',
                                        'example' => 'one-piece'
                                    ],
                                    'chapterNumber' => [
                                        'type' => 'number',
                                        'minimum' => 0,
                                        'description' => 'Numéro du chapitre à tester',
                                        'example' => 1.0
                                    ],
                                    'imageSelector' => [
                                        'type' => 'string',
                                        'nullable' => true,
                                        'description' => 'Sélecteur CSS pour identifier les images dans la page',
                                        'example' => 'img.manga-page, .chapter-image img'
                                    ],
                                    'nextPageSelector' => [
                                        'type' => 'string',
                                        'nullable' => true,
                                        'description' => 'Sélecteur CSS pour le lien vers la page suivante (pour les lecteurs horizontaux)',
                                        'example' => 'a.next-page, .navigation .next'
                                    ],
                                    'chapterSelector' => [
                                        'type' => 'string',
                                        'nullable' => true,
                                        'description' => 'Sélecteur CSS pour identifier la zone contenant le chapitre',
                                        'example' => '.chapter-content, #manga-reader'
                                    ]
                                ],
                                'required' => ['baseUrl', 'chapterUrlFormat', 'scrapingType', 'testUrl', 'mangaSlug', 'chapterNumber']
                            ],
                            'examples' => [
                                'lecteur_vertical' => [
                                    'summary' => 'Configuration pour un lecteur vertical',
                                    'description' => 'Exemple de configuration pour un site avec toutes les images sur une seule page',
                                    'value' => [
                                        'baseUrl' => 'https://mangasite.example.com',
                                        'chapterUrlFormat' => 'https://mangasite.example.com/manga/{slug}/chapter/{chapter}',
                                        'scrapingType' => 'html',
                                        'testUrl' => 'https://mangasite.example.com/manga/one-piece/chapter/1',
                                        'mangaSlug' => 'one-piece',
                                        'chapterNumber' => 1.0,
                                        'imageSelector' => 'img.manga-page',
                                        'nextPageSelector' => null,
                                        'chapterSelector' => '.chapter-content'
                                    ]
                                ],
                                'lecteur_horizontal' => [
                                    'summary' => 'Configuration pour un lecteur horizontal',
                                    'description' => 'Exemple de configuration pour un site avec navigation page par page',
                                    'value' => [
                                        'baseUrl' => 'https://mangasite.example.com',
                                        'chapterUrlFormat' => 'https://mangasite.example.com/read/{slug}/{chapter}/1',
                                        'scrapingType' => 'html',
                                        'testUrl' => 'https://mangasite.example.com/read/one-piece/1/1',
                                        'mangaSlug' => 'one-piece',
                                        'chapterNumber' => 1.0,
                                        'imageSelector' => '#manga-image',
                                        'nextPageSelector' => 'a.next-page',
                                        'chapterSelector' => '.reader-container'
                                    ]
                                ]
                            ]
                        ]
                    ])
                ),
                responses: [
                    '200' => new OpenApiResponse(
                        description: 'Test de configuration réussi',
                        content: new \ArrayObject([
                            'application/json' => [
                                'schema' => [
                                    'type' => 'object',
                                    'properties' => [
                                        'success' => [
                                            'type' => 'boolean',
                                            'description' => 'Indique si le test a réussi'
                                        ],
                                        'imageUrls' => [
                                            'type' => 'array',
                                            'items' => [
                                                'type' => 'string',
                                                'format' => 'uri'
                                            ],
                                            'description' => 'Liste des URLs d\'images trouvées'
                                        ],
                                        'totalImages' => [
                                            'type' => 'integer',
                                            'description' => 'Nombre total d\'images trouvées'
                                        ],
                                        'testedUrl' => [
                                            'type' => 'string',
                                            'format' => 'uri',
                                            'description' => 'URL qui a été testée'
                                        ],
                                        'scrapingType' => [
                                            'type' => 'string',
                                            'description' => 'Type de scraping utilisé'
                                        ],
                                        'errors' => [
                                            'type' => 'array',
                                            'items' => [
                                                'type' => 'object',
                                                'properties' => [
                                                    'type' => [
                                                        'type' => 'string',
                                                        'description' => 'Type d\'erreur (selector_error, url_error, general_error)'
                                                    ],
                                                    'field' => [
                                                        'type' => 'string',
                                                        'description' => 'Champ concerné par l\'erreur'
                                                    ],
                                                    'message' => [
                                                        'type' => 'string',
                                                        'description' => 'Message d\'erreur détaillé'
                                                    ],
                                                    'suggestion' => [
                                                        'type' => 'string',
                                                        'description' => 'Suggestion pour corriger l\'erreur'
                                                    ]
                                                ]
                                            ],
                                            'description' => 'Liste des erreurs détaillées (vide en cas de succès)'
                                        ]
                                    ]
                                ],
                                'examples' => [
                                    'succes' => [
                                        'summary' => 'Test réussi',
                                        'value' => [
                                            'success' => true,
                                            'imageUrls' => [
                                                'https://mangasite.example.com/images/chapter1/page1.jpg',
                                                'https://mangasite.example.com/images/chapter1/page2.jpg',
                                                'https://mangasite.example.com/images/chapter1/page3.jpg'
                                            ],
                                            'totalImages' => 3,
                                            'testedUrl' => 'https://mangasite.example.com/manga/one-piece/chapter/1',
                                            'scrapingType' => 'html',
                                            'errors' => []
                                        ]
                                    ],
                                    'echec_selecteur' => [
                                        'summary' => 'Échec - Sélecteur invalide',
                                        'value' => [
                                            'success' => false,
                                            'imageUrls' => [],
                                            'totalImages' => 0,
                                            'testedUrl' => 'https://mangasite.example.com/manga/one-piece/chapter/1',
                                            'scrapingType' => 'html',
                                            'errors' => [
                                                [
                                                    'type' => 'selector_error',
                                                    'field' => 'imageSelector',
                                                    'message' => 'Le sélecteur d\'image \'.invalid-selector\' ne trouve aucun élément sur la page',
                                                    'suggestion' => 'Vérifiez que le sélecteur CSS est correct et qu\'il correspond aux éléments d\'image sur la page'
                                                ]
                                            ]
                                        ]
                                    ],
                                    'echec_url' => [
                                        'summary' => 'Échec - URL inaccessible',
                                        'value' => [
                                            'success' => false,
                                            'imageUrls' => [],
                                            'totalImages' => 0,
                                            'testedUrl' => 'https://invalid-site.example.com/chapter/1',
                                            'scrapingType' => 'html',
                                            'errors' => [
                                                [
                                                    'type' => 'url_error',
                                                    'field' => 'testUrl',
                                                    'message' => 'Impossible d\'accéder à l\'URL de test: https://invalid-site.example.com/chapter/1',
                                                    'suggestion' => 'Vérifiez que l\'URL est correcte et accessible, et que le chapitre existe'
                                                ]
                                            ]
                                        ]
                                    ]
                                ]
                            ]
                        ])
                    ),
                    '422' => new OpenApiResponse(
                        description: 'Erreur de validation des données d\'entrée',
                        content: new \ArrayObject([
                            'application/json' => [
                                'schema' => [
                                    'type' => 'object',
                                    'properties' => [
                                        'type' => [
                                            'type' => 'string',
                                            'example' => 'https://tools.ietf.org/html/rfc2616#section-10'
                                        ],
                                        'title' => [
                                            'type' => 'string',
                                            'example' => 'An error occurred'
                                        ],
                                        'detail' => [
                                            'type' => 'string',
                                            'example' => 'baseUrl: L\'URL de base doit être une URL valide'
                                        ],
                                        'violations' => [
                                            'type' => 'array',
                                            'items' => [
                                                'type' => 'object',
                                                'properties' => [
                                                    'propertyPath' => [
                                                        'type' => 'string',
                                                        'description' => 'Champ contenant l\'erreur'
                                                    ],
                                                    'message' => [
                                                        'type' => 'string',
                                                        'description' => 'Message d\'erreur de validation'
                                                    ]
                                                ]
                                            ]
                                        ]
                                    ]
                                ],
                                'example' => [
                                    'type' => 'https://symfony.com/errors/validation',
                                    'title' => 'Validation Failed',
                                    'detail' => 'baseUrl: L\'URL de base doit être une URL valide',
                                    'violations' => [
                                        [
                                            'propertyPath' => 'baseUrl',
                                            'message' => 'L\'URL de base doit être une URL valide'
                                        ]
                                    ]
                                ]
                            ]
                        ])
                    )
                ]
            )
        ),
    ]
)]
readonly class TestScraperConfigurationRequest
{
    public function __construct(
        #[ApiProperty(
            description: 'URL de base du site web source de mangas',
            example: 'https://mangasite.example.com',
            schema: ['type' => 'string', 'format' => 'uri']
        )]
        #[Assert\NotBlank(message: 'L\'URL de base est obligatoire')]
        #[Assert\Url(message: 'L\'URL de base doit être une URL valide')]
        public string $baseUrl,
        #[ApiProperty(
            description: 'Format d\'URL pour accéder aux chapitres. Utilisez {slug} pour le nom du manga et {chapter} pour le numéro de chapitre',
            example: 'https://mangasite.example.com/manga/{slug}/chapter/{chapter}',
            schema: ['type' => 'string', 'pattern' => '.*\{slug\}.*\{chapter\}.*']
        )]
        #[Assert\NotBlank(message: 'Le format d\'URL de chapitre est obligatoire')]
        public string $chapterUrlFormat,
        #[ApiProperty(
            description: 'Type de scraping à utiliser. "html" pour les sites statiques, "javascript" pour les sites avec contenu dynamique',
            example: 'html',
            schema: ['type' => 'string', 'enum' => ['html', 'javascript']]
        )]
        #[Assert\NotBlank(message: 'Le type de scraping est obligatoire')]
        #[Assert\Choice(choices: ['html', 'javascript'], message: 'Le type de scraping doit être html ou javascript')]
        public string $scrapingType,
        #[ApiProperty(
            description: 'URL complète d\'un chapitre existant à utiliser pour tester la configuration. Cette URL doit être accessible et contenir des images',
            example: 'https://mangasite.example.com/manga/one-piece/chapter/1',
            schema: ['type' => 'string', 'format' => 'uri']
        )]
        #[Assert\NotBlank(message: 'L\'URL de test est obligatoire')]
        #[Assert\Url(message: 'L\'URL de test doit être une URL valide')]
        public string $testUrl,
        #[ApiProperty(
            description: 'Identifiant du manga utilisé dans les URLs (slug). Sera utilisé pour remplacer {slug} dans le format d\'URL',
            example: 'one-piece',
            schema: ['type' => 'string', 'pattern' => '^[a-z0-9-_]+$']
        )]
        #[Assert\NotBlank(message: 'Le slug du manga est obligatoire')]
        public string $mangaSlug,
        #[ApiProperty(
            description: 'Numéro du chapitre à tester. Peut être décimal pour les chapitres spéciaux (ex: 1.5)',
            example: 1.0,
            schema: ['type' => 'number', 'minimum' => 0]
        )]
        #[Assert\NotBlank(message: 'Le numéro de chapitre est obligatoire')]
        #[Assert\Type(type: 'numeric', message: 'Le numéro de chapitre doit être numérique')]
        #[Assert\Positive(message: 'Le numéro de chapitre doit être positif')]
        public float $chapterNumber,
        #[ApiProperty(
            description: 'Sélecteur CSS pour identifier les images du manga sur la page. Exemples: "img.manga-page", ".chapter img", "#reader img"',
            example: 'img.manga-page, .chapter-image img',
            schema: ['type' => 'string', 'nullable' => true, 'maxLength' => 500]
        )]
        #[Assert\Length(min: 1, max: 500, minMessage: 'Le sélecteur d\'image ne peut pas être vide', maxMessage: 'Le sélecteur d\'image est trop long')]
        public ?string $imageSelector = null,
        #[ApiProperty(
            description: 'Sélecteur CSS pour le lien vers la page suivante (requis pour les lecteurs horizontaux). Exemples: "a.next", ".navigation .next-page"',
            example: 'a.next-page, .navigation .next',
            schema: ['type' => 'string', 'nullable' => true, 'maxLength' => 500]
        )]
        #[Assert\Length(max: 500, maxMessage: 'Le sélecteur de page suivante est trop long')]
        public ?string $nextPageSelector = null,
        #[ApiProperty(
            description: 'Sélecteur CSS pour délimiter la zone contenant le chapitre (optionnel). Utile pour cibler une zone spécifique de la page',
            example: '.chapter-content, #manga-reader',
            schema: ['type' => 'string', 'nullable' => true, 'maxLength' => 500]
        )]
        #[Assert\Length(max: 500, maxMessage: 'Le sélecteur de chapitre est trop long')]
        public ?string $chapterSelector = null,
    ) {
    }
}
