<?php

namespace App\Services;

use App\Models\Client\Client;
use App\Models\Contact\Hub\ContactMessageAttachment;
use App\Models\Document\Document;
use App\Models\Dsar\Dsar;
use Illuminate\Support\Collection;

/**
 * Normalises a client's evidence files into one uniform row shape so the Evidence
 * tab and the Evidence Workbench can present a single DSAR-grouped corpus.
 *
 * Every evidence file belongs to a DSAR — either an email attachment received in
 * response to it (ContactMessageAttachment) or a document uploaded directly onto
 * it (Document with owner = Dsar, from the DSAR page's uploader). The general
 * client Documents list is deliberately NOT a source: evidence must be attributed
 * to a DSAR, so handlers upload/migrate it onto the relevant DSAR.
 */
class EvidenceCorpus
{
    /**
     * @return Collection<int, array> one row per evidence file, all DSAR-attributed
     */
    public function forClient(Client $client): Collection
    {
        $rows = collect();

        if (!$client->claim) {
            return $rows;
        }

        // Explicit eager-load so each recipient's institution is always hydrated,
        // independent of whatever relation state is already cached on $client.
        $dsars = $client->claim->dsars()->with('institution.area.council')->get();

        foreach ($dsars as $dsar) {
            foreach ($dsar->evidenceAttachments() as $attachment) {
                $rows->push($this->attachmentRow($attachment, $dsar));
            }

            foreach ($dsar->documents()->with('evidenceItems')->latest()->get() as $document) {
                $rows->push($this->documentRow($document, $dsar));
            }
        }

        return $rows;
    }

    private function attachmentRow(ContactMessageAttachment $attachment, Dsar $dsar): array
    {
        $items   = $attachment->evidenceItems;
        $preview = $this->previewMeta($attachment->mime, $attachment->filename);

        return [
            'type'                  => 'attachment',
            'id'                    => $attachment->id,
            'model'                 => $attachment,
            'origin'                => 'Email attachment',
            'origin_icon'           => 'email-outline',
            'name'                  => $attachment->filename,
            'meta'                  => $attachment->mime,
            'is_pdf'                => str_contains($attachment->mime ?? '', 'pdf'),
            'is_image'              => $preview['is_image'],
            'file_ext'              => $preview['file_ext'],
            'doc_icon'              => $preview['doc_icon'],
            'doc_color'             => $preview['doc_color'],
            'preview_url'           => $preview['is_image'] ? route('inbox.attachment.preview', $attachment) : null,
            'institution'           => $dsar->institution,
            'institution_id'        => $dsar->institution_id,
            'dsar'                  => $dsar,
            'status'                => $attachment->evidence_status,
            'excluded'              => $attachment->isEvidenceExcluded(),
            'items'                 => $items,
            'count'                 => $items->count(),
            'confirmed'             => $items->filter->isConfirmed()->count(),
            'unreviewed'            => $items->filter->isUnreviewed()->count(),
            'dismissed'             => $items->filter->isDismissed()->count(),
            'view_url'              => $items->isNotEmpty()
                ? route('dsars.evidence', [$dsar, $attachment->id])
                : null,
        ];
    }

    private function documentRow(Document $document, Dsar $dsar): array
    {
        $items   = $document->evidenceItems;
        $preview = $this->previewMeta($document->file_type, $document->file_name ?? $document->display_name);

        return [
            'type'                  => 'document',
            'id'                    => $document->id,
            'model'                 => $document,
            'origin'                => 'DSAR upload',
            'origin_icon'           => 'cloud-upload-outline',
            'name'                  => $document->display_name,
            'meta'                  => strtoupper($document->file_type ?? ''),
            'is_pdf'                => strtolower($document->file_type ?? '') === 'pdf'
                || str_contains(strtolower($document->file_type ?? ''), 'pdf'),
            'is_image'              => $preview['is_image'],
            'file_ext'              => $preview['file_ext'],
            'doc_icon'              => $preview['doc_icon'],
            'doc_color'             => $preview['doc_color'],
            'preview_url'           => $preview['is_image'] ? route('documents.raw', $document) : null,
            // Document is uploaded onto the DSAR, so it inherits the DSAR's recipient.
            'institution'           => $dsar->institution,
            'institution_id'        => $dsar->institution_id,
            'dsar'                  => $dsar,
            'status'                => $document->evidence_status,
            'excluded'              => $document->isEvidenceExcluded(),
            'items'                 => $items,
            'count'                 => $items->count(),
            'confirmed'             => $items->filter->isConfirmed()->count(),
            'unreviewed'            => $items->filter->isUnreviewed()->count(),
            'dismissed'             => $items->filter->isDismissed()->count(),
            'view_url'              => $items->isNotEmpty()
                ? route('documents.evidence', $document)
                : null,
        ];
    }

    /**
     * Derive a lightweight doctype "tile" for the evidence list: an mdi icon +
     * short type label, and whether the file is an image (the only kind we render
     * as a real inline thumbnail — everything else shows the icon tile).
     *
     * @return array{is_image: bool, file_ext: string, doc_icon: string, doc_color: string}
     */
    private function previewMeta(?string $mimeOrType, ?string $filename): array
    {
        $type = strtolower(trim($mimeOrType ?? ''));
        $ext  = strtolower(pathinfo($filename ?? '', PATHINFO_EXTENSION));

        // Prefer the real extension; fall back to a bare type value that already
        // looks like an extension (e.g. Document->file_type is sometimes "pdf").
        if ($ext === '' && $type !== '' && !str_contains($type, '/')) {
            $ext = $type;
        }

        $isImage = str_starts_with($type, 'image/')
            || in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg', 'tiff', 'heic'], true);

        [$icon, $color] = match (true) {
            $type === 'application/pdf' || $ext === 'pdf'                        => ['file-pdf-box', '#dc2626'],
            $isImage                                                             => ['file-image', '#0ea5e9'],
            str_contains($type, 'word') || in_array($ext, ['doc', 'docx'], true) => ['file-word-box', '#2563eb'],
            str_contains($type, 'sheet') || str_contains($type, 'excel')
                || in_array($ext, ['xls', 'xlsx', 'csv'], true)                  => ['file-excel-box', '#16a34a'],
            str_contains($type, 'zip') || in_array($ext, ['zip', 'rar', '7z'], true) => ['folder-zip', '#d97706'],
            str_starts_with($type, 'audio/') || in_array($ext, ['mp3', 'wav', 'ogg', 'm4a'], true) => ['file-music', '#7c3aed'],
            $ext === 'eml' || str_contains($type, 'rfc822')                      => ['email', '#6b7280'],
            str_starts_with($type, 'text/') || in_array($ext, ['txt', 'md', 'json', 'xml', 'log'], true) => ['file-document-outline', '#6b7280'],
            default                                                              => ['file-outline', '#6b7280'],
        };

        return [
            'is_image' => $isImage,
            'file_ext' => $ext !== '' ? strtoupper($ext) : 'FILE',
            'doc_icon' => $icon,
            'doc_color' => $color,
        ];
    }
}
