<?php

declare(strict_types=1);

final class PublicSiteController
{
    public static function usesRoot(): bool
    {
        return AppSettings::get('public_site_routing') === 'root';
    }
    public static function handles(string $path): bool
    {
        if ($path === '/site' || str_starts_with($path, '/site/')) {
            return true;
        }
        return self::usesRoot() &&
            in_array(
                $path,
                [
                    '/',
                    '/animaux',
                    '/adoption',
                    '/presentation',
                    '/dons',
                    '/contact',
                    '/mentions-legales',
                    '/confidentialite',
                    '/logo-association',
                ],
                true,
            );
    }
    public static function url(string $page = 'home', array $query = []): string
    {
        $root = self::usesRoot();
        $path = match ($page) {
            'home' => $root ? '/' : '/site',
            'animals' => $root ? '/animaux' : '/site/animaux',
            'animal' => $root ? '/adoption' : '/site/animal',
            'about' => $root ? '/presentation' : '/site/presentation',
            'donation' => $root ? '/dons' : '/site/dons',
            'contact' => $root ? '/contact' : '/site/contact',
            'legal' => $root ? '/mentions-legales' : '/site/mentions-legales',
            'privacy' => $root ? '/confidentialite' : '/site/confidentialite',
            'logo' => $root ? '/logo-association' : '/site/logo',
            default => $root ? '/' : '/site',
        };
        return $path . ($query ? '?' . http_build_query($query) : '');
    }
    public static function dispatch(string $path): void
    {
        $path = self::normalize($path);
        if (AppSettings::get('public_site_enabled') !== '1') {
            http_response_code(404);
            self::render('public_site_unavailable.php', ['title' => t('public_site.unavailable')]);
            return;
        }
        if ($path === '/site/logo') {
            self::logo();
            return;
        }
        match ($path) {
            '/site', '/site/' => self::home(),
            '/site/animaux' => self::animals(),
            '/site/animal' => self::animal(),
            '/site/dons' => self::donation(),
            '/site/contact' => self::contact(),
            '/site/presentation' => self::about(),
            '/site/mentions-legales' => self::legal(),
            '/site/confidentialite' => self::privacy(),
            default => self::notFound(),
        };
    }
    private static function normalize(string $path): string
    {
        return match ($path) {
            '/' => '/site',
            '/animaux' => '/site/animaux',
            '/adoption' => '/site/animal',
            '/presentation' => '/site/presentation',
            '/dons' => '/site/dons',
            '/contact' => '/site/contact',
            '/mentions-legales' => '/site/mentions-legales',
            '/confidentialite' => '/site/confidentialite',
            '/logo-association' => '/site/logo',
            default => $path,
        };
    }
    private static function home(): void
    {
        $db = DB::pdo();
        $animals = self::animalQuery('', 8);
        $counts = $db
            ->query(
                "SELECT species,COUNT(*) count FROM animals WHERE website_published=1 AND adoption_availability='available' AND archived_at IS NULL AND deleted_at IS NULL AND status NOT IN ('adopte','decede') GROUP BY species ORDER BY species",
            )
            ->fetchAll(PDO::FETCH_ASSOC);
        self::render('public_site_home.php', [
            'title' => AppSettings::get('public_site_home_title'),
            'animals' => $animals,
            'speciesCounts' => $counts,
        ]);
    }
    private static function animals(): void
    {
        $species = SpeciesService::normalize((string) ($_GET['espece'] ?? ''));
        if ($species !== '' && !SpeciesService::exists($species, false)) {
            $species = '';
        }
        self::render('public_site_animals.php', [
            'title' => t('public_site.animals'),
            'animals' => self::animalQuery($species, 200),
            'selectedSpecies' => $species,
            'publicSpecies' => self::species(),
        ]);
    }
    private static function animal(): void
    {
        $id = (int) ($_GET['id'] ?? 0);
        $s = DB::pdo()->prepare(
            "SELECT a.*,s.name species_name,s.icon species_icon,(SELECT filename FROM animal_photos p WHERE p.animal_id=a.id AND p.is_public=1 ORDER BY p.is_primary DESC,p.id DESC LIMIT 1) primary_photo FROM animals a LEFT JOIN ref_species s ON s.code=a.species WHERE a.id=? AND a.website_published=1 AND a.adoption_availability='available' AND a.archived_at IS NULL AND a.deleted_at IS NULL AND a.status NOT IN ('adopte','decede')",
        );
        $s->execute([$id]);
        $animal = $s->fetch(PDO::FETCH_ASSOC);
        if (!$animal) {
            self::notFound();
            return;
        }
        $p = DB::pdo()->prepare(
            'SELECT filename,caption FROM animal_photos WHERE animal_id=? AND is_public=1 ORDER BY is_primary DESC,id DESC',
        );
        $p->execute([$id]);
        self::render('public_site_animal.php', [
            'title' => $animal['name'],
            'animal' => $animal,
            'photos' => $p->fetchAll(PDO::FETCH_ASSOC),
        ]);
    }
    private static function donation(): void
    {
        self::render('public_site_text.php', [
            'title' => AppSettings::get('public_site_donation_title'),
            'content' => AppSettings::get('public_site_donation_text'),
            'kind' => 'donation',
        ]);
    }
    private static function contact(): void
    {
        self::render('public_site_contact.php', ['title' => t('public_site.contact')]);
    }
    private static function about(): void
    {
        if (AppSettings::get('public_site_about_enabled') !== '1') {
            self::notFound();
            return;
        }
        self::render('public_site_text.php', [
            'title' => AppSettings::get('public_site_about_title'),
            'content' => AppSettings::get('public_site_about_text'),
            'kind' => 'about',
        ]);
    }
    private static function legal(): void
    {
        self::render('public_site_text.php', [
            'title' => t('public_site.legal'),
            'content' => self::legalText(),
            'kind' => 'legal',
        ]);
    }
    private static function privacy(): void
    {
        self::render('public_site_text.php', [
            'title' => t('public_site.privacy'),
            'content' => self::privacyText(),
            'kind' => 'privacy',
        ]);
    }
    public static function legalText(?array $settings = null): string
    {
        $settings ??= AppSettings::all();
        $custom = trim((string) ($settings['public_site_legal_text'] ?? ''));
        if ($custom !== '') {
            return $custom;
        }
        $address =
            implode(
                ', ',
                array_filter([
                    $settings['association_address'] ?? '',
                    trim(($settings['association_postal_code'] ?? '') . ' ' . ($settings['association_city'] ?? '')),
                ]),
            ) ?:
            t('public_site.to_complete');
        return t('public_site.default_legal', [
            'association' => $settings['association_name'] ?: t('public_site.to_complete'),
            'address' => $address,
            'email' => $settings['association_email'] ?: t('public_site.to_complete'),
            'rna' => $settings['association_rna'] ?: t('public_site.to_complete'),
            'siret' => $settings['association_siret'] ?: t('public_site.to_complete'),
        ]);
    }
    public static function privacyText(?array $settings = null): string
    {
        $settings ??= AppSettings::all();
        $custom = trim((string) ($settings['public_site_privacy_text'] ?? ''));
        if ($custom !== '') {
            return $custom;
        }
        $address =
            implode(
                ', ',
                array_filter([
                    $settings['association_address'] ?? '',
                    trim(($settings['association_postal_code'] ?? '') . ' ' . ($settings['association_city'] ?? '')),
                ]),
            ) ?:
            t('public_site.to_complete');
        return t('public_site.default_privacy', [
            'association' => $settings['association_name'] ?: t('public_site.to_complete'),
            'address' => $address,
            'email' => $settings['association_email'] ?: t('public_site.to_complete'),
        ]);
    }
    private static function logo(): void
    {
        $path = AssociationBrand::path();
        if (!$path) {
            http_response_code(404);
            return;
        }
        $mime = (new finfo(FILEINFO_MIME_TYPE))->file($path) ?: 'application/octet-stream';
        header('Content-Type: ' . $mime);
        header('Content-Length: ' . filesize($path));
        header('Cache-Control: public,max-age=3600');
        readfile($path);
    }
    private static function animalQuery(string $species, int $limit): array
    {
        $sql =
            "SELECT a.id,a.name,a.species,a.sex,a.birth_date,a.birth_is_estimated,a.birth_estimated_months,a.breed,a.color,a.sterilization_status,a.compatibility_dogs,a.compatibility_cats,a.compatibility_children,a.house_trained,a.website_description,s.name species_name,s.icon species_icon,(SELECT filename FROM animal_photos p WHERE p.animal_id=a.id AND p.is_public=1 ORDER BY p.is_primary DESC,p.id DESC LIMIT 1) primary_photo FROM animals a LEFT JOIN ref_species s ON s.code=a.species WHERE a.website_published=1 AND a.adoption_availability='available' AND a.archived_at IS NULL AND a.deleted_at IS NULL AND a.status NOT IN ('adopte','decede')";
        $params = [];
        if ($species !== '') {
            $sql .= ' AND a.species=:species';
            $params[':species'] = $species;
        }
        $sql .= ' ORDER BY a.updated_at DESC,a.name COLLATE NOCASE LIMIT ' . max(1, min(500, $limit));
        $s = DB::pdo()->prepare($sql);
        $s->execute($params);
        return $s->fetchAll(PDO::FETCH_ASSOC);
    }
    private static function species(): array
    {
        return DB::pdo()
            ->query(
                "SELECT s.code,s.name,s.icon,COUNT(a.id) count FROM ref_species s JOIN animals a ON a.species=s.code AND a.website_published=1 AND a.adoption_availability='available' AND a.archived_at IS NULL AND a.deleted_at IS NULL AND a.status NOT IN ('adopte','decede') GROUP BY s.id ORDER BY s.sort_order,s.name COLLATE NOCASE",
            )
            ->fetchAll(PDO::FETCH_ASSOC);
    }
    private static function render(string $view, array $vars = []): void
    {
        extract($vars, EXTR_SKIP);
        $settings = AppSettings::all();
        $publicSpecies = self::species();
        require dirname(__DIR__) . '/Views/public_site_layout.php';
    }
    private static function notFound(): void
    {
        http_response_code(404);
        self::render('public_site_unavailable.php', ['title' => t('public_site.not_found')]);
    }
}
