<?php

declare(strict_types=1);

namespace App\Repositories;

use App\Contracts\Repositories\InvestmentDistributionRepositoryInterface;
use App\Models\InvestmentDistribution;
use Illuminate\Database\Eloquent\Collection;

final class EloquentInvestmentDistributionRepository implements InvestmentDistributionRepositoryInterface
{
    public function findById(int $id): ?InvestmentDistribution
    {
        return InvestmentDistribution::with(['investmentProperty', 'partnerDistributions'])->find($id);
    }

    public function getAll(array $filters = []): Collection
    {
        return $this->applyFilters(InvestmentDistribution::query(), $filters)
            ->with('investmentProperty')
            ->latest('distribution_period')
            ->get();
    }

    public function getByProperty(int $propertyId): Collection
    {
        return InvestmentDistribution::where('investment_property_id', $propertyId)
            ->latest('distribution_period')
            ->get();
    }

    public function getPending(): Collection
    {
        return InvestmentDistribution::pending()
            ->with('investmentProperty')
            ->latest('distribution_period')
            ->get();
    }

    public function getPendingForPeriod(string $period): Collection
    {
        return InvestmentDistribution::where('status', 'pending')
            ->where('distribution_period', 'like', $period.'%')
            ->with('investmentProperty')
            ->get();
    }

    public function getDistributed(): Collection
    {
        return InvestmentDistribution::distributed()
            ->with('investmentProperty')
            ->latest('distribution_period')
            ->get();
    }

    public function getByPeriod(string $startDate, string $endDate): Collection
    {
        return InvestmentDistribution::whereBetween('distribution_period', [$startDate, $endDate])
            ->with('investmentProperty')
            ->latest('distribution_period')
            ->get();
    }

    public function create(array $data): InvestmentDistribution
    {
        return InvestmentDistribution::create($data);
    }

    public function update(int $id, array $data): InvestmentDistribution
    {
        $distribution = InvestmentDistribution::findOrFail($id);
        $distribution->update($data);

        return $distribution->fresh();
    }

    public function markAsDistributed(int $id): bool
    {
        $distribution = InvestmentDistribution::findOrFail($id);
        $distribution->markAsDistributed();

        return true;
    }

    public function getTotalDistributedByProperty(int $propertyId): float
    {
        return (float) InvestmentDistribution::where('investment_property_id', $propertyId)
            ->where('status', 'distributed')
            ->sum('net_distributable');
    }

    /**
     * Apply filters to query
     */
    private function applyFilters($query, array $filters)
    {
        if (isset($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        if (isset($filters['property_id'])) {
            $query->where('investment_property_id', $filters['property_id']);
        }

        return $query;
    }
}
