<?php

namespace App\Http\Controllers;

use App\Models\HealthInstitution;
use App\Models\InstitutionPayment;
use App\Models\PaymentConfiguration;
use App\Services\DirectorySearchService;
use App\Services\PaymentService;
use App\Services\EmailService;
use App\Services\SMSService;
use App\Http\Requests\StoreHealthInstitutionRequest;
use App\Http\Requests\UpdateHealthInstitutionRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;

/**
 * HealthInstitutionController
 *
 * Handles health institution directory listing, registration, and management.
 * Supports public views and authenticated Health Marketor dashboard.
 *
 * Requirements: 1.1-1.5, 5.1-5.5, 3.1-3.3
 */
class HealthInstitutionController extends Controller
{
    protected DirectorySearchService $searchService;
    protected PaymentService $paymentService;
    protected EmailService $emailService;
    protected SMSService $smsService;

    public function __construct(
        DirectorySearchService $searchService,
        PaymentService $paymentService,
        EmailService $emailService,
        SMSService $smsService
    ) {
        $this->searchService = $searchService;
        $this->paymentService = $paymentService;
        $this->emailService = $emailService;
        $this->smsService = $smsService;
    }

    // =========================================================================
    // PUBLIC METHODS
    // =========================================================================

    /**
     * Display public directory listing with search functionality.
     *
     * Requirements: 5.1, 5.3
     */
    public function index(Request $request)
    {
        $query = (string) ($request->get('q') ?? '');
        $filters = [
            'city'     => $request->get('city') ?: null,
            'country'  => $request->get('country') ?: null,
            'services' => $request->get('services') ?: null,
        ];

        $institutions = $this->searchService->searchInstitutions($query, $filters, 12);

        // Preserve all active query params across pagination links
        $institutions->appends($request->query());

        // Get filter options (always from full published set, not filtered subset)
        $cities   = $this->searchService->getCitiesWithCount();
        $services = $this->searchService->getServicesWithCount();

        // Get featured institutions for sidebar
        $featured = $this->searchService->getFeaturedInstitutions(4);

        return view('institutions.index', compact(
            'institutions',
            'query',
            'filters',
            'cities',
            'services',
            'featured'
        ));
    }

    /**
     * Display institution detail page.
     *
     * Requirements: 5.4
     */
    public function show(string $slug)
    {
        $institution = HealthInstitution::where('slug', $slug)
            ->published()
            ->firstOrFail();

        // Increment view count
        $institution->incrementViewCount();

        // Get related institutions
        $related = HealthInstitution::published()
            ->where('id', '!=', $institution->id)
            ->where(function ($q) use ($institution) {
                $q->where('city', $institution->city)
                    ->orWhereJsonContains('services', $institution->services[0] ?? null);
            })
            ->limit(4)
            ->get();

        return view('institutions.show', compact('institution', 'related'));
    }

    /**
     * Show registration form (multi-step).
     *
     * Requirements: 1.1
     */
    public function register()
    {
        // Check if payment is required
        $paymentConfig = PaymentConfiguration::getForInstitutions();
        $requiresPayment = $paymentConfig && $paymentConfig->requiresPayment();

        // Get common services for selection
        $services = HealthInstitution::getCommonServices();
        
        // Get cities for dropdown
        $cities = ['Juba', 'Wau', 'Malakal', 'Yei', 'Aweil', 'Rumbek', 'Bor', 'Torit', 'Yambio', 'Maridi'];

        return view('institutions.register', compact(
            'paymentConfig',
            'requiresPayment',
            'services',
            'cities'
        ));
    }

