<?php

namespace App\Http\Controllers\Partnership;

use App\Http\Controllers\Controller;
use App\Models\RPartner;
use App\Models\RPartnership;
use App\Services\PartnershipService;
use App\Http\Requests\Partnership\StorePartnerRequest;
use Illuminate\Http\Request;
use Illuminate\View\View;
use Illuminate\Http\JsonResponse;

/**
 * Controller: RPartnerController
 * 
 * Handles partner organization management and public directory.
 * 
 * @author SSHIA Development Team
 * @version 1.0.0
 */
class RPartnerController extends Controller
{
    /**
     * Create a new controller instance.
     */
    public function __construct(
        protected PartnershipService $partnershipService
    ) {}

    /**
     * Display public partner directory.
     * Public access - Site Layout
     */
    public function publicIndex(Request $request): View
    {
        $partners = $this->partnershipService->getPublicDirectory(
            $request->only(['type', 'search', 'per_page'])
        );

        // Organization types for filter
        $types = [
            'government' => 'Government Agency',
            'ngo' => 'NGO',
            'private_sector' => 'Private Sector',
            'academic' => 'Academic Institution',
            'healthcare' => 'Healthcare Organization',
            'international' => 'International Organization',
        ];

        return view('partners.index', [
            'partners' => $partners,
            'types' => $types,
            'filters' => $request->only(['type', 'search']),
        ]);
    }

    /**
     * Display single partner profile (public).
     */
    public function publicShow(RPartner $partner): View
    {
        if (!$partner->show_in_directory) {
            abort(404);
        }

        $partner->load(['contacts', 'partnerships' => function ($q) {
            $q->active()->latest();
        }]);

        return view('partners.show', [
            'partner' => $partner,
        ]);
    }

    /**
     * Get filtered partners for real-time search (AJAX).
     * Public access - JSON response
     */
    public function publicSearch(Request $request): JsonResponse
    {
        $search = $request->get('search', '');
        $type = $request->get('type', '');
        $limit = (int) $request->get('limit', 12);

        $query = RPartner::where('show_in_directory', true)
                        ->where('partnership_status', RPartner::PARTNERSHIP_ACTIVE);

        // Search filter
        if (!empty($search)) {
            $query->where(function ($q) use ($search) {
                $q->where('organization_name', 'LIKE', "%{$search}%")
                  ->orWhere('description', 'LIKE', "%{$search}%")
                  ->orWhere('email', 'LIKE', "%{$search}%");
            });
        }

        // Type filter
        if (!empty($type)) {
            $query->where('organization_type', $type);
        }

        $partners = $query->orderByDesc('is_featured')
                         ->orderBy('organization_name')
                         ->limit($limit)
                         ->get();

        return response()->json([
            'success' => true,
            'count' => $partners->count(),
            'partners' => $partners->map(fn($p) => [
                'id' => $p->id,
                'name' => $p->organization_name,
                'type' => $p->type_label,
                'description' => \Illuminate\Support\Str::limit($p->description, 100),
                'logo' => $p->logo ? asset('storage/' . $p->logo) : null,
                'is_verified' => $p->is_verified,
                'is_featured' => $p->is_featured,
                'url' => route('partners.public.show', $p),
                'website' => $p->website,
            ]),
        ]);
    }

    /**
     * Show "Become a Partner" form.
     */
    public function becomePartner(): View
    {
        return view('partners.become-partner');
    }

    /**
     * Submit partnership application (public).
     */
    public function apply(Request $request): mixed
    {
        $validated = $request->validate([
            'organization_name' => 'required|string|max:191',
            'email' => 'required|email|max:191',
            'phone' => 'nullable|string|max:50',
            'website' => 'nullable|url|max:191',
            'organization_type' => 'required|string|max:50',
            'description' => 'required|string|max:2000',
            'contact_name' => 'required|string|max:191',
            'contact_email' => 'required|email|max:191',
            'contact_phone' => 'nullable|string|max:50',
            'message' => 'nullable|string|max:2000',
        ]);

        try {
            // Create pending partner
            $partner = RPartner::create([
                'organization_name' => $validated['organization_name'],
                'slug' => RPartner::generateSlug($validated['organization_name']),
                'email' => $validated['email'],
                'phone' => $validated['phone'],
                'website' => $validated['website'],
                'organization_type' => $validated['organization_type'],
                'description' => $validated['description'],
                'partnership_status' => RPartner::PARTNERSHIP_PENDING,
                'show_in_directory' => false,
            ]);

            // Add contact
            $partner->contacts()->create([
                'name' => $validated['contact_name'],
                'email' => $validated['contact_email'],
                'phone' => $validated['contact_phone'],
                'role' => 'primary_contact',
                'is_primary' => true,
            ]);

            // TODO: Notify admins

            return redirect()
                ->route('partners.public.index')
                ->with('success', 'Your partnership application has been submitted! We will contact you shortly.');

        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->with('error', 'Failed to submit application: ' . $e->getMessage());
        }
    }

