<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\BusinessType;
use App\Models\Company;
use App\Models\Setting;
use App\Models\User;
use App\Models\Warehouse;
use Illuminate\Auth\Events\Registered;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Schema;
use Illuminate\Validation\Rules;
use Inertia\Inertia;
use Inertia\Response;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class RegisteredUserController extends Controller
{
    /**
     * Constructor - Ensure all tables have company_id and business_id columns
     */
    public function __construct()
    {
        // Ensure all tables have company_id and business_id columns (except companies table)
        $this->ensureAllTablesHaveCompanyAndBusinessColumns();
    }

    /**
     * Generate company code
     */
    private function generateCompanyCode()
    {
        $lastCompany = Company::orderByDesc('code')->first();
        if (! $lastCompany) {
            return '00001';
        }

        return sprintf('%05d', (int) $lastCompany->code + 1);
    }

    /**
     * Ensure company_id column exists in the given table
     */
    private function ensureCompanyIdColumn(string $tableName): void
    {
        // Skip companies table (it doesn't have company_id - it IS the company)
        if ($tableName === 'companies') {
            return;
        }

        // Check if companies table exists first (needed for foreign key)
        if (! Schema::hasTable('companies')) {
            return;
        }

        if (! Schema::hasColumn($tableName, 'company_id')) {
            try {
                Schema::table($tableName, function (Blueprint $table) {
                    $table->unsignedBigInteger('company_id')->nullable()->after('id');
                    $table->index('company_id');
                });

                // Try to add foreign key constraint separately
                try {
                    Schema::table($tableName, function (Blueprint $table) {
                        $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade');
                    });
                } catch (\Exception $e) {
                    // Foreign key might already exist, ignore
                }
            } catch (\Exception $e) {
                // Column might have been added by another process, ignore
            }
        }
    }

    /**
     * Ensure business_id column exists in the given table
     */
    private function ensureBusinessIdColumn(string $tableName): void
    {
        // Skip companies table (it doesn't have business_id)
        if ($tableName === 'companies') {
            return;
        }

        // Skip system tables that shouldn't have business_id
        $excludedTables = [

            'password_reset_tokens', // Laravel auth
            'personal_access_tokens', // Laravel Sanctum
            'sessions', // Laravel sessions
            'cache', // Laravel cache
            'cache_locks', // Laravel cache
            'jobs', // Laravel queue
            'job_batches', // Laravel queue
            'failed_jobs', // Laravel queue
        ];

        if (in_array($tableName, $excludedTables)) {
            return;
        }

        // Check if business_types table exists first (needed for foreign key)
        if (! Schema::hasTable('business_types')) {
            return;
        }

        if (! Schema::hasColumn($tableName, 'business_id')) {
            try {
                Schema::table($tableName, function (Blueprint $table) {
                    $table->unsignedBigInteger('business_id')->nullable()->after('id');
                    $table->index('business_id');
                });

                // Try to add foreign key constraint separately
                try {
                    Schema::table($tableName, function (Blueprint $table) {
                        $table->foreign('business_id')->references('id')->on('business_types')->onDelete('set null');
                    });
                } catch (\Exception $e) {
                    // Foreign key might already exist, ignore
                }
            } catch (\Exception $e) {
                // Column might have been added by another process, ignore
            }
        }
    }

    /**
     * Ensure all tables have company_id and business_id columns (except companies table)
     */
    private function ensureAllTablesHaveCompanyAndBusinessColumns(): void
    {
        // Get all table names from database
        $tables = DB::select('SHOW TABLES');
        $dbName = DB::getDatabaseName();
        $tableKey = "Tables_in_{$dbName}";

        foreach ($tables as $table) {
            $tableName = $table->$tableKey;

            // Skip companies table
            if ($tableName === 'companies') {
                continue;
            }

            // Ensure company_id column exists
            $this->ensureCompanyIdColumn($tableName);

            // Ensure business_id column exists
            $this->ensureBusinessIdColumn($tableName);
        }
    }

    /**
     * Display the registration view.
     */
    public function create(): Response
    {
        $businessTypes = BusinessType::orderBy('name')->get();

        return Inertia::render('Auth/Register', [
            'businessTypes' => $businessTypes,
        ]);
    }

    /**
     * Handle an incoming registration request.
     *
     * @throws \Illuminate\Validation\ValidationException
     */
    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            // Company/Client Information
            'company_name' => 'required|string|max:255',
            'business_type_id' => 'required|exists:business_types,id',
            'proprietor' => 'nullable|string|max:255',
            'email' => [
                'required',
                'string',
                'lowercase',
                'email',
                'max:255',
                'unique:companies,email',
                'unique:users,email',
            ],
            'number' => 'nullable|string|max:255',
            'nid' => 'nullable|string|max:255',
            'address' => 'nullable|string|max:500',
            // User Account Information
            'name' => 'required|string|max:255|unique:users,name',
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        DB::beginTransaction();
        try {
            // Generate company code
            $companyCode = $this->generateCompanyCode();

            // Create Company record
            $companyData = [
                'name' => $request->company_name,
                'code' => $companyCode,
                'business_type_id' => $request->business_type_id,
                'proprietor' => $request->proprietor,
                'email' => $request->email,
                'number' => $request->number,
                'nid' => $request->nid,
                'address' => $request->address,
                'status' => '0', // Pending approval by default
            ];

            $company = Company::create($companyData);

            // Create setting for the company with business_id
            Setting::create([
                'company_id' => $company->id,
                'business_id' => $company->business_type_id,
                'shop_name' => $company->name,
                'shop_owner' => $company->proprietor,
                'shop_address' => $company->address,
                'shop_phone' => $company->number,
                'shop_email' => $company->email,
                'invoice_currency_symbol' => '৳',

            ]);

            // Create warehouse for the company
            $warehouse = Warehouse::create([
                'name' => $company->code.' - Warehouse',
                'address' => $company->address,
                'owner' => $company->proprietor,
                'number' => $company->number,
                'description' => 'Main warehouse for '.$company->name,
                'status' => '1', // Active
                'company_id' => $company->id,
            ]);

            // Create or get Company Admin role (company-wise role)
            $roleName = 'Company Admin - '.$company->code;
            $role = Role::firstOrCreate(
                ['name' => $roleName],
                [
                    'guard_name' => 'web',
                    'company_id' => $company->id,
                ]
            );

            // Update company_id if role already existed
            if ($role->company_id !== $company->id) {
                $role->update(['company_id' => $company->id]);
            }

            // Assign basic permissions to company role (component-wise permissions)
            // Exclude all admin access permissions
            $companyPermissions = [
                'opening_super_admin_access',
                'adjustment_super_admin_access',
                'purchase_return_super_admin_access',
                'purchase_super_admin_access',
                'transfer_super_admin_access',
                'sales_admin_access',
                'sales_return_super_admin_access',
                'customer_retailer_superAdmin_access',
                'customer_collection_superAdmin_access',
                'report_super_admin_access',
                'fqty_pos',
                'customer_branch_create',
                'customer_branch_delete',
                'customer_branch_edit',
                'customer_branch_view',
                'customer_branch_use',
                'requsition_document_wise',
                'warehoue_view',
                'warehoue_setup_view',
                'warehoue_setup_create',
                'warehoue_setup_edit',
                'warehoue_setup_delete',

            ];

            $permissions = Permission::whereNotIn('name', $companyPermissions)->get();
            $role->syncPermissions($permissions);

            // Create User account
            $userData = [
                'name' => $request->name,
                'email' => $request->email,
                'password' => Hash::make($request->password),
            ];

            // Associate user with company if company_id column exists
            if (Schema::hasColumn('users', 'company_id')) {
                $userData['company_id'] = $company->id;
                $userData['shop_id'] = $warehouse->id;
            }

            $user = User::create($userData);

            // Assign role to user
            $user->assignRole($role);

            // Clear permission cache
            app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

            event(new Registered($user));

            DB::commit();

            Artisan::call('optimize:clear');

            // Redirect to login page with success message
            return redirect('/')
                ->with('success', 'Company registered successfully! Please login to continue.');

        } catch (\Exception $e) {
            DB::rollBack();

            return redirect()->back()->withErrors([
                'error' => 'Registration failed. Please try again.',
            ])->withInput();
        }
    }
}