    /**
     * Process registration (creates Health Marketor account and institution).
     *
     * Requirements: 1.2, 1.4
     */
    public function store(StoreHealthInstitutionRequest $request)
    {
        DB::beginTransaction();
        try {
            // Check if user already exists
            $user = \App\Models\User::where('email', $request->contact_email)->first();

            if ($user) {
                // An account with this email already exists.
                // Only allow reuse if the user is already authenticated as that account,
                // or if they are a manager. Otherwise reject to prevent account hijacking.
                if (!auth()->check() || auth()->id() !== $user->id) {
                    if (!auth()->user()?->hasAnyRole(['Super Manager', 'Manager'])) {
                        DB::rollBack();
                        return back()->withInput()
                            ->withErrors(['contact_email' => 'An account with this email already exists. Please log in to register an institution under your existing account.'])
                            ->with('error', 'An account with this email already exists.');
                    }
                }
            } else {
                // Create new Health Marketor user
                $user = \App\Models\User::create([
                    'name'     => $request->contact_name,
                    'email'    => $request->contact_email,
                    'username' => \App\Models\User::generateUsername($request->contact_email),
                    'phone'    => $request->contact_phone,
                    'password' => bcrypt($request->contact_password),
                ]);

                // Assign Health Marketor role
                $role = Role::firstOrCreate(['name' => 'Health Marketor'], ['theme' => 'red']);
                $user->assignRole($role);

                // Send welcome notification
                $this->sendWelcomeNotification($user);
            }

            // Guard against duplicate institution name for the same user
            $duplicate = \App\Models\HealthInstitution::where('user_id', $user->id)
                ->where('name', $request->name)
                ->whereNotIn('listing_status', ['suspended'])
                ->first();

            if ($duplicate) {
                DB::rollBack();
                return back()->withInput()
                    ->withErrors(['name' => 'You have already registered an institution with this name.'])
                    ->with('error', 'Duplicate institution name.');
            }

            // Handle logo upload
            $logoPath = null;
            if ($request->hasFile('logo')) {
                $logoPath = $request->file('logo')->store('institutions/logos', 'public');
            }

            // Handle images upload
            $images = [];
            if ($request->hasFile('images')) {
                foreach ($request->file('images') as $image) {
                    $images[] = $image->store('institutions/images', 'public');
                }
            }

            // Generate unique slug
            $slug = HealthInstitution::generateUniqueSlug($request->name);

            // Get payment configuration
            $paymentConfig = PaymentConfiguration::getForInstitutions();
            $requiresPayment = $paymentConfig && $paymentConfig->requiresPayment();

            // Create institution
            $institution = HealthInstitution::create([
                'user_id' => $user->id,
                'name' => $request->name,
                'short_name' => $request->short_name,
                'slug' => $slug,
                'logo' => $logoPath,
                'city' => $request->city,
                'address' => $request->address,
                'country' => $request->country ?? 'South Sudan',
                'email' => $request->email,
                'phone' => $request->phone,
                'website_url' => $request->website_url,
                'description' => $request->description,
                'services' => $request->services,
                'images' => $images,
                'is_published' => !$requiresPayment,
                'listing_status' => $requiresPayment ? 'pending_payment' : 'published',
                'payment_status' => $requiresPayment ? 'pending' : 'exempt',
            ]);

            DB::commit();

            // Log the new user in so they can access the authenticated payment page
            if (!auth()->check()) {
                auth()->login($user);
            }

            // If payment is required, redirect to payment page
            if ($requiresPayment) {
                return redirect()->route('dashboard.institutions.payment', $institution)
                    ->with('info', 'Registration successful! Please complete payment to publish your listing.');
            }

            // Auto-publish if free
            $institution->publish();

            return redirect()->route('institutions.show', $institution->slug)
                ->with('success', 'Your institution has been registered and published successfully!');

        } catch (\Exception $e) {
            DB::rollBack();
            return back()->withInput()
                ->with('error', 'Registration failed: ' . $e->getMessage());
        }
    }

    // =========================================================================
    // HEALTH MARKETOR DASHBOARD METHODS
    // =========================================================================

    /**
     * Display Health Marketor's institution management dashboard.
     *
     * Requirements: 1.3, 3.2
     */
    public function dashboard(Request $request)
    {
        abort_unless(auth()->user()->can('view institutions'), 403);

        $institutions = HealthInstitution::where('user_id', auth()->id())
            ->latest()
            ->paginate(10);

        $stats = [
            'total' => HealthInstitution::where('user_id', auth()->id())->count(),
            'active' => HealthInstitution::where('user_id', auth()->id())
                ->where('listing_status', 'published')->count(),
            'pending' => HealthInstitution::where('user_id', auth()->id())
                ->where('listing_status', 'pending_payment')->count(),
            'expired' => HealthInstitution::where('user_id', auth()->id())
                ->where('listing_status', 'expired')->count(),
        ];

        return view('institutions.dashboard.index', compact('institutions', 'stats'));
    }

