<?php

namespace Database\Seeders;

use App\Models\BillingHistory;
use App\Models\Business;
use App\Models\ChartOfAccount;
use App\Models\Contact;
use App\Models\Document;
use App\Models\DocumentData;
use App\Models\DocumentHistory;
use App\Models\PaymentMethod;
use App\Models\Subscription;
use App\Models\User;
use App\Models\UserActivity;
use App\Models\VatGstRate;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        // ---- Users: one per role ----
        $client = User::updateOrCreate(
            ['email' => 'client@entrybot.test'],
            [
                'full_name' => 'Clara Client',
                'password' => 'Passw0rd!',
                'role' => 'client',
                'is_email_verified' => true,
                'email_verified_at' => now(),
                'is_active' => true,
                'connected' => true,
            ]
        );

        $dataEntry = User::updateOrCreate(
            ['email' => 'dataentry@entrybot.test'],
            [
                'full_name' => 'Dan Dataentry',
                'password' => 'Passw0rd!',
                'role' => 'dataentry',
                'is_email_verified' => true,
                'email_verified_at' => now(),
                'is_active' => true,
            ]
        );

        $supervisor = User::updateOrCreate(
            ['email' => 'supervisor@entrybot.test'],
            [
                'full_name' => 'Sam Supervisor',
                'password' => 'Passw0rd!',
                'role' => 'supervisor',
                'is_email_verified' => true,
                'email_verified_at' => now(),
                'is_active' => true,
            ]
        );

        // A second client to test multi-business scoping
        $client2 = User::updateOrCreate(
            ['email' => 'client2@entrybot.test'],
            [
                'full_name' => 'Carla Client',
                'password' => 'Passw0rd!',
                'role' => 'client',
                'is_email_verified' => true,
                'email_verified_at' => now(),
                'is_active' => true,
            ]
        );

        // ---- Businesses for the primary client ----
        $acme = Business::updateOrCreate(
            ['user_id' => $client->id, 'business_name' => 'Acme Industries'],
            [
                'business_short_name' => 'ACME',
                'document_inbox' => 'inbox@acme.test',
                'business_type' => 'LLC',
                'organization_type' => 'Corporation',
                'contact_number' => '+1-555-0100',
                'registration_number' => 'REG-ACME-001',
                'address' => '100 Acme Way, Springfield',
                'email' => 'hello@acme.test',
                'country_id' => 1, 'currency_id' => 1, 'state_id' => 1,
                'is_organization' => true,
                'is_active' => true,
            ]
        );

        $globex = Business::updateOrCreate(
            ['user_id' => $client->id, 'business_name' => 'Globex Trading'],
            [
                'business_short_name' => 'GLBX',
                'document_inbox' => 'inbox@globex.test',
                'business_type' => 'PLC',
                'contact_number' => '+1-555-0200',
                'is_organization' => true,
                'is_active' => true,
            ]
        );

        Business::updateOrCreate(
            ['user_id' => $client2->id, 'business_name' => 'Initech'],
            ['business_short_name' => 'INTC', 'is_organization' => true, 'is_active' => true]
        );

        // ---- Subscriptions ----
        foreach ([$acme, $globex] as $b) {
            Subscription::updateOrCreate(
                ['business_id' => $b->id],
                [
                    'plan' => 'professional',
                    'status' => 'active',
                    'document_limit' => 500,
                    'documents_used' => 12,
                    'start_date' => now()->subMonth()->toDateString(),
                    'end_date' => now()->addMonths(11)->toDateString(),
                    'auto_renew' => true,
                ]
            );
        }

        // ---- Contacts (suppliers + customers) for Acme ----
        $supplierA = Contact::updateOrCreate(
            ['business_id' => $acme->id, 'name' => 'Office Supplies Co'],
            ['email' => 'sales@officesupplies.test', 'phone' => '+1-555-0301',
             'is_supplier' => true, 'is_customer' => false]
        );
        $supplierB = Contact::updateOrCreate(
            ['business_id' => $acme->id, 'name' => 'Cloud Hosting Inc'],
            ['email' => 'billing@cloudhost.test', 'is_supplier' => true, 'is_customer' => false]
        );
        $customerA = Contact::updateOrCreate(
            ['business_id' => $acme->id, 'name' => 'Big Retail Corp'],
            ['email' => 'ap@bigretail.test', 'is_supplier' => false, 'is_customer' => true]
        );
        $customerB = Contact::updateOrCreate(
            ['business_id' => $acme->id, 'name' => 'Local Cafe Ltd'],
            ['email' => 'cafe@local.test', 'is_supplier' => false, 'is_customer' => true]
        );

        // ---- Chart of accounts ----
        $coaSeeds = [
            ['1000', 'Cash', 'Asset'],
            ['1200', 'Accounts Receivable', 'Asset'],
            ['2000', 'Accounts Payable', 'Liability'],
            ['4000', 'Sales Revenue', 'Revenue'],
            ['5000', 'Cost of Goods Sold', 'Expense'],
            ['6000', 'Office Expenses', 'Expense'],
        ];
        foreach ($coaSeeds as [$code, $name, $type]) {
            ChartOfAccount::updateOrCreate(
                ['business_id' => $acme->id, 'code' => $code],
                ['name' => $name, 'type' => $type, 'is_active' => true]
            );
        }

        // ---- Payment methods ----
        foreach ([
            ['Business Checking', 'Bank', '****1234', 'Chase'],
            ['Corporate Visa', 'Credit Card', '****5678', 'Visa'],
            ['Cash on Hand', 'Cash', null, null],
        ] as [$name, $type, $acct, $bank]) {
            PaymentMethod::updateOrCreate(
                ['business_id' => $acme->id, 'name' => $name],
                ['type' => $type, 'account_number' => $acct, 'bank_name' => $bank, 'is_active' => true]
            );
        }

        // ---- VAT / GST rates ----
        foreach ([
            ['Standard 20%', 20.0, 'VAT'],
            ['Reduced 5%', 5.0, 'VAT'],
            ['Zero Rated', 0.0, 'VAT'],
            ['GST 10%', 10.0, 'GST'],
        ] as [$name, $rate, $type]) {
            VatGstRate::updateOrCreate(
                ['business_id' => $acme->id, 'name' => $name],
                ['rate' => $rate, 'type' => $type, 'is_active' => true]
            );
        }

        // ---- Documents across statuses & types ----
        $matrix = [
            ['SalesInvoice',     'Uploaded',     $customerA->id, 'customer'],
            ['SalesInvoice',     'Data Entered', $customerB->id, 'customer'],
            ['SalesInvoice',     'Processed',    $customerA->id, 'customer'],
            ['SalesInvoice',     'Exported',     $customerB->id, 'customer'],
            ['PurchaseInvoice',  'Uploaded',     $supplierA->id, 'supplier'],
            ['PurchaseInvoice',  'Data Entered', $supplierB->id, 'supplier'],
            ['PurchaseInvoice',  'Processing',   $supplierA->id, 'supplier'],
            ['PurchaseInvoice',  'Processed',    $supplierB->id, 'supplier'],
            ['PurchaseInvoice',  'Exported',     $supplierA->id, 'supplier'],
            ['BankStatement',    'Uploaded',     null,           null],
            ['BankStatement',    'Data Entered', null,           null],
            ['OtherDocuments',   'Uploaded',     null,           null],
            ['OtherDocuments',   'Processed',    null,           null],
        ];

        $samplePdf = file_get_contents(__DIR__ . '/sample-invoice.pdf');

        foreach ($matrix as $i => [$type, $status, $contactId, $contactKind]) {
            $fileName = sprintf('seed-%s-%03d.pdf', strtolower($type), $i + 1);
            $dir = storage_path('app/public/Uploads/Documents/' . $type);
            if (!is_dir($dir)) @mkdir($dir, 0755, true);
            file_put_contents($dir . '/' . $fileName, $samplePdf);

            $doc = Document::create([
                'business_id'    => $acme->id,
                'document_type'  => $type,
                'file_name'      => $fileName,
                'file_url'       => '/storage/Uploads/Documents/' . $type . '/' . $fileName,
                'mime_type'      => 'application/pdf',
                'file_size'      => strlen($samplePdf),
                'status'         => $status,
                'uploaded_by'    => $client->id,
                'uploaded_date'  => now()->subDays(rand(1, 30)),
                'processed_by'   => $status === 'Uploaded' ? null : $dataEntry->id,
                'processed_date' => $status === 'Uploaded' ? null : now()->subDays(rand(0, 5)),
                'contact_id'     => $contactId,
                'is_deleted'     => false,
            ]);

            if ($status !== 'Uploaded') {
                $subtotal = rand(100, 5000);
                $tax = round($subtotal * 0.2, 2);
                DocumentData::create([
                    'document_id'    => $doc->id,
                    'invoice_number' => 'INV-' . str_pad((string) ($i + 1001), 5, '0', STR_PAD_LEFT),
                    'supplier_id'    => $contactKind === 'supplier' ? $contactId : null,
                    'customer_id'    => $contactKind === 'customer' ? $contactId : null,
                    'document_date'  => now()->subDays(rand(5, 60))->toDateString(),
                    'due_date'       => now()->addDays(rand(5, 30))->toDateString(),
                    'subtotal'       => $subtotal,
                    'tax_total'      => $tax,
                    'total_amount'   => $subtotal + $tax,
                    'currency'       => 'USD',
                    'description'    => "Seeded {$type} #" . ($i + 1),
                    'line_items'     => [
                        ['description' => 'Item A', 'qty' => 2, 'unitPrice' => 50, 'amount' => 100],
                        ['description' => 'Item B', 'qty' => 1, 'unitPrice' => $subtotal - 100, 'amount' => $subtotal - 100],
                    ],
                ]);
            }

            DocumentHistory::create([
                'document_id' => $doc->id,
                'user_id'     => $client->id,
                'action'      => 'Uploaded',
                'to_status'   => 'Uploaded',
            ]);
            if ($status !== 'Uploaded') {
                DocumentHistory::create([
                    'document_id' => $doc->id,
                    'user_id'     => $dataEntry->id,
                    'action'      => $status,
                    'from_status' => 'Uploaded',
                    'to_status'   => $status,
                ]);
            }
        }

        // A deleted document for the recycle bin view
        $deleted = Document::create([
            'business_id'   => $acme->id,
            'document_type' => 'OtherDocuments',
            'file_name'     => 'old-receipt.pdf',
            'file_url'      => '/storage/Uploads/Documents/OtherDocuments/old-receipt.pdf',
            'mime_type'     => 'application/pdf',
            'status'        => 'Deleted',
            'uploaded_by'   => $client->id,
            'uploaded_date' => now()->subMonths(2),
            'is_deleted'    => true,
        ]);
        DocumentHistory::create([
            'document_id' => $deleted->id,
            'user_id'     => $client->id,
            'action'      => 'Deleted',
            'to_status'   => 'Deleted',
        ]);

        // ---- Billing history ----
        foreach (range(1, 3) as $m) {
            BillingHistory::create([
                'business_id'    => $acme->id,
                'subscription_id'=> $acme->subscription?->id,
                'invoice_number' => 'BILL-' . now()->subMonths($m)->format('Ym') . '-001',
                'amount'         => 49.99,
                'currency'       => 'USD',
                'status'         => 'paid',
                'billing_date'   => now()->subMonths($m)->toDateString(),
                'paid_date'      => now()->subMonths($m)->addDays(2)->toDateString(),
                'description'    => 'Professional plan — monthly',
            ]);
        }

        // ---- Activity logs ----
        foreach ([$client, $dataEntry, $supervisor] as $u) {
            UserActivity::create([
                'user_id'     => $u->id,
                'business_id' => $acme->id,
                'action'      => 'Login',
                'description' => $u->full_name . ' signed in',
                'ip_address'  => '127.0.0.1',
            ]);
        }

        $this->command?->info('');
        $this->command?->info('Seed users (password for all: Passw0rd!):');
        $this->command?->info('  client@entrybot.test       (client)');
        $this->command?->info('  client2@entrybot.test      (client, separate businesses)');
        $this->command?->info('  dataentry@entrybot.test    (dataentry)');
        $this->command?->info('  supervisor@entrybot.test   (supervisor)');
    }
}
