<?php

namespace Tests\Feature;

use App\Models\Branch;
use App\Models\Business;
use App\Models\Customer;
use App\Models\Loan;
use App\Models\LoanProduct;
use App\Models\ReminderNotificationLog;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class NextSmsIntegrationTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        $this->seed(DatabaseSeeder::class);
    }

    public function test_nextsms_credentials_are_saved_encrypted_and_never_audited_in_plain_text(): void
    {
        $admin=User::where('username','admin')->firstOrFail();
        $business=Business::firstOrFail();
        $secret='nextsms-secret-api-key-123';

        $this->actingAs($admin)->put(route('notification-settings.update'),[
            'reminders_enabled'=>1,
            'reminder_pre_due_days'=>'3,1',
            'reminder_due_date_enabled'=>1,
            'reminder_overdue_enabled'=>1,
            'reminder_overdue_frequency'=>'daily',
            'reminder_channels'=>['in_system','sms'],
            'nextsms_api_key'=>$secret,
            'nextsms_sender_id'=>'MICROFIN',
        ])->assertRedirect()->assertSessionHasNoErrors();

        $business->refresh();
        $this->assertSame($secret,$business->nextsms_api_key);
        $this->assertSame('MICROFIN',$business->nextsms_sender_id);

        $raw=(string)DB::table('businesses')->where('id',$business->id)->value('nextsms_api_key');
        $this->assertNotSame($secret,$raw);
        $this->assertStringNotContainsString($secret,$raw);

        $audit=(string)DB::table('audit_logs')->where('action','notifications.settings.updated')->latest('id')->value('after');
        $this->assertStringNotContainsString($secret,$audit);
        $this->assertStringContainsString('MICROFIN',$audit);
    }

    public function test_sms_reminder_uses_nextsms_api_sender_id_basic_key_and_international_phone_format(): void
    {
        $target='2026-08-20';
        $business=Business::firstOrFail();
        $business->update([
            'reminders_enabled'=>true,
            'reminder_pre_due_days'=>[1],
            'reminder_due_date_enabled'=>false,
            'reminder_overdue_enabled'=>false,
            'reminder_channels'=>['sms'],
            'nextsms_api_key'=>'api-key-xyz',
            'nextsms_sender_id'=>'NEVANA',
        ]);

        $branch=Branch::create(['business_id'=>$business->id,'name'=>'NextSMS Branch','status'=>'active']);
        $customer=Customer::create([
            'branch_id'=>$branch->id,'customer_number'=>'CUS-NXS-0001','identity_mode'=>'without_nin',
            'first_name'=>'Asha','last_name'=>'Juma','phone'=>'0756123456','status'=>'active',
        ]);
        $product=LoanProduct::create([
            'business_id'=>$business->id,'name'=>'NextSMS Product','minimum_amount'=>'1000.00','maximum_amount'=>'500000.00',
            'duration'=>1,'duration_unit'=>'months','interest_rate'=>'0.000000','interest_calculation_method'=>'flat','repayment_frequency'=>'monthly',
            'grace_period_days'=>0,'late_payment_penalty_type'=>'fixed','late_payment_penalty_value'=>'0.000000','processing_fee_type'=>'fixed','processing_fee_value'=>'0.000000',
            'insurance_fee_type'=>'fixed','insurance_fee_value'=>'0.000000','other_charges'=>'0.00','collateral_required'=>false,'guarantor_required'=>false,'status'=>'active',
        ]);
        $loan=Loan::create([
            'branch_id'=>$branch->id,'customer_id'=>$customer->id,'loan_product_id'=>$product->id,'sequence_number'=>1,'sequence_year'=>2026,'loan_number'=>'LN-NXS-2026-0001',
            'principal'=>'10000.00','interest'=>'0.00','processing_fee'=>'0.00','insurance_fee'=>'0.00','other_charges'=>'0.00','fees'=>'0.00','total_repayment'=>'10000.00',
            'principal_outstanding'=>'10000.00','interest_outstanding'=>'0.00','fees_outstanding'=>'0.00','penalties_outstanding'=>'0.00','total_outstanding'=>'10000.00','total_paid'=>'0.00',
            'purpose'=>'NextSMS testing','schedule_start_date'=>$target,'status'=>'active','disbursed_at'=>$target,'activated_at'=>$target,'schedule_activated_at'=>$target,
        ]);
        $loan->installments()->create([
            'installment_number'=>1,'principal'=>'10000.00','interest'=>'0.00','fees'=>'0.00','amount_due'=>'10000.00','due_date'=>'2026-08-21',
            'amount_paid'=>'0.00','remaining'=>'10000.00','status'=>'upcoming','principal_paid'=>'0.00','interest_paid'=>'0.00','fees_paid'=>'0.00','penalty_due'=>'0.00','penalty_paid'=>'0.00',
        ]);

        $endpoint='https://messaging-service.co.tz/api/sms/v1/text/single';
        config(['reminders.providers.nextsms.endpoint'=>$endpoint]);
        Http::fake([$endpoint=>Http::response(['status'=>'success','message_id'=>'sms-123'],200)]);

        $this->artisan('notifications:dispatch-reminders',['--date'=>$target])->assertSuccessful();

        $log=ReminderNotificationLog::firstOrFail();
        $this->assertSame('sms',$log->channel);
        $this->assertSame('delivered',$log->status);
        $this->assertSame('255756123456',$log->recipient);
        $this->assertStringContainsString('sms-123',(string)$log->provider_response);

        Http::assertSent(function($request) use($endpoint,$log): bool {
            return $request->url()===$endpoint
                && $request->hasHeader('Authorization','Basic api-key-xyz')
                && $request['from']==='NEVANA'
                && $request['to']==='255756123456'
                && $request['text']===$log->message;
        });
    }

    public function test_blank_api_key_keeps_existing_secret_and_clear_option_removes_it(): void
    {
        $admin=User::where('username','admin')->firstOrFail();
        $business=Business::firstOrFail();
        $business->update(['nextsms_api_key'=>'keep-me','nextsms_sender_id'=>'KEEPER']);

        $base=[
            'reminder_pre_due_days'=>'3,1','reminder_overdue_frequency'=>'daily','reminder_channels'=>['in_system'],
            'nextsms_api_key'=>'','nextsms_sender_id'=>'KEEPER',
        ];
        $this->actingAs($admin)->put(route('notification-settings.update'),$base)->assertRedirect()->assertSessionHasNoErrors();
        $this->assertSame('keep-me',$business->fresh()->nextsms_api_key);

        $this->actingAs($admin)->put(route('notification-settings.update'),$base+['clear_nextsms_api_key'=>1])->assertRedirect()->assertSessionHasNoErrors();
        $this->assertNull($business->fresh()->nextsms_api_key);
    }
}