    /**
     * Display partner management dashboard.
     */
    public function index(Request $request): mixed
    {
        $user = auth()->user();

        // Partners with 'view own partners' only see their own record
        $isOwnOnly = !$user->can('view partners') && $user->can('view own partners');

        $query = RPartner::with(['contacts', 'user'])
                        ->orderByDesc('is_featured')
                        ->orderBy('organization_name');

        if ($isOwnOnly) {
            // Restrict to the partner linked to this user
            $ownPartnerId = $user->partner?->id;
            if ($ownPartnerId) {
                $query->where('id', $ownPartnerId);
            } else {
                $query->whereRaw('1=0'); // no partner linked — show nothing
            }
        } else {
            abort_unless($user->can('view partners'), 403);

            // Filters (managers only)
            if ($request->filled('status')) {
                $query->where('partnership_status', $request->status);
            }
            if ($request->filled('type')) {
                $query->where('organization_type', $request->type);
            }
            if ($request->filled('search')) {
                $search = $request->search;
                $query->where(function ($q) use ($search) {
                    $q->where('organization_name', 'LIKE', "%{$search}%")
                      ->orWhere('email', 'LIKE', "%{$search}%");
                });
            }
        }

        $partners = $query->paginate(15);
        $stats    = $this->partnershipService->getPartnershipStats();

        // AJAX request — return rendered partial as JSON
        if ($request->ajax() || $request->has('ajax')) {
            $html = view('partners.manage._partners_table', ['partners' => $partners])->render();
            return response()->json(['html' => $html]);
        }

        return view('partners.manage.index', [
            'partners' => $partners,
            'stats'    => [
                'total'         => $stats['total_partners'] ?? 0,
                'active'        => $stats['active_partners'] ?? 0,
                'pending'       => RPartner::where('partnership_status', 'pending')->count(),
                'expiring_soon' => $stats['expiring_soon'] ?? 0,
            ],
            'filters'  => $request->only(['status', 'type', 'search']),
        ]);
    }

    /**
     * Show form for creating partner.
     */
    public function create(): View
    {
        abort_unless(auth()->user()->can('create partners'), 403);

        return view('partners.manage.create');
    }

    /**
     * Store new partner.
     */
    public function store(StorePartnerRequest $request): mixed
    {
        abort_unless(auth()->user()->can('create partners'), 403);

        try {
            $partner = $this->partnershipService->createPartner($request->validated());

            return redirect()
                ->route('partners.show', $partner)
                ->with('success', 'Partner created successfully!');

        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->with('error', 'Failed to create partner: ' . $e->getMessage());
        }
    }

    /**
     * Display partner details.
     */
    public function show(RPartner $partner): View
    {
        // Check authorization - can view all partners OR own partner
        abort_unless(
            auth()->user()->can('view partners') || 
            (auth()->user()->can('view own partners') && auth()->user()->partner?->id === $partner->id),
            403
        );

        $partner->load(['contacts', 'partnerships', 'forumThreads' => function ($q) {
            $q->latest()->limit(5);
        }]);

        return view('partners.manage.show', [
            'partner' => $partner,
        ]);
    }

    /**
     * Show form for editing partner.
     */
    public function edit(RPartner $partner): View
    {
        // Check authorization - can edit all partners OR edit own partner
        abort_unless(
            auth()->user()->can('edit partners') || 
            (auth()->user()->can('edit own partners') && auth()->user()->partner?->id === $partner->id),
            403
        );

        $partner->load('contacts');

        return view('partners.manage.edit', [
            'partner' => $partner,
        ]);
    }

    /**
     * Update partner.
     */
    public function update(StorePartnerRequest $request, RPartner $partner): mixed
    {
        // Check authorization - can edit all partners OR edit own partner
        abort_unless(
            auth()->user()->can('edit partners') || 
            (auth()->user()->can('edit own partners') && auth()->user()->partner?->id === $partner->id),
            403
        );

        try {
            $partner = $this->partnershipService->updatePartner(
                $partner,
                $request->validated()
            );

            return redirect()
                ->route('partners.show', $partner)
                ->with('success', 'Partner updated successfully!');

        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->with('error', 'Failed to update partner: ' . $e->getMessage());
        }
    }

    /**
     * Delete partner.
     */
    public function destroy(RPartner $partner): mixed
    {
        abort_unless(auth()->user()->can('delete partners'), 403);

        $partner->delete();

        return redirect()
            ->route('partners.index')
            ->with('success', 'Partner deleted successfully!');
    }

    /**
     * Verify partner.
     */
    public function verify(RPartner $partner): JsonResponse
    {
        abort_unless(auth()->user()->can('verify partners'), 403);

        $this->partnershipService->verifyPartner($partner, auth()->id());

        return response()->json([
            'success' => true,
            'message' => 'Partner verified successfully!',
        ]);
    }

    /**
     * Toggle featured status.
     */
    public function toggleFeatured(RPartner $partner): JsonResponse
    {
        abort_unless(auth()->user()->can('feature partners'), 403);

        $partner->update([
            'is_featured' => !$partner->is_featured,
        ]);

        return response()->json([
            'success' => true,
            'is_featured' => $partner->is_featured,
        ]);
    }

    /**
     * Get expiring partnerships.
     */
    public function expiring(): JsonResponse
    {
        abort_unless(auth()->user()->can('view partners'), 403);

        $expiring = $this->partnershipService->getExpiringPartnerships();

        return response()->json([
            'success' => true,
            'data' => $expiring,
        ]);
    }
}
