<?php

namespace Database\Seeders;

use App\Models\Branch;
use App\Models\Agent;
use App\Models\Customer;
use App\Models\Loan;
use App\Models\LoanProduct;
use App\Models\PlatformProduct;
use App\Models\RoleProfile;
use App\Models\SavingsAccount;
use App\Models\SavingsProduct;
use App\Models\SavingsTransaction;
use App\Models\Subscription;
use App\Models\SubscriptionPlan;
use App\Models\SystemSetting;
use App\Models\Tenant;
use App\Models\User;
use App\Services\AccountingService;
use App\Services\LoanCalculator;
use App\Services\NumberGenerator;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        DB::transaction(function (): void {
            $plans = collect([
                ['Starter', 25000, 250000, 5, 500, 1, ['Customer KYC', 'Savings', 'Loans', 'Basic reports']],
                ['Growth', 60000, 600000, 15, 2500, 5, ['All Starter features', 'Accounting', 'Branch management', 'PDF reports']],
                ['Enterprise', 150000, 1500000, 50, 10000, 20, ['All Growth features', 'Priority support', 'Advanced limits']],
            ])->mapWithKeys(function ($plan) {
                [$name, $monthly, $yearly, $staff, $customers, $branches, $features] = $plan;

                $model = SubscriptionPlan::updateOrCreate(
                    ['slug' => str($name)->slug()->toString()],
                    [
                        'name' => $name,
                        'description' => $name.' plan for microfinance operators.',
                        'price_monthly' => $monthly,
                        'price_yearly' => $yearly,
                        'staff_limit' => $staff,
                        'customer_limit' => $customers,
                        'branch_limit' => $branches,
                        'storage_limit_mb' => 1024,
                        'features' => $features,
                        'is_active' => true,
                    ]
                );

                return [$name => $model];
            });

            foreach ([
                'platform_name' => 'NewKipp Microfinance Solution',
                'support_email' => 'support@example.com',
                'trial_days' => '14',
                'default_agent_commission_rate' => (string) Agent::SELF_ONBOARDING_COMMISSION_RATE,
                'default_merchant_referral_commission_rate' => (string) Agent::REFERRAL_COMMISSION_RATE,
                'bank_details' => "Bank: Demo Bank\nAccount Name: NewKipp Microfinance Solution\nAccount Number: 0000000000",
            ] as $key => $value) {
                SystemSetting::updateOrCreate(['key' => $key], ['value' => $value]);
            }

            $appUrl = rtrim((string) config('app.url'), '/');
            foreach ([
                [
                    'name' => 'Microfinance & Cooperative',
                    'slug' => 'microfinance-cooperative',
                    'category' => PlatformProduct::CATEGORY_MICROFINANCE,
                    'short_description' => 'Manage members, savings, loans, repayments, investments, bill payments, and reports.',
                    'description' => 'The main microfinance and cooperative platform with tenant portals, member portal, offline/online sync, accounting, and mobile app support.',
                    'website_url' => $appUrl,
                    'signup_url' => $appUrl.'/register-company',
                    'color' => '#155e75',
                    'icon' => 'bi-bank',
                    'sort_order' => 1,
                    'is_featured' => true,
                ],
                [
                    'name' => 'Point of Sale',
                    'slug' => 'point-of-sale',
                    'category' => PlatformProduct::CATEGORY_POS,
                    'short_description' => 'Retail POS for sales, inventory, receipts, staff, branches, and daily cash reports.',
                    'description' => 'Use the merchant link to onboard shops, supermarkets, pharmacies, boutiques, and distributors.',
                    'website_url' => 'https://pos.example.com',
                    'signup_url' => 'https://pos.example.com/register',
                    'color' => '#dc2626',
                    'icon' => 'bi-receipt',
                    'sort_order' => 2,
                    'is_featured' => true,
                ],
                [
                    'name' => 'Hotel Management',
                    'slug' => 'hotel-management',
                    'category' => PlatformProduct::CATEGORY_HOTEL,
                    'short_description' => 'Run bookings, rooms, guests, restaurant orders, payments, and occupancy reports.',
                    'description' => 'Designed for hotels, guest houses, short-let apartments, resorts, and event lodges.',
                    'website_url' => 'https://hotel.example.com',
                    'signup_url' => 'https://hotel.example.com/register',
                    'color' => '#7c3aed',
                    'icon' => 'bi-building',
                    'sort_order' => 3,
                    'is_featured' => true,
                ],
                [
                    'name' => 'HR & Payroll',
                    'slug' => 'hr-payroll',
                    'category' => PlatformProduct::CATEGORY_HR,
                    'short_description' => 'Manage staff records, attendance, payroll, leave, departments, and HR reports.',
                    'description' => 'A practical HR platform for SMEs, schools, hospitals, hotels, factories, and service companies.',
                    'website_url' => 'https://hr.example.com',
                    'signup_url' => 'https://hr.example.com/register',
                    'color' => '#2563eb',
                    'icon' => 'bi-people',
                    'sort_order' => 4,
                    'is_featured' => true,
                ],
                [
                    'name' => 'Hospital & Clinic',
                    'slug' => 'hospital-clinic',
                    'category' => PlatformProduct::CATEGORY_HOSPITAL,
                    'short_description' => 'Patient registration, appointments, billing, pharmacy, lab, and clinical records.',
                    'description' => 'Built for hospitals, clinics, labs, pharmacies, and diagnostic centres.',
                    'website_url' => 'https://hospital.example.com',
                    'signup_url' => 'https://hospital.example.com/register',
                    'color' => '#16a34a',
                    'icon' => 'bi-hospital',
                    'sort_order' => 5,
                    'is_featured' => true,
                ],
            ] as $product) {
                PlatformProduct::updateOrCreate(
                    ['slug' => $product['slug']],
                    [
                        ...$product,
                        'monthly_price' => $product['monthly_price'] ?? null,
                        'yearly_price' => $product['yearly_price'] ?? null,
                        'onboarding_commission_rate' => Agent::SELF_ONBOARDING_COMMISSION_RATE,
                        'referral_commission_rate' => Agent::REFERRAL_COMMISSION_RATE,
                        'is_active' => true,
                    ]
                );
            }

            User::updateOrCreate(
                ['email' => 'admin@microfinance.test'],
                ['name' => 'Platform Owner', 'role' => User::ROLE_SUPER_ADMIN, 'password' => 'password', 'status' => 'active']
            );

            $agentUser = User::updateOrCreate(
                ['email' => 'agent@microfinance.test'],
                ['name' => 'Demo Merchant', 'role' => User::ROLE_AGENT, 'phone' => '+2348011111111', 'password' => 'password', 'status' => 'active']
            );

            $agent = Agent::updateOrCreate(
                ['user_id' => $agentUser->id],
                [
                    'code' => 'MCH-DEMO001',
                    'slug' => 'demo-merchant',
                    'business_name' => 'Demo Merchant Network',
                    'commission_rate' => Agent::SELF_ONBOARDING_COMMISSION_RATE,
                    'merchant_type' => Agent::MERCHANT_HYBRID,
                    'onboarding_commission_rate' => Agent::SELF_ONBOARDING_COMMISSION_RATE,
                    'referral_commission_rate' => Agent::REFERRAL_COMMISSION_RATE,
                    'status' => Agent::STATUS_ACTIVE,
                    'kyc_status' => Agent::KYC_VERIFIED,
                    'kyc_submitted_at' => now(),
                    'kyc_verified_at' => now(),
                    'country' => 'Nigeria',
                    'state' => 'Lagos',
                    'city' => 'Ikeja',
                    'residential_address' => '12 Merchant Road, Ikeja, Lagos',
                    'bank_name' => 'Demo Bank',
                    'account_name' => 'Demo Merchant',
                    'account_number' => '1234567890',
                    'approved_at' => now(),
                ]
            );

            $tenant = Tenant::updateOrCreate(
                ['slug' => 'demo-microfinance'],
                [
                    'subscription_plan_id' => $plans['Growth']->id,
                    'agent_id' => $agent->id,
                    'agent_assigned_at' => now(),
                    'agent_commission_type' => Agent::MERCHANT_ONBOARDING,
                    'name' => 'Demo Microfinance',
                    'subdomain' => 'demo-microfinance',
                    'owner_name' => 'Demo Owner',
                    'email' => 'owner@demo.test',
                    'phone' => '+2348000000000',
                    'address' => '12 Market Road, Lagos',
                    'primary_color' => '#155e75',
                    'status' => 'active',
                    'settings' => [
                        'currency' => 'NGN',
                        'interest_rate' => 5,
                        'penalty_rate' => 1,
                        'account_number_mode' => 'random',
                        'account_number_prefixes' => null,
                    ],
                    'approved_at' => now(),
                    'trial_ends_at' => now()->addDays(14),
                    'subscription_ends_at' => now()->addMonth(),
                ]
            );

            $branch = Branch::withoutGlobalScopes()->updateOrCreate(
                ['tenant_id' => $tenant->id, 'code' => 'HQ'],
                ['name' => 'Head Office', 'address' => $tenant->address, 'phone' => $tenant->phone, 'is_active' => true]
            );

            SavingsProduct::createDefaultsForTenant($tenant);
            RoleProfile::createDefaultsForTenant($tenant);

            foreach ([
                ['Demo Owner', 'owner@demo.test', User::ROLE_TENANT_ADMIN],
                ['Branch Manager', 'manager@demo.test', User::ROLE_MANAGER],
                ['Loan Officer', 'loan@demo.test', User::ROLE_LOAN_OFFICER],
                ['Accountant', 'accountant@demo.test', User::ROLE_ACCOUNTANT],
            ] as [$name, $email, $role]) {
                $roleProfileId = RoleProfile::withoutGlobalScopes()
                    ->where('tenant_id', $tenant->id)
                    ->where('base_role', $role)
                    ->value('id');

                User::updateOrCreate(
                    ['email' => $email],
                    ['tenant_id' => $tenant->id, 'branch_id' => $branch->id, 'name' => $name, 'role' => $role, 'role_profile_id' => $roleProfileId, 'password' => 'password', 'status' => 'active']
                );
            }

            Subscription::withoutGlobalScopes()->updateOrCreate(
                ['tenant_id' => $tenant->id, 'reference' => 'SEED-SUBSCRIPTION'],
                ['subscription_plan_id' => $plans['Growth']->id, 'status' => 'active', 'billing_cycle' => 'monthly', 'amount' => 60000, 'starts_at' => now(), 'ends_at' => now()->addMonth()]
            );

            $accounting = app(AccountingService::class);
            $accounting->ensureChartOfAccounts($tenant);

            $product = LoanProduct::withoutGlobalScopes()->updateOrCreate(
                ['tenant_id' => $tenant->id, 'name' => 'Market Trader Loan'],
                [
                    'loan_number_prefix' => 'LON',
                    'interest_rate' => 8,
                    'interest_method' => 'flat',
                    'repayment_frequency' => 'monthly',
                    'term_value' => 3,
                    'term_unit' => 'months',
                    'term_days' => 90,
                    'penalty_type' => 'percentage',
                    'penalty_rate' => 1,
                    'processing_fee_type' => 'percentage',
                    'processing_fee_value' => 1,
                    'minimum_amount' => 10000,
                    'maximum_amount' => 500000,
                    'guarantor_requirement' => 'optional',
                    'collateral_requirement' => 'optional',
                    'show_on_member_portal' => true,
                    'show_on_public_website' => true,
                    'is_active' => true,
                ]
            );

            collect([
                ['Amina', 'Okafor', '08030000001'],
                ['Bola', 'Adeyemi', '08030000002'],
                ['Chinedu', 'Nwosu', '08030000003'],
            ])->each(function ($row) use ($tenant, $branch, $accounting, $product): void {
                [$first, $last, $phone] = $row;
                $customer = Customer::withoutGlobalScopes()->firstOrCreate(
                    ['tenant_id' => $tenant->id, 'phone' => $phone],
                    [
                        'branch_id' => $branch->id,
                        'account_number' => NumberGenerator::customerAccount($tenant),
                        'first_name' => $first,
                        'last_name' => $last,
                        'address' => 'Customer address',
                        'status' => 'active',
                        'kyc_status' => 'verified',
                    ]
                );

                $savings = SavingsAccount::withoutGlobalScopes()->firstOrCreate(
                    ['tenant_id' => $tenant->id, 'customer_id' => $customer->id],
                    [
                        'savings_product_id' => SavingsProduct::withoutGlobalScopes()->where('tenant_id', $tenant->id)->where('name', 'Regular Savings')->value('id'),
                        'account_number' => NumberGenerator::make($tenant, 'SAV', SavingsAccount::class, 'account_number'),
                        'product_name' => 'Regular Savings',
                        'product_type' => 'regular',
                        'balance' => 0,
                        'status' => 'active',
                        'opened_at' => now(),
                    ]
                );

                if ((float) $savings->balance === 0.0) {
                    $transaction = SavingsTransaction::withoutGlobalScopes()->create([
                        'tenant_id' => $tenant->id,
                        'savings_account_id' => $savings->id,
                        'customer_id' => $customer->id,
                        'type' => 'deposit',
                        'amount' => 50000,
                        'balance_before' => 0,
                        'balance_after' => 50000,
                        'reference' => NumberGenerator::reference('DEP'),
                        'method' => 'cash',
                        'description' => 'Opening deposit',
                        'transacted_at' => now(),
                    ]);
                    $savings->update(['balance' => 50000]);
                    $accounting->recordSavings($transaction);
                }

                if ($first === 'Amina' && ! Loan::withoutGlobalScopes()->where('tenant_id', $tenant->id)->where('customer_id', $customer->id)->exists()) {
                    $quote = app(LoanCalculator::class)->quote(100000, $product);
                    $loan = Loan::withoutGlobalScopes()->create([
                        'tenant_id' => $tenant->id,
                        'branch_id' => $branch->id,
                        'customer_id' => $customer->id,
                        'loan_product_id' => $product->id,
                        'loan_number' => NumberGenerator::make($tenant, $product->loan_number_prefix ?: 'LON', Loan::class, 'loan_number'),
                        'principal' => 100000,
                        'interest_rate' => $product->interest_rate,
                        'interest_method' => $product->interest_method,
                        'interest_amount' => $quote['interest_amount'],
                        'processing_fee' => $quote['processing_fee'],
                        'total_payable' => $quote['total_payable'],
                        'amount_disbursed' => 100000,
                        'balance' => $quote['total_payable'],
                        'repayment_frequency' => $product->repayment_frequency,
                        'term_days' => $product->term_days,
                        'term_value' => $product->term_value,
                        'term_unit' => $product->term_unit,
                        'status' => 'active',
                        'purpose' => 'Working capital',
                        'application_date' => today(),
                        'first_repayment_date' => today()->addMonthNoOverflow(),
                        'approved_at' => now(),
                        'disbursed_at' => now(),
                        'due_date' => today()->addDays($product->term_days),
                    ]);
                    app(LoanCalculator::class)->createSchedule($loan);
                    $accounting->recordLoanDisbursement($loan);
                }
            });
        });
    }
}
