<?php

namespace App\Http\Controllers;

use App\Models\Harvest;
use App\Models\PlannedTask;
use App\Models\VarietyVariation;
use App\Models\VineyardRow;
use App\Models\Treatment;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;

class VineyardOverviewController extends Controller
{
    public function index(Request $request)
    {
        $query = VineyardRow::query()
            ->with(['varietyVariation.grapeVariety'])
            ->withMax('treatments as last_treatment_at', 'created_at');

        $query = $this->applyFilters($query, $request);

        $rows = $query
            ->orderBy('id')
            ->paginate(15)
            ->withQueryString();

        $rowIds = $rows->pluck('id');
        $upcomingCounts = $this->upcomingPlannedCounts($rowIds);

        $rows->transform(function (VineyardRow $row) use ($upcomingCounts) {
            if ($row->last_treatment_at) {
                $row->last_treatment_at = Carbon::parse($row->last_treatment_at);
            }
            $row->upcoming_planned_count = $upcomingCounts[$row->getKey()] ?? 0;
            return $row;
        });

        $variationOptions = VarietyVariation::with('grapeVariety')
            ->orderBy('grape_variety_id')
            ->get()
            ->map(fn (VarietyVariation $variation) => [
                'id' => $variation->getKey(),
                'label' => sprintf(
                    '%s — %s',
                    $variation->grapeVariety->variety_name,
                    ucfirst($variation->color)
                ),
            ]);

        return view('vineyard.overview.index', [
            'rows' => $rows,
            'variationOptions' => $variationOptions,
            'statusOptions' => ['active', 'inactive', 'replanting', 'discarded'],
            'filters' => Arr::only($request->all(), [
                'status',
                'variety_variation_id',
                'planting_year_from',
                'planting_year_to',
                'vine_count_min',
                'vine_count_max',
            ]),
        ]);
    }

    protected function applyFilters($query, Request $request)
    {
        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        }

        if ($request->filled('variety_variation_id')) {
            $query->where('variety_variation_id', $request->integer('variety_variation_id'));
        }

        if ($request->filled('planting_year_from')) {
            $query->where('planting_year', '>=', $request->integer('planting_year_from'));
        }

        if ($request->filled('planting_year_to')) {
            $query->where('planting_year', '<=', $request->integer('planting_year_to'));
        }

        if ($request->filled('vine_count_min')) {
            $query->where('vine_count', '>=', $request->integer('vine_count_min'));
        }

        if ($request->filled('vine_count_max')) {
            $query->where('vine_count', '<=', $request->integer('vine_count_max'));
        }

        return $query;
    }

    protected function upcomingPlannedCounts(Collection $rowIds): array
    {
        if ($rowIds->isEmpty()) {
            return [];
        }

        $today = Carbon::now()->toDateString();

        $treatmentCounts = PlannedTask::query()
            ->selectRaw('treatments.row_id as row_id, COUNT(*) as aggregate')
            ->join('treatments', function ($join) {
                $join->on('planned_tasks.taskable_id', '=', 'treatments.treatment_id')
                    ->where('planned_tasks.taskable_type', '=', Treatment::class);
            })
            ->whereIn('treatments.row_id', $rowIds)
            ->whereNull('planned_tasks.execution_date')
            ->whereDate('planned_tasks.planned_date', '>=', $today)
            ->groupBy('treatments.row_id')
            ->pluck('aggregate', 'row_id');

        $harvestCounts = PlannedTask::query()
            ->selectRaw('harvests.vineyard_row_id as row_id, COUNT(*) as aggregate')
            ->join('harvests', function ($join) {
                $join->on('planned_tasks.taskable_id', '=', 'harvests.id')
                    ->where('planned_tasks.taskable_type', '=', Harvest::class);
            })
            ->whereIn('harvests.vineyard_row_id', $rowIds)
            ->whereNull('planned_tasks.execution_date')
            ->whereDate('planned_tasks.planned_date', '>=', $today)
            ->groupBy('harvests.vineyard_row_id')
            ->pluck('aggregate', 'row_id');

        $combined = [];

        foreach ($treatmentCounts as $rowId => $count) {
            $combined[$rowId] = ($combined[$rowId] ?? 0) + $count;
        }

        foreach ($harvestCounts as $rowId => $count) {
            $combined[$rowId] = ($combined[$rowId] ?? 0) + $count;
        }

        return $combined;
    }
}
