<?php

namespace App\Http\Controllers;

use App\Models\VarietyVariation;
use App\Models\VineyardRow;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Carbon;

class VineyardMapController extends Controller
{
    /**
     * Display a read-only vineyard map with available actions.
     */
    public function index()
    {
        $rows = VineyardRow::with([
            'varietyVariation.grapeVariety',
            'treatments' => function ($query) {
                $query->latest('created_at');
            },
            'sprayings' => function ($query) {
                $query->with('plannedTask')->orderByDesc('created_at');
            },
            'harvests' => function ($query) {
                $query->with('plannedTask')->orderByDesc('date');
            },
        ])->get();

        $actionGroups = [
            'Treatment' => [
                'watering',
                'pruning',
                'fertilisation',
                'pesticide',
            ],
            'Manage Crops' => [
                'harvest',
                'add-plants',
                'discard-plants',
            ],
        ];

        return view('vineyard.map.index', [
            'rows' => $this->formatRows($rows),
            'actions' => array_merge(...array_values($actionGroups)),
            'actionGroups' => $actionGroups,
        ]);
    }

    /**
     * Display the editable vineyard map.
     */
    public function edit()
    {
        $rows = VineyardRow::with(['varietyVariation.grapeVariety'])->get();
        $variations = VarietyVariation::with('grapeVariety')
            ->orderBy('grape_variety_id')
            ->get()
            ->map(function (VarietyVariation $variation) {
                $grape = $variation->grapeVariety;
                $label = $grape
                    ? sprintf('%s — %s', $grape->variety_name, ucfirst($variation->color))
                    : ucfirst($variation->color);

                return [
                    'id' => $variation->getKey(),
                    'label' => $label,
                ];
            });

        return view('vineyard.map.edit', [
            'rows' => $this->formatRows($rows),
            'statuses' => ['active', 'inactive', 'replanting', 'discarded'],
            'variationOptions' => $variations,
        ]);
    }

    /**
     * Transform rows into a structure suitable for the front-end map.
     */
    protected function formatRows(Collection $rows): Collection
    {
        return $rows->map(function (VineyardRow $row) {
            [$x, $y] = $this->parseLocation($row->location);

            $variation = $row->varietyVariation;
            $grapeVariety = $variation?->grapeVariety;

            $lastTreatmentDate = optional($row->treatments->first())->created_at;

            $pesticideCompleted = $row->sprayings->map(function ($spraying) {
                $executionDate = optional($spraying->plannedTask)->execution_date;
                if ($executionDate) {
                    return Carbon::parse($executionDate)->toDateString();
                }

                return optional($spraying->created_at)?->toDateString();
            })->filter()->unique()->sort()->values()->all();

            $pesticidePlanned = $row->sprayings->map(function ($spraying) {
                $plannedDate = optional($spraying->plannedTask)->planned_date;
                if ($plannedDate) {
                    return Carbon::parse($plannedDate)->toDateString();
                }

                return null;
            })->filter()->unique()->sort()->values()->all();

            $harvestCompleted = $row->harvests->map(function ($harvest) {
                $executionDate = optional($harvest->plannedTask)->execution_date;
                if ($executionDate) {
                    return Carbon::parse($executionDate)->toDateString();
                }

                $harvestDate = $harvest->date;
                return $harvestDate ? Carbon::parse($harvestDate)->toDateString() : null;
            })->filter()->unique()->sort()->values()->all();

            $harvestPlanned = $row->harvests->map(function ($harvest) {
                $plannedDate = optional($harvest->plannedTask)->planned_date;
                if ($plannedDate) {
                    return Carbon::parse($plannedDate)->toDateString();
                }

                return null;
            })->filter()->unique()->sort()->values()->all();

            return [
                'id' => $row->getKey(),
                'location' => [
                    'x' => $x,
                    'y' => $y,
                ],
                'dimensions' => [
                    'width' => 1,
                    'height' => 1,
                ],
                'vine_count' => $row->vine_count,
                'status' => $row->status,
                'notes' => $row->notes,
                'planting_year' => $row->planting_year,
                'variety' => $variation ? [
                    'id' => $variation->getKey(),
                    'color' => $variation->color,
                    'label' => $grapeVariety
                        ? sprintf('%s — %s', $grapeVariety->variety_name, ucfirst($variation->color))
                        : ucfirst($variation->color),
                ] : null,
                'last_treatment_at' => $lastTreatmentDate,
                'timeline' => [
                    'pesticide' => [
                        'completed' => $pesticideCompleted,
                        'planned' => $pesticidePlanned,
                    ],
                    'harvest' => [
                        'completed' => $harvestCompleted,
                        'planned' => $harvestPlanned,
                    ],
                ],
            ];
        });
    }

    /**
     * Parse the "x,y" string stored on vineyard rows.
     */
    protected function parseLocation(?string $location): array
    {
        if (blank($location)) {
            return [0, 0];
        }

        $parts = Str::of($location)->explode(',')->map(fn ($fragment) => (int) trim($fragment));

        return [
            $parts->get(0, 0),
            $parts->get(1, 0),
        ];
    }
}
