<?php

namespace App\Services;

use App\Models\RPartner;
use App\Models\RPartnership;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;

/**
 * Service: PartnershipService
 * 
 * Handles partnership management including MOUs, agreements,
 * and renewal tracking.
 * 
 * @author SSHIA Development Team
 * @version 1.0.0
 */
class PartnershipService
{
    /**
     * Create a new partner.
     */
    public function createPartner(array $data): RPartner
    {
        return DB::transaction(function () use ($data) {
            // Generate slug
            $data['slug'] = RPartner::generateSlug($data['organization_name']);

            // Create partner
            $partner = RPartner::create($data);

            // Create contacts if provided
            if (!empty($data['contacts'])) {
                foreach ($data['contacts'] as $contactData) {
                    $partner->contacts()->create($contactData);
                }
            }

            return $partner->load('contacts');
        });
    }

    /**
     * Update partner.
     */
    public function updatePartner(RPartner $partner, array $data): RPartner
    {
        return DB::transaction(function () use ($partner, $data) {
            $partner->update($data);

            // Update contacts if provided
            if (isset($data['contacts'])) {
                // Delete removed contacts
                $existingIds = collect($data['contacts'])
                    ->filter(fn($c) => isset($c['id']))
                    ->pluck('id');

                $partner->contacts()
                    ->whereNotIn('id', $existingIds)
                    ->delete();

                // Update or create contacts
                foreach ($data['contacts'] as $contactData) {
                    if (isset($contactData['id'])) {
                        $partner->contacts()
                            ->where('id', $contactData['id'])
                            ->update($contactData);
                    } else {
                        $partner->contacts()->create($contactData);
                    }
                }
            }

            return $partner->fresh(['contacts']);
        });
    }

    /**
     * Create a new partnership (MOU/Agreement).
     */
    public function createPartnership(RPartner $partner, array $data): RPartnership
    {
        return DB::transaction(function () use ($partner, $data) {
            $data['partner_id'] = $partner->id;

            // Handle document upload
            if (!empty($data['document'])) {
                $data['document_path'] = $data['document']->store('partnerships/documents', 'private');
                $data['document_name'] = $data['document']->getClientOriginalName();
                unset($data['document']);
            }

            $partnership = RPartnership::create($data);

            // Update partner partnership dates
            $this->updatePartnerPartnershipDates($partner);

            return $partnership;
        });
    }

    /**
     * Renew partnership.
     */
    public function renewPartnership(RPartnership $partnership, int $months, array $data = []): RPartnership
    {
        return DB::transaction(function () use ($partnership, $months, $data) {
            $newEndDate = $partnership->end_date
                ? $partnership->end_date->copy()->addMonths($months)
                : now()->addMonths($months);

            $partnership->renew($months);

            // Update partner status
            $partner = $partnership->partner;
            $partner->update([
                'partnership_status' => RPartner::PARTNERSHIP_ACTIVE,
                'partnership_end_date' => $newEndDate,
            ]);

            return $partnership->fresh();
        });
    }

    /**
     * Terminate partnership.
     */
    public function terminatePartnership(RPartnership $partnership, string $reason = null): RPartnership
    {
        return DB::transaction(function () use ($partnership, $reason) {
            $partnership->terminate($reason);

            // Check if partner has other active partnerships
            $partner = $partnership->partner;
            $hasOtherActive = $partner->partnerships()
                ->where('id', '!=', $partnership->id)
                ->active()
                ->exists();

            if (!$hasOtherActive) {
                $partner->update([
                    'partnership_status' => RPartner::PARTNERSHIP_INACTIVE,
                ]);
            }

            return $partnership->fresh();
        });
    }

    /**
     * Verify partner.
     */
    public function verifyPartner(RPartner $partner, int $verifiedBy): void
    {
        $partner->update([
            'is_verified' => true,
            'verified_at' => now(),
            'verified_by' => $verifiedBy,
        ]);
    }

    /**
     * Get expiring partnerships.
     */
    public function getExpiringPartnerships(int $days = 30)
    {
        return RPartnership::with('partner')
            ->active()
            ->whereNotNull('end_date')
            ->where('end_date', '<=', now()->addDays($days))
            ->where('end_date', '>=', now())
            ->where('expiry_notification_sent', false)
            ->get();
    }

    /**
     * Send expiry notifications.
     */
    public function sendExpiryNotifications(int $days = 30): int
    {
        $expiring = $this->getExpiringPartnerships($days);
        $sent = 0;

        foreach ($expiring as $partnership) {
            try {
                $manager = $partnership->manager;
                if ($manager) {
                    // TODO: Send notification
                    // Notification::send($manager, new PartnershipExpiringNotification($partnership));
                }

                $partnership->update(['expiry_notification_sent' => true]);
                $sent++;
            } catch (\Exception $e) {
                // Log error but continue
                logger()->error('Failed to send expiry notification', [
                    'partnership_id' => $partnership->id,
                    'error' => $e->getMessage(),
                ]);
            }
        }

        return $sent;
    }

    /**
     * Update partner partnership dates based on active partnerships.
     */
    protected function updatePartnerPartnershipDates(RPartner $partner): void
    {
        $activePartnership = $partner->partnerships()
            ->active()
            ->orderByDesc('end_date')
            ->first();

        if ($activePartnership) {
            $partner->update([
                'partnership_start_date' => $activePartnership->start_date,
                'partnership_end_date' => $activePartnership->end_date,
                'partnership_status' => RPartner::PARTNERSHIP_ACTIVE,
            ]);
        }
    }

    /**
     * Get partner directory for public view.
     */
    public function getPublicDirectory(array $filters = [])
    {
        $query = RPartner::inDirectory()
                        ->verified()
                        ->with('contacts')
                        ->orderByDesc('is_featured')
                        ->orderBy('organization_name');

        // Apply filters
        if (!empty($filters['type'])) {
            $query->byType($filters['type']);
        }

        if (!empty($filters['search'])) {
            $search = $filters['search'];
            $query->where(function ($q) use ($search) {
                $q->where('organization_name', 'LIKE', "%{$search}%")
                  ->orWhere('description', 'LIKE', "%{$search}%")
                  ->orWhere('category', 'LIKE', "%{$search}%");
            });
        }

        return $query->paginate($filters['per_page'] ?? 15);
    }

    /**
     * Get partnership statistics for dashboard.
     */
    public function getPartnershipStats(): array
    {
        return [
            'total_partners' => RPartner::count(),
            'active_partners' => RPartner::active()->count(),
            'verified_partners' => RPartner::verified()->count(),
            'featured_partners' => RPartner::featured()->count(),
            'total_partnerships' => RPartnership::count(),
            'active_partnerships' => RPartnership::active()->count(),
            'expiring_soon' => RPartnership::expiringSoon()->count(),
            'expired' => RPartnership::expired()->count(),
            'by_level' => [
                'bronze' => RPartner::where('partnership_level', RPartner::LEVEL_BRONZE)->count(),
                'silver' => RPartner::where('partnership_level', RPartner::LEVEL_SILVER)->count(),
                'gold' => RPartner::where('partnership_level', RPartner::LEVEL_GOLD)->count(),
                'platinum' => RPartner::where('partnership_level', RPartner::LEVEL_PLATINUM)->count(),
            ],
            'by_type' => RPartner::selectRaw('organization_type, COUNT(*) as count')
                ->groupBy('organization_type')
                ->pluck('count', 'organization_type')
                ->toArray(),
        ];
    }
}