    /**
     * Show edit form for Health Marketor's institution.
     *
     * Requirements: 1.5
     */
    public function edit(HealthInstitution $institution)
    {
        // Authorization check
        abort_unless(
            auth()->user()->can('edit institutions') &&
            ($institution->isOwnedBy(auth()->user()) ||
             auth()->user()->hasAnyRole(['Super Manager', 'Manager'])),
            403
        );

        $services = HealthInstitution::getCommonServices();
        $cities = ['Juba', 'Wau', 'Malakal', 'Yei', 'Aweil', 'Rumbek', 'Bor', 'Torit', 'Yambio', 'Maridi'];

        return view('institutions.dashboard.edit', compact('institution', 'services', 'cities'));
    }

    /**
     * Update institution details.
     *
     * Requirements: 1.5
     */
    public function update(UpdateHealthInstitutionRequest $request, HealthInstitution $institution)
    {
        DB::beginTransaction();
        try {
            $data = $request->validated();

            // Handle logo upload
            if ($request->hasFile('logo')) {
                // Delete old logo
                if ($institution->logo) {
                    Storage::disk('public')->delete($institution->logo);
                }
                $data['logo'] = $request->file('logo')->store('institutions/logos', 'public');
            }

            // Handle images upload
            if ($request->hasFile('images')) {
                $images = $institution->images ?? [];
                foreach ($request->file('images') as $image) {
                    $images[] = $image->store('institutions/images', 'public');
                }
                $data['images'] = $images;
            }

            // Remove null values
            $data = array_filter($data, fn($value) => !is_null($value));

            $institution->update($data);

            DB::commit();

            return redirect()->route('dashboard.institutions.index')
                ->with('success', 'Institution updated successfully!');

        } catch (\Exception $e) {
            DB::rollBack();
            return back()->withInput()
                ->with('error', 'Update failed: ' . $e->getMessage());
        }
    }

    /**
     * Show payment page for institution listing.
     */
    public function payment(HealthInstitution $institution)
    {
        $paymentConfig = PaymentConfiguration::getForInstitutions();
        
        if (!$paymentConfig || !$paymentConfig->requiresPayment()) {
            // Auto-publish if free
            $institution->publish();
            return redirect()->route('institutions.show', $institution->slug)
                ->with('success', 'Your institution has been published!');
        }

        return view('institutions.dashboard.payment', compact('institution', 'paymentConfig'));
    }

    /**
     * Show renewal page for expired subscription.
     */
    public function renew(HealthInstitution $institution)
    {
        abort_unless(
            $institution->isOwnedBy(auth()->user()) ||
            auth()->user()->hasAnyRole(['Super Manager', 'Manager']),
            403
        );

        $paymentConfig = PaymentConfiguration::getForInstitutions();
        $lastPayment = $institution->latestPayment;

        return view('institutions.dashboard.renew', compact('institution', 'paymentConfig', 'lastPayment'));
    }

    // =========================================================================
    // ADMIN METHODS
    // =========================================================================

    /**
     * Admin: Display all institutions grid.
     *
     * Requirements: 3.3
     */
    public function adminIndex(Request $request)
    {
        abort_unless(auth()->user()->can('manage institutions'), 403);

        $query = HealthInstitution::with('user')
            ->when($request->status, fn($q, $status) => $q->where('listing_status', $status))
            ->when($request->search, fn($q, $search) => $q->search($search))
            ->latest();

        $institutions = $query->paginate(20);

        $stats = [
            'total' => HealthInstitution::count(),
            'published' => HealthInstitution::where('listing_status', 'published')->count(),
            'pending' => HealthInstitution::where('listing_status', 'pending_payment')->count(),
            'suspended' => HealthInstitution::where('listing_status', 'suspended')->count(),
        ];

        return view('admin.institutions.index', compact('institutions', 'stats'));
    }

    /**
     * Admin: Toggle institution status (activate/suspend).
     */
    public function toggleStatus(Request $request, HealthInstitution $institution)
    {
        abort_unless(auth()->user()->can('manage institutions'), 403);

        $request->validate([
            'status' => 'required|in:published,paused,suspended',
        ]);

        $institution->update([
            'listing_status' => $request->status,
            'is_published' => $request->status === 'published',
        ]);

        return back()->with('success', 'Institution status updated successfully.');
    }

