<?php

namespace App\Services;

use App\Models\Park;
use App\Models\ParkArea;
use App\Models\Operator;
use Illuminate\Support\Facades\DB;

class StatisticsRollupService
{
    /**
     * Update statistics for a specific area.
     */
    public function updateAreaStatistics(ParkArea $area): void
    {
        DB::transaction(function () use ($area) {
            // Update area statistics (will be implemented with Rides system)
            // For now, we'll just ensure the area triggers park updates
            $this->updateParkStatistics($area->park);
        });
    }

    /**
     * Update statistics for a specific park.
     */
    public function updateParkStatistics(Park $park): void
    {
        DB::transaction(function () use ($park) {
            // Update area counts
            $park->updateAreaCounts();

            // Update ride statistics
            $park->updateRideStatistics();

            // Update visitor statistics
            $park->updateVisitorStats();

            // Update operator statistics
            if ($park->operator) {
                $this->updateOperatorStatistics($park->operator);
            }
        });
    }

    /**
     * Update statistics for a specific operator.
     */
    public function updateOperatorStatistics(Operator $operator): void
    {
        DB::transaction(function () use ($operator) {
            $parks = $operator->parks;

            // Update park counts
            $operator->update([
                'total_parks' => $parks->count(),
                'operating_parks' => $parks->operating()->count(),
                'closed_parks' => $parks->closed()->count(),
            ]);

            // Update ride totals
            $operator->update([
                'total_rides' => $parks->sum('total_rides'),
                'total_coasters' => $parks->sum('total_coasters'),
                'total_flat_rides' => $parks->sum('total_flat_rides'),
                'total_water_rides' => $parks->sum('total_water_rides'),
            ]);

            // Update performance metrics
            $ratedParks = $parks->whereNotNull('average_rating');
            if ($ratedParks->count() > 0) {
                $operator->update([
                    'average_rating' => $ratedParks->avg('average_rating'),
                    'total_daily_capacity' => $parks->sum('total_daily_capacity'),
                    'average_utilization' => $parks->avg('utilization_rate'),
                ]);
            }
        });
    }

    /**
     * Update all statistics in the system.
     */
    public function refreshAllStatistics(): void
    {
        DB::transaction(function () {
            // Update all areas first
            ParkArea::chunk(100, function ($areas) {
                foreach ($areas as $area) {
                    // Area statistics will be implemented with Rides system
                }
            });

            // Update all parks
            Park::chunk(100, function ($parks) {
                foreach ($parks as $park) {
                    $this->updateParkStatistics($park);
                }
            });

            // Update all operators
            Operator::chunk(100, function ($operators) {
                foreach ($operators as $operator) {
                    $this->updateOperatorStatistics($operator);
                }
            });
        });
    }

    /**
     * Schedule regular statistics updates.
     */
    public function scheduleUpdates(): void
    {
        // This method will be called by the scheduler
        $this->refreshAllStatistics();
    }

    /**
     * Handle ride addition event.
     */
    public function handleRideAdded(ParkArea $area): void
    {
        DB::transaction(function () use ($area) {
            $area->recordNewRide();
            $this->updateAreaStatistics($area);
        });
    }

    /**
     * Handle ride retirement event.
     */
    public function handleRideRetired(ParkArea $area): void
    {
        DB::transaction(function () use ($area) {
            $area->recordRetirement();
            $this->updateAreaStatistics($area);
        });
    }

    /**
     * Handle park expansion event.
     */
    public function handleParkExpansion(Park $park): void
    {
        DB::transaction(function () use ($park) {
            $park->recordExpansion();
            $this->updateParkStatistics($park);
        });
    }

    /**
     * Handle major update event.
     */
    public function handleMajorUpdate(Park $park): void
    {
        DB::transaction(function () use ($park) {
            $park->recordMajorUpdate();
            $this->updateParkStatistics($park);
        });
    }
}