<?php

declare(strict_types=1);

namespace App\Http\Resources;

use App\Models\Report;
use App\Support\FileUrl;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class ReportResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'user_id' => $this->user_id,
            'project_id' => $this->project_id,
            'producer_id' => $this->producer_id,
            'product_id' => $this->product_id,
            'type' => (int) $this->type,
            'title' => $this->title,
            'period' => $this->period,
            'date' => $this->date?->toDateString(),
            'report_at' => $this->report_at?->toISOString(),
            'status' => $this->workflow_status ?? $this->status,
            'workflow_status' => $this->workflow_status,
            'publish_status' => $this->status,
            'desc' => $this->desc,
            'written_report' => $this->written_report,
            'health_type' => $this->when(
                (int) $this->type === Report::TYPE_HEALTH,
                $this->report_type
            ),
            'report_type' => $this->report_type,
            'disease_name' => $this->disease_name,
            'diagnosis' => $this->diagnosis,
            'expert_opinion' => $this->expert_opinion,
            'next_visit_at' => $this->next_visit_at?->toDateString(),
            'total_cost' => $this->total_cost !== null ? (int) $this->total_cost : null,
            'invoice_image' => FileUrl::url($this->invoice_image),
            'product_weight' => $this->product_weight !== null ? (float) $this->product_weight : null,
            'unit' => $this->unit,
            'create_invoice' => (bool) ($this->create_invoice ?? false),
            'attachments' => $this->formatFiles($this->attachments),
            'documents' => $this->formatFiles($this->documents),
            'metrics' => $this->metrics,
            'data' => $this->data,
            'summary' => $this->when(
                (int) $this->type === Report::TYPE_GROWTH && $this->relationLoaded('items'),
                fn () => [
                    'avg' => $this->itemsAverage(),
                    'min' => $this->itemsMin(),
                    'max' => $this->itemsMax(),
                    'items_count' => $this->items->count(),
                    'groups' => $this->items
                        ->groupBy(fn ($item) => $item->group_name ?: 'default')
                        ->map(fn ($group, $name) => [
                            'group_name' => $name === 'default' ? null : $name,
                            'avg' => round((float) $group->map->resolveAverage()->filter()->avg(), 3),
                            'min' => $group->pluck('min_value')->filter()->min(),
                            'max' => $group->pluck('max_value')->filter()->max(),
                            'products_count' => $group->count(),
                        ])->values(),
                ]
            ),
            'mix_type' => $this->mix_type,
            'mix_type_label' => $this->when(
                (int) $this->type === Report::TYPE_RATION && $this->mix_type,
                fn () => Report::mixTypeOptions()[$this->mix_type] ?? $this->mix_type
            ),
            'ration_type' => $this->ration_type,
            'warnings' => $this->warnings,
            'water_temp' => $this->water_temp !== null ? (float) $this->water_temp : null,
            'water_per_unit_daily' => $this->water_per_unit_daily !== null ? (float) $this->water_per_unit_daily : null,
            'wait_between_meals_hours' => $this->wait_between_meals_hours !== null ? (float) $this->wait_between_meals_hours : null,
            'admin_reason' => $this->admin_reason,
            'created_by' => $this->created_by,
            'updated_by' => $this->updated_by,
            'created_at' => $this->created_at?->toISOString(),
            'updated_at' => $this->updated_at?->toISOString(),
            'user' => new UserResource($this->whenLoaded('user')),
            'project' => new ProjectResource($this->whenLoaded('project')),
            'producer' => new ProducerResource($this->whenLoaded('producer')),
            'product' => new ProductResource($this->whenLoaded('product')),
            'items' => ReportItemResource::collection($this->whenLoaded('items')),
            'consumables' => ReportConsumableResource::collection($this->whenLoaded('consumables')),
            'invoice_items' => ReportInvoiceItemResource::collection($this->whenLoaded('invoiceItems')),
            'ration_summary' => $this->when(
                (int) $this->type === Report::TYPE_RATION && $this->relationLoaded('rationIngredients'),
                fn () => $this->rationSummary()
            ),
            'ration_ingredients' => $this->whenLoaded('rationIngredients', fn () => $this->rationIngredients->map(fn ($item) => [
                'id' => $item->id,
                'report_id' => $item->report_id,
                'name' => $item->name,
                'unit' => $item->unit,
                'quantity_per_unit' => $item->quantity_per_unit !== null ? (float) $item->quantity_per_unit : null,
                'price_per_unit' => $item->price_per_unit !== null ? (int) $item->price_per_unit : null,
                'total' => (int) round((float) $item->quantity_per_unit * (float) $item->price_per_unit),
                'sort_order' => $item->sort_order,
            ])),
            'feeding_meals' => $this->whenLoaded('feedingMeals', fn () => $this->feedingMeals->map(function ($item) {
                $totalQty = $this->relationLoaded('rationIngredients')
                    ? (float) $this->rationIngredients->sum('quantity_per_unit')
                    : 0;
                $percent = $item->percent_of_total !== null ? (float) $item->percent_of_total : 0;

                return [
                    'id' => $item->id,
                    'report_id' => $item->report_id,
                    'meal_time' => $item->meal_time,
                    'name' => $item->name,
                    'percent_of_total' => $percent,
                    'weight' => $totalQty > 0 ? round($totalQty * ($percent / 100), 3) : null,
                    'sort_order' => $item->sort_order,
                ];
            })),
            'ration_weekly' => $this->whenLoaded('rationWeekly', fn () => $this->rationWeekly->map(fn ($item) => [
                'id' => $item->id,
                'report_id' => $item->report_id,
                'day_of_week' => (int) $item->day_of_week,
                'day_name' => \App\Models\ReportRationWeekly::dayNames()[(int) $item->day_of_week] ?? null,
                'is_active' => (bool) $item->is_active,
                'status' => $item->status,
                'status_label' => \App\Models\ReportRationWeekly::statusOptions()[$item->status] ?? $item->status,
            ])),
        ];
    }

    private function formatFiles(?array $files): ?array
    {
        if ($files === null) {
            return null;
        }

        return array_values(array_filter(array_map(
            fn ($file) => is_string($file) ? FileUrl::url($file) : null,
            $files
        )));
    }
}
