<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\Csrf;
use App\Core\MailService;
use App\Core\Recaptcha;
use App\Core\Request;
use App\Core\Response;
use App\Core\Session;
use App\Core\Settings;
use App\Core\View;
use App\Models\ContactMessage;
use App\Models\ImageRepository;

final class ContactController
{
    /** @param array<string,string> $params */
    public function show(Request $request, array $params): Response
    {
        if (!self::enabled()) {
            return $this->notFound();
        }

        return $this->form([], [], Session::pull('contact_sent') === '1');
    }

    /** @param array<string,string> $params */
    public function submit(Request $request, array $params): Response
    {
        if (!self::enabled()) {
            return $this->notFound();
        }

        $old = [
            'name'    => trim((string) $request->input('name', '')),
            'email'   => trim((string) $request->input('email', '')),
            'phone'   => trim((string) $request->input('phone', '')),
            'message' => trim((string) $request->input('message', '')),
        ];

        // CSRF
        $token = $request->input('_csrf');
        if (!Csrf::check(is_string($token) ? $token : null)) {
            return $this->form($old, ['Session expirée, merci de réessayer.'], false);
        }

        // Honeypot : champ piège rempli => on fait comme si c'était envoyé, sans rien faire.
        if (trim((string) $request->input('website', '')) !== '') {
            Session::set('contact_sent', '1');
            return Response::redirect(base_url('contact'));
        }

        // Horodatage anti-bot (soumission trop rapide / périmée).
        $ts      = (int) $request->input('ts', 0);
        $elapsed = time() - $ts;
        if ($ts <= 0 || $elapsed < 2 || $elapsed > 3600) {
            return $this->form($old, ['Envoi invalide, merci de réessayer.'], false);
        }

        // Limitation de fréquence (par session).
        if (time() - (int) Session::get('contact_last', 0) < 30) {
            return $this->form($old, ['Merci de patienter avant un nouvel envoi.'], false);
        }

        // Validation
        $errors = [];
        if (mb_strlen($old['name']) < 2) {
            $errors[] = 'Le nom est requis.';
        }
        if (!filter_var($old['email'], FILTER_VALIDATE_EMAIL)) {
            $errors[] = 'L\'adresse email est invalide.';
        }
        if (mb_strlen($old['message']) < 10) {
            $errors[] = 'Le message est trop court.';
        }

        // reCAPTCHA (si actif)
        $rc = $request->input('g-recaptcha-response');
        if (!Recaptcha::verify(is_string($rc) ? $rc : null, $_SERVER['REMOTE_ADDR'] ?? null)) {
            $errors[] = 'La vérification anti-robot a échoué.';
        }

        if ($errors !== []) {
            return $this->form($old, $errors, false);
        }

        // Conservation + envoi (best-effort).
        $message = mb_substr($old['message'], 0, 5000);
        $phone   = mb_substr($old['phone'], 0, 40);
        ContactMessage::create($old['name'], $old['email'], $message, $_SERVER['REMOTE_ADDR'] ?? null);
        $body = "Nom : {$old['name']}\nEmail : {$old['email']}\n";
        if ($phone !== '') {
            $body .= "Téléphone : {$phone}\n";
        }
        $body .= "\n{$message}";
        MailService::send(
            'Contact site — ' . $old['name'],
            $body,
            $old['email'],
            $old['name']
        );

        Session::set('contact_last', time());
        Session::set('contact_sent', '1');

        return Response::redirect(base_url('contact'));
    }

    private static function enabled(): bool
    {
        return (string) Settings::get('contact_enabled', '0') === '1';
    }

    /**
     * @param array<string,string> $old
     * @param list<string> $errors
     */
    private function form(array $old, array $errors, bool $sent): Response
    {
        return Response::html(View::render('public/contact', [
            'pageTitle'     => 'Contact',
            'old'           => $old,
            'errors'        => $errors,
            'sent'          => $sent,
            'recaptcha'     => Recaptcha::isActive(),
            'recaptchaSite' => Recaptcha::siteKey(),
            'contactImage'  => self::randomImage(),
        ]));
    }

    /** Image d'illustration (une œuvre publiée au hasard) ou null. @return array{url:string,alt:string}|null */
    private static function randomImage(): ?array
    {
        $img = ImageRepository::randomPublished();
        if ($img === null) {
            return null;
        }
        $alt = trim((string) ($img['alt'] ?? ''));
        if ($alt === '') {
            $alt = (string) $img['name'];
        }
        return [
            'url' => media_url((int) $img['gallery_id'], (string) $img['filename'], 'thumb'),
            'alt' => $alt,
        ];
    }

    private function notFound(): Response
    {
        return Response::html(View::render('errors/404', ['pageTitle' => 'Page introuvable']), 404);
    }
}