    /**
     * Admin: Assign different marketor to institution.
     */
    public function assignMarketor(Request $request, HealthInstitution $institution)
    {
        abort_unless(auth()->user()->hasRole('Super Manager'), 403);

        $request->validate([
            'user_id' => 'required|exists:users,id',
        ]);

        $institution->update(['user_id' => $request->user_id]);

        return back()->with('success', 'Marketor assigned successfully.');
    }

    /**
     * Admin: Terminate institution connection (detach or delete).
     */
    public function terminate(HealthInstitution $institution)
    {
        abort_unless(auth()->user()->hasRole('Super Manager'), 403);

        $institution->update([
            'user_id' => null,
            'listing_status' => 'suspended',
            'is_published' => false,
        ]);

        return back()->with('success', 'Institution connection terminated.');
    }

    /**
     * Remove institution (soft delete).
     */
    public function destroy(HealthInstitution $institution)
    {
        abort_unless(auth()->user()->can('delete institutions'), 403);

        $institution->delete();

        return redirect()->route('admin.institutions.index')
            ->with('success', 'Institution deleted successfully.');
    }

    // =========================================================================
    // AJAX METHODS
    // =========================================================================

    /**
     * AJAX search endpoint for real-time institution search dropdown.
     * Returns JSON with `results` array containing name, city, slug, url fields.
     *
     * Requirements: 4.1, 4.2, 4.5, 4.6
     */
    public function ajaxSearch(Request $request)
    {
        $query = $request->get('q', '');

        if (strlen($query) < 2) {
            return response()->json(['results' => []]);
        }

        $institutions = HealthInstitution::query()
            ->published()
            ->search($query)
            ->orderBy('name')
            ->limit(10)
            ->get(['id', 'name', 'slug', 'city', 'logo'])
            ->map(fn($inst) => [
                'name'     => $inst->name,
                'city'     => $inst->city,
                'slug'     => $inst->slug,
                'url'      => route('institutions.show', $inst->slug),
                'logo_url' => $inst->logo ? asset('storage/' . $inst->logo) : null,
            ]);

        return response()->json(['results' => $institutions]);
    }

    /**
     * Real-time search for AJAX requests (home component + directory).
     * Supports ?q=, ?city=, ?country= query params.
     */
    public function search(Request $request)
    {
        $query   = $request->get('q', '');
        $city    = $request->get('city', '');
        $country = $request->get('country', '');

        $institutions = HealthInstitution::query()
            ->published()
            ->when(strlen($query) >= 1, fn ($q) => $q->search($query))
            ->when($city,    fn ($q) => $q->byCity($city))
            ->when($country, fn ($q) => $q->byCountry($country))
            ->orderBy('name')
            ->limit(12)
            ->get(['id', 'name', 'slug', 'short_name', 'city', 'country', 'email', 'website_url', 'description', 'logo'])
            ->map(fn ($inst) => [
                'id'          => $inst->id,
                'name'        => $inst->name,
                'slug'        => $inst->slug,
                'short_name'  => $inst->short_name,
                'city'        => $inst->city,
                'country'     => $inst->country,
                'email'       => $inst->email,
                'website_url' => $inst->website_url,
                'description' => $inst->description
                    ? \Illuminate\Support\Str::words($inst->description, 12, '…')
                    : null,
                'logo_url'    => $inst->logo ? asset('storage/' . $inst->logo) : null,
                'url'         => route('institutions.show', $inst->slug),
            ]);

        return response()->json(['institutions' => $institutions]);
    }

    // =========================================================================
    // HELPER METHODS
    // =========================================================================

    /**
     * Send welcome notification to new Health Marketor.
     */
    protected function sendWelcomeNotification($user): void
    {
        // Send welcome email
        if ($this->emailService->isReady()) {
            $this->emailService->sendTemplate(
                $user->email,
                'Welcome to Health Directory',
                'emails.welcome-health-marketor',
                ['userName' => $user->name]
            );
        }

        // Send welcome SMS
        if ($user->phone && $this->smsService->isAvailable()) {
            $this->smsService->sendTemplate(
                $user->phone,
                'Welcome to Health Directory, {name}! Your account has been created.',
                ['name' => $user->name]
            );
        }
    }
}
