<?php

declare(strict_types=1);

final class PlacementsController
{
    private const TYPES = [
        'reservation' => 'Réservation',
        'foster' => 'Placement en famille d’accueil',
        'return' => 'Retour au refuge',
        'cancellation' => 'Annulation',
    ];

    public static function save(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') {
            http_response_code(405);
            return;
        }
        $db = DB::pdo();
        $animalId = (int) ($_POST['animal_id'] ?? 0);
        $type = (string) ($_POST['event_type'] ?? '');
        $date = (string) ($_POST['event_date'] ?? '');
        if (!$animalId || !isset(self::TYPES[$type]) || !self::validDate($date)) {
            http_response_code(400);
            echo h(t('error.invalid_placement'));
            return;
        }
        $reason = trim((string) ($_POST['reason'] ?? ''));
        if (in_array($type, ['return', 'cancellation'], true) && $reason === '') {
            http_response_code(400);
            echo h(t('error.placement_reason_required'));
            return;
        }
        $s = $db->prepare('SELECT * FROM animals WHERE id=:id AND deleted_at IS NULL AND archived_at IS NULL');
        $s->execute([':id' => $animalId]);
        $animal = $s->fetch(PDO::FETCH_ASSOC);
        if (!$animal) {
            http_response_code(404);
            return;
        }
        $contactId = (int) ($_POST['contact_id'] ?? 0) ?: null;
        $contact = null;
        if ($contactId) {
            $s = $db->prepare('SELECT * FROM directory_contacts WHERE id=:id AND deleted_at IS NULL');
            $s->execute([':id' => $contactId]);
            $contact = $s->fetch(PDO::FETCH_ASSOC) ?: null;
            if (!$contact) {
                $contactId = null;
            }
        }
        $status = match ($type) {
            'reservation' => 'reserve',
            'foster' => 'fa',
            'return' => 'refuge',
            'cancellation' => in_array($animal['status'], ['reserve', 'réservé'], true) ? 'refuge' : $animal['status'],
        };
        $currentAddress = (string) ($animal['current_address'] ?? '');
        if ($type === 'foster' && $contact) {
            $currentAddress = implode(
                ' ',
                array_filter([$contact['address'] ?? '', $contact['postal_code'] ?? '', $contact['city'] ?? '']),
            );
        }
        if ($type === 'return') {
            $currentAddress = implode(
                ' ',
                array_filter([
                    AppSettings::get('association_address'),
                    AppSettings::get('association_postal_code'),
                    AppSettings::get('association_city'),
                ]),
            );
        }
        $notes = trim((string) ($_POST['notes'] ?? ''));
        $db->beginTransaction();
        try {
            $db->prepare(
                'INSERT INTO animal_placements(animal_id,event_type,event_date,contact_id,reason,notes,created_by) VALUES(:animal,:type,:date,:contact,:reason,:notes,:user)',
            )->execute([
                ':animal' => $animalId,
                ':type' => $type,
                ':date' => $date,
                ':contact' => $contactId,
                ':reason' => $reason ?: null,
                ':notes' => $notes ?: null,
                ':user' => Auth::id(),
            ]);
            $db->prepare(
                'UPDATE animals SET status=:status,refuge_room=NULL,care_box_key=NULL,current_address=:address,current_lat=NULL,current_lng=NULL,updated_at=datetime(\'now\') WHERE id=:id',
            )->execute([':status' => $status, ':address' => $currentAddress ?: null, ':id' => $animalId]);
            $after = $animal;
            $after['status'] = $status;
            $after['refuge_room'] = null;
            $after['care_box_key'] = null;
            $after['current_address'] = $currentAddress;
            LocationHistoryService::record(
                $db,
                $animalId,
                $animal,
                $after,
                'placement',
                self::TYPES[$type] . ($reason !== '' ? ' — ' . $reason : ''),
                $date . ' 12:00:00',
            );
            $details = [];
            if ($reason !== '') {
                $details[] = 'Motif : ' . $reason;
            }
            if ($notes !== '') {
                $details[] = 'Notes : ' . $notes;
            }
            $db->prepare(
                'INSERT INTO animal_history(animal_id,type,label,details,user_id,created_at) VALUES(:animal,\'placement\',:label,:details,:user,:date)',
            )->execute([
                ':animal' => $animalId,
                ':label' => self::TYPES[$type],
                ':details' => $details ? implode("\n", $details) : null,
                ':user' => Auth::id(),
                ':date' => $date . ' 12:00:00',
            ]);
            if ($type === 'foster' || $type === 'return') {
                self::movement($db, $animalId, $type, $contactId, $reason, $notes, $date);
            }
            $db->commit();
            header('Location: /animal?id=' . $animalId . '#tab-placements');
            exit();
        } catch (Throwable $e) {
            if ($db->inTransaction()) {
                $db->rollBack();
            }
            throw $e;
        }
    }

    private static function movement(
        PDO $db,
        int $animalId,
        string $type,
        ?int $contactId,
        string $reason,
        string $notes,
        string $date,
    ): void {
        $contact = null;
        if ($contactId) {
            $s = $db->prepare('SELECT name,phone,email,city FROM directory_contacts WHERE id=:id');
            $s->execute([':id' => $contactId]);
            $contact = $s->fetch(PDO::FETCH_ASSOC) ?: null;
        }
        $db->prepare(
            'INSERT INTO animal_movements(animal_id,kind,place,lieu,contact_name,contact_phone,contact_email,note,created_at) VALUES(:animal,:kind,:place,:lieu,:name,:phone,:email,:note,:date)',
        )->execute([
            ':animal' => $animalId,
            ':kind' => $type === 'return' ? 'entry' : 'exit',
            ':place' => $contact['city'] ?? null,
            ':lieu' => $type === 'return' ? 'Retour de placement' : 'Placement en FA',
            ':name' => $contact['name'] ?? null,
            ':phone' => $contact['phone'] ?? null,
            ':email' => $contact['email'] ?? null,
            ':note' =>
                trim(($reason !== '' ? 'Motif : ' . $reason : '') . ($notes !== '' ? "\nNotes : " . $notes : '')) ?:
                null,
            ':date' => $date . ' 12:00:00',
        ]);
    }
    private static function validDate(string $date): bool
    {
        $d = DateTimeImmutable::createFromFormat('!Y-m-d', $date);
        return $d !== false && $d->format('Y-m-d') === $date;
    }
}
