<?php

declare(strict_types=1);

namespace App\Services;

use App\Core\FileStore;

class InvoiceService
{
    private FileStore $invoices;
    private AuthService $auth;
    private CourseService $courses;

    public function __construct()
    {
        $this->invoices = new FileStore(storage_path('data/invoices.json'));
        $this->auth = new AuthService();
        $this->courses = new CourseService();
    }

    public function createForPayment(array $payment, array $order): array
    {
        $existing = $this->findByPayment((int) $payment['id']);

        if ($existing) {
            return $existing;
        }

        $student = $this->auth->findById((int) $payment['student_id']);
        $course = $this->courses->find((int) $payment['course_id']);
        $invoiceNumber = 'REC-' . date('Y') . '-' . str_pad((string) ($this->nextNumber()), 5, '0', STR_PAD_LEFT);

        return $this->invoices->insert([
            'order_id' => (int) $payment['order_id'],
            'payment_id' => (int) $payment['id'],
            'student_id' => (int) $payment['student_id'],
            'invoice_number' => $invoiceNumber,
            'document_type' => 'receipt',
            'buyer_name' => $student['name'] ?? 'Aluno',
            'buyer_email' => $student['email'] ?? '',
            'buyer_phone' => $student['phone'] ?? '',
            'buyer_nuit' => $student['profile']['nuit'] ?? '',
            'course_title' => $course['title'] ?? ($order['course_title'] ?? 'Curso'),
            'subtotal' => (float) ($order['subtotal'] ?? $payment['amount']),
            'discount_total' => (float) ($order['discount_total'] ?? 0),
            'tax_amount' => 0,
            'total' => (float) $payment['amount'],
            'currency' => 'MZN',
            'status' => 'issued',
            'issued_at' => date('c'),
            'created_at' => date('c'),
            'updated_at' => date('c'),
        ]);
    }

    public function invoicesForStudent(int $studentId): array
    {
        $items = array_values(array_filter(
            $this->invoices->all(),
            fn (array $invoice): bool => (int) ($invoice['student_id'] ?? 0) === $studentId
        ));

        usort($items, fn (array $a, array $b): int => strcmp($b['issued_at'] ?? '', $a['issued_at'] ?? ''));

        return $items;
    }

    public function all(array $filters = []): array
    {
        $search = strtolower(trim($filters['search'] ?? ''));
        $items = $this->invoices->all();

        if ($search !== '') {
            $items = array_filter($items, function (array $invoice) use ($search): bool {
                $haystack = strtolower(
                    ($invoice['invoice_number'] ?? '') . ' ' .
                    ($invoice['buyer_name'] ?? '') . ' ' .
                    ($invoice['buyer_email'] ?? '') . ' ' .
                    ($invoice['course_title'] ?? '')
                );

                return str_contains($haystack, $search);
            });
        }

        usort($items, fn (array $a, array $b): int => strcmp($b['issued_at'] ?? '', $a['issued_at'] ?? ''));

        return array_values($items);
    }

    public function find(int $id): ?array
    {
        foreach ($this->invoices->all() as $invoice) {
            if ((int) ($invoice['id'] ?? 0) === $id) {
                return $invoice;
            }
        }

        return null;
    }

    public function findByPayment(int $paymentId): ?array
    {
        foreach ($this->invoices->all() as $invoice) {
            if ((int) ($invoice['payment_id'] ?? 0) === $paymentId) {
                return $invoice;
            }
        }

        return null;
    }

    private function nextNumber(): int
    {
        $ids = array_column($this->invoices->all(), 'id');

        return $ids ? max($ids) + 1 : 1;
    }
}
