<?php

namespace App\Observers;

use App\Models\FinancialAssignment;
use App\Models\FinancialItem;
use App\Models\Payment;
use App\Models\Project;
use App\Models\ProjectContribution;
use Illuminate\Support\Facades\Log;

/**
 * Observes Payment model events to auto-create ProjectContribution records
 * when a payment linked to a project-related FinancialItem is completed.
 *
 * Handles BOTH:
 * - Mandatory levy payments (from Dues page / Paystack webhook)
 * - Voluntary donations (from ProjectController::verifyContribution)
 */
class PaymentObserver
{
    /**
     * Handle the Payment "updated" event.
     *
     * When a payment transitions to 'completed', check if it's linked to a
     * project-related FinancialItem and auto-create a ProjectContribution.
     */
    public function updated(Payment $payment): void
    {
        // Only act when status transitions TO completed
        if (!$payment->wasChanged('status') || $payment->status !== 'completed') {
            return;
        }

        $this->recordProjectContribution($payment);
    }

    /**
     * Resolve the payment chain: Payment → FinancialAssignment → FinancialItem → Project
     * and create a ProjectContribution record if applicable.
     */
    private function recordProjectContribution(Payment $payment): void
    {
        // Payment must be linked to a FinancialAssignment
        if ($payment->payable_type !== FinancialAssignment::class) {
            return;
        }

        $assignment = $payment->payable;
        if (!$assignment) {
            return;
        }

        // Resolve the FinancialItem
        $financialItem = $assignment->financialItem;
        if (!$financialItem) {
            return;
        }

        // Check if this FinancialItem is linked to a Project
        if ($financialItem->related_type !== Project::class || !$financialItem->related_id) {
            return;
        }

        $projectId = $financialItem->related_id;

        // Verify the project exists
        $projectExists = Project::where('id', $projectId)->exists();
        if (!$projectExists) {
            Log::warning('PaymentObserver: Project not found for contribution', [
                'payment_id' => $payment->id,
                'project_id' => $projectId,
                'financial_item_id' => $financialItem->id,
            ]);
            return;
        }

        // Create or update the ProjectContribution (idempotent via firstOrCreate)
        try {
            ProjectContribution::firstOrCreate(
                [
                    'project_id' => $projectId,
                    'user_id' => $payment->user_id,
                    'financial_assignment_id' => $assignment->id,
                ],
                [
                    'amount' => $payment->amount,
                    'status' => 'completed',
                    'contributed_at' => now(),
                ]
            );
        } catch (\Exception $e) {
            Log::error('PaymentObserver: Failed to create ProjectContribution', [
                'payment_id' => $payment->id,
                'project_id' => $projectId,
                'user_id' => $payment->user_id,
                'error' => $e->getMessage(),
            ]);
        }
    }
}
