<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\PaymentGatewaySetting;
use App\Services\Care\AuditLogger;
use App\Services\Care\CarePermissions;
use App\Services\Care\PlanService;
use App\Services\Messaging\CustomerSmsClient;
use App\Services\Messaging\MessagingCredentialsService;
use App\Services\Payments\MerchantGatewayService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;

class IntegrationsController extends Controller
{
    use ScopesToAccount;

    public function edit(
        Request $request,
        MessagingCredentialsService $credentials,
        MerchantGatewayService $gateway,
        PlanService $plans,
    ): View {
        $this->authorizeAbility($request, 'settings.view');
        $organization = $this->organization($request);
        $canManage = app(CarePermissions::class)->can($this->member($request), 'settings.manage');

        return view('care.integrations.edit', [
            'organization' => $organization,
            'canManage' => $canManage,
            'credential' => $credentials->forOrganization($organization),
            'gateway' => $gateway->settingFor($organization),
            'canUsePaymentGateway' => $plans->canUsePaymentGateway($organization),
            'gatewayLabels' => config('care.payment_gateways'),
        ]);
    }

    public function saveSms(Request $request, MessagingCredentialsService $credentials): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);

        $data = $request->validate([
            'sms_api_key' => ['required', 'string', 'max:200'],
            'sms_sender_id' => ['required', 'string', 'max:11'],
        ]);

        $result = $credentials->validateAndSaveSms(
            $organization,
            $data['sms_api_key'],
            $data['sms_sender_id'],
        );

        AuditLogger::record(
            $this->ownerRef($request),
            ($result['ok'] ?? false) ? 'integrations.sms_connected' : 'integrations.sms_failed',
            $organization->id,
            $this->ownerRef($request),
            \App\Models\Organization::class,
            $organization->id,
            ['prefix' => substr(trim($data['sms_api_key']), 0, 16)],
        );

        if (! ($result['ok'] ?? false)) {
            return back()->withInput()->with('error', $result['error'] ?? 'Could not save SMS credentials.');
        }

        return back()->with('success', 'SMS credentials saved.');
    }

    public function disconnectSms(Request $request, MessagingCredentialsService $credentials): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);
        $credentials->disconnectSms($organization);

        AuditLogger::record(
            $this->ownerRef($request),
            'integrations.sms_disconnected',
            $organization->id,
            $this->ownerRef($request),
            \App\Models\Organization::class,
            $organization->id,
        );

        return back()->with('success', 'SMS disconnected.');
    }

    public function saveBird(Request $request, MessagingCredentialsService $credentials): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);

        $data = $request->validate([
            'bird_api_key' => ['required', 'string', 'max:200'],
            'bird_from_email' => ['required', 'email', 'max:255'],
            'bird_from_name' => ['nullable', 'string', 'max:100'],
        ]);

        $result = $credentials->validateAndSaveBird(
            $organization,
            $data['bird_api_key'],
            $data['bird_from_email'],
            $data['bird_from_name'] ?? null,
        );

        AuditLogger::record(
            $this->ownerRef($request),
            ($result['ok'] ?? false) ? 'integrations.bird_connected' : 'integrations.bird_failed',
            $organization->id,
            $this->ownerRef($request),
            \App\Models\Organization::class,
            $organization->id,
            ['prefix' => substr(trim($data['bird_api_key']), 0, 16)],
        );

        if (! ($result['ok'] ?? false)) {
            return back()->withInput()->with('error', $result['error'] ?? 'Could not save Bird credentials.');
        }

        return back()->with('success', 'Email credentials saved.');
    }

    public function disconnectBird(Request $request, MessagingCredentialsService $credentials): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);
        $credentials->disconnectBird($organization);

        AuditLogger::record(
            $this->ownerRef($request),
            'integrations.bird_disconnected',
            $organization->id,
            $this->ownerRef($request),
            \App\Models\Organization::class,
            $organization->id,
        );

        return back()->with('success', 'Email disconnected.');
    }

    public function previewSenders(Request $request, CustomerSmsClient $sms): JsonResponse
    {
        $this->authorizeAbility($request, 'settings.manage');

        $data = $request->validate([
            'sms_api_key' => ['required', 'string', 'max:200'],
        ]);

        $result = $sms->senders(trim($data['sms_api_key']));
        if (! ($result['ok'] ?? false)) {
            return response()->json(['error' => $result['error'] ?? 'Could not load senders.'], 422);
        }

        return response()->json($result['data'] ?? []);
    }

    public function saveGateway(Request $request, PlanService $plans): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);

        if (! $plans->canUsePaymentGateway($organization)) {
            return back()->with('error', 'Connecting your own payment gateway requires Care Pro or Enterprise.');
        }

        $data = $request->validate([
            'gateway_provider' => ['required', 'string', Rule::in(PaymentGatewaySetting::providers())],
            'gateway_public_key' => ['nullable', 'string', 'max:2000'],
            'gateway_secret_key' => ['nullable', 'string', 'max:2000'],
            'gateway_webhook_secret' => ['nullable', 'string', 'max:2000'],
            'gateway_is_active' => ['nullable', 'boolean'],
        ]);

        $existing = PaymentGatewaySetting::query()
            ->where('organization_id', $organization->id)
            ->first();

        $publicKey = trim((string) ($data['gateway_public_key'] ?? ''));
        $secretKey = trim((string) ($data['gateway_secret_key'] ?? ''));
        $webhookSecret = trim((string) ($data['gateway_webhook_secret'] ?? ''));

        $attributes = [
            'owner_ref' => $this->ownerRef($request),
            'provider' => $data['gateway_provider'],
            'is_active' => $request->boolean('gateway_is_active', true),
        ];

        // Blank fields keep previously stored encrypted credentials.
        if ($publicKey !== '') {
            $attributes['public_key'] = $publicKey;
        }
        if ($secretKey !== '') {
            $attributes['secret_key'] = $secretKey;
        }
        if ($webhookSecret !== '') {
            $attributes['webhook_secret'] = $webhookSecret;
        }

        if ($existing === null && $secretKey === '') {
            return back()->withInput()->with('error', 'Secret / API key is required to connect a payment gateway.');
        }

        if ($data['gateway_provider'] === PaymentGatewaySetting::PROVIDER_HUBTEL && $publicKey === '' && ! $existing?->public_key) {
            return back()->withInput()->with('error', 'Hubtel requires a merchant account number (public key field).');
        }

        PaymentGatewaySetting::query()->updateOrCreate(
            ['organization_id' => $organization->id],
            $attributes,
        );

        AuditLogger::record(
            $this->ownerRef($request),
            'integrations.gateway_connected',
            $organization->id,
            $this->ownerRef($request),
            \App\Models\Organization::class,
            $organization->id,
            ['provider' => $data['gateway_provider']],
        );

        return back()->with('success', 'Payment gateway saved.');
    }

    public function disconnectGateway(Request $request, PlanService $plans): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);

        PaymentGatewaySetting::query()
            ->where('organization_id', $organization->id)
            ->delete();

        AuditLogger::record(
            $this->ownerRef($request),
            'integrations.gateway_disconnected',
            $organization->id,
            $this->ownerRef($request),
            \App\Models\Organization::class,
            $organization->id,
        );

        return back()->with('success', 'Payment gateway disconnected.');
    }
}
