<?php
declare(strict_types=1);

namespace App\Repositories;

use App\Json\FileStore;

class JsonAppointmentRepository implements AppointmentRepository
{
    public function __construct(private FileStore $store) {}

    private function list(): array
    {
        $d = $this->store->read();
        return $d['appointments'] ?? [];
    }

    public function find(string $id): ?array
    {
        foreach ($this->list() as $a) if (($a['id'] ?? null) === $id) return $a;
        return null;
    }

    public function all(array $filters = []): array
    {
        $list = $this->list();
        if (!empty($filters['status'])) {
            $list = array_values(array_filter($list, fn($a) => ($a['status'] ?? '') === $filters['status']));
        }
        if (!empty($filters['artist_id'])) {
            $list = array_values(array_filter($list, fn($a) => ($a['artist_id'] ?? '') === $filters['artist_id']));
        }
        if (!empty($filters['from'])) {
            $list = array_values(array_filter($list, fn($a) => ($a['start_at'] ?? '') >= $filters['from']));
        }
        if (!empty($filters['to'])) {
            $list = array_values(array_filter($list, fn($a) => ($a['start_at'] ?? '') <= $filters['to']));
        }
        usort($list, fn($a, $b) => strcmp((string)($a['start_at'] ?? ''), (string)($b['start_at'] ?? '')));
        return $list;
    }

    public function byStatus(string $status): array
    {
        return $this->all(['status' => $status]);
    }

    public function forArtistOnDate(string $artistId, string $date): array
    {
        $from = $date . 'T00:00:00';
        $to   = $date . 'T23:59:59';
        // Also include "no preference" appointments (artist_id null/empty) since they may
        // eventually be assigned to this artist and should block the slot.
        $list = $this->list();
        $list = array_values(array_filter($list, function ($a) use ($artistId, $from, $to) {
            $start = (string)($a['start_at'] ?? '');
            if ($start < $from || $start > $to) return false;
            $aid = (string)($a['artist_id'] ?? '');
            return $aid === $artistId || $aid === '';
        }));
        usort($list, fn($a, $b) => strcmp((string)($a['start_at'] ?? ''), (string)($b['start_at'] ?? '')));
        return $list;
    }

    public function forCustomer(string $customerId): array
    {
        $list = array_values(array_filter($this->list(), fn($a) => ($a['customer_id'] ?? '') === $customerId));
        usort($list, fn($a, $b) => strcmp((string)($b['start_at'] ?? ''), (string)($a['start_at'] ?? '')));
        return $list;
    }

    public function save(array $appt): array
    {
        $now = now_iso();
        $appt['updated_at'] = $now;
        if (empty($appt['id'])) {
            $appt['id'] = uuid();
            $appt['created_at'] = $now;
            $appt['status'] = $appt['status'] ?? 'PENDING';
            $appt['source'] = $appt['source'] ?? 'ONLINE';
        }
        $this->store->transaction(function ($d) use (&$appt) {
            $list = $d['appointments'] ?? [];
            $found = false;
            foreach ($list as $i => $a) {
                if (($a['id'] ?? null) === $appt['id']) {
                    $list[$i] = array_merge($a, $appt);
                    $appt = $list[$i];
                    $found = true;
                    break;
                }
            }
            if (!$found) $list[] = $appt;
            $d['appointments'] = $list;
            return $d;
        });
        return $appt;
    }

    public function delete(string $id): void
    {
        $this->store->transaction(function ($d) use ($id) {
            $d['appointments'] = array_values(array_filter($d['appointments'] ?? [], fn($a) => ($a['id'] ?? null) !== $id));
            return $d;
        });
    }
}
