<?php
namespace App\Http\Controllers\Api\RBAC;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;

class ModuleController extends Controller
{
    /**
     * GET /api/modules
     * List all active modules
     */
    public function index(Request $request)
    {
        try {
            $nowUtc = Carbon::now('UTC');
            $adminId =  1;

            $query = DB::table('modules')
                ->whereNull('deleted_at_utc');

            // Optional filters
            if ($request->has('status')) {
                $query->where('status', $request->status);
            }

            if ($request->has('is_active')) {
                $query->where('is_active', $request->is_active);
            }

            if ($request->has('search')) {
                $query->where(function($q) use ($request) {
                    $q->where('name_en', 'like', "%{$request->search}%")
                      ->orWhere('code', 'like', "%{$request->search}%");
                });
            }

            $modules = $query->orderBy('display_order')->get();

            // Log access
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Modules Listed',
                'action_type' => 'view',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'request_url' => $request->fullUrl(),
                'request_method' => 'GET',
                'response_code' => 200,
                'created_at_utc' => $nowUtc,
            ]);

            return response()->json([
                'message' => 'Modules retrieved successfully',
                'data' => $modules
            ], 200);

        } catch (\Exception $e) {
            Log::error('Modules list failed', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to retrieve modules'], 500);
        }
    }

    /**
     * GET /api/modules/{id}
     * Get single module details
     */
    public function show(Request $request, int $id)
    {
        try {
            $nowUtc = Carbon::now('UTC');
            $adminId = 1;

            $module = DB::table('modules')
                ->where('id', $id)
                ->whereNull('deleted_at_utc')
                ->first();

            if (!$module) {
                return response()->json(['error' => 'Module not found'], 404);
            }

            // Log access
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Module Viewed',
                'action_type' => 'view',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'record_id' => $id,
                'record_identifier' => $module->code,
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'request_url' => $request->fullUrl(),
                'request_method' => 'GET',
                'response_code' => 200,
                'created_at_utc' => $nowUtc,
            ]);

            return response()->json([
                'message' => 'Module retrieved successfully',
                'data' => $module
            ], 200);

        } catch (\Exception $e) {
            Log::error('Module show failed', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to retrieve module'], 500);
        }
    }

    /**
     * POST /api/modules
     * Create new module
     */
    public function store(Request $request)
    {
        $nowUtc = Carbon::now('UTC');
        $adminId = 1;

        try {
            // 1. Validate Input
            $validated = $request->validate([
                'name_en' => 'required|string|max:100',
                'name_native' => 'nullable|string|max:100',
                'code' => 'required|string|max:50|unique:modules,code',
                'description_en' => 'nullable|string',
                'description_native' => 'nullable|string',
                'icon' => 'nullable|string|max:50',
                'display_order' => 'nullable|integer',
                'is_active' => 'nullable|boolean',
            ]);

            // 2. Insert Module
            $moduleId = DB::table('modules')->insertGetId([
                'name_en' => $validated['name_en'],
                'name_native' => $validated['name_native'] ?? null,
                'code' => $validated['code'],
                'description_en' => $validated['description_en'] ?? null,
                'description_native' => $validated['description_native'] ?? null,
                'icon' => $validated['icon'] ?? null,
                'display_order' => $validated['display_order'] ?? 0,
                'is_active' => $validated['is_active'] ?? true,
                'status' => 'active',
                // UTC Timestamps
                'created_at_utc' => $nowUtc,
                'updated_at_utc' => $nowUtc,
                // Audit Fields
                'created_by' => $adminId,
                'updated_by' => $adminId,
                // deleted_at_utc, deleted_by remain NULL
            ]);

            // 3. Fetch Created Module
            $module = DB::table('modules')->where('id', $moduleId)->first();

            // 4. Log Success
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Module Created',
                'action_type' => 'create',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'record_id' => $moduleId,
                'record_identifier' => $validated['code'],
                'new_values' => json_encode($validated),
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'request_url' => $request->fullUrl(),
                'request_method' => 'POST',
                'response_code' => 201,
                'created_at_utc' => $nowUtc,
            ]);

            Log::info('Module created', [
                'module_id' => $moduleId,
                'code' => $validated['code'],
                'admin_id' => $adminId,
            ]);

            return response()->json([
                'message' => 'Module created successfully',
                'data' => $module
            ], 201);

        } catch (\Illuminate\Validation\ValidationException $e) {
            Log::error('Module validation failed', ['errors' => $e->errors()]);
            return response()->json([
                'error' => 'validation_error',
                'message' => 'The given data was invalid.',
                'errors' => $e->errors()
            ], 422);

        } catch (\Illuminate\Database\QueryException $e) {
            Log::error('Module database error', ['error' => $e->getMessage()]);
            return response()->json([
                'error' => 'database_error',
                'message' => 'Failed to create module'
            ], 500);

        } catch (\Exception $e) {
            Log::error('Module creation failed', ['error' => $e->getMessage()]);
            return response()->json([
                'error' => 'server_error',
                'message' => 'Failed to create module'
            ], 500);
        }
    }

    /**
     * PUT /api/modules/{id}
     * Update existing module
     */
    public function update(Request $request, int $id)
    {
        $nowUtc = Carbon::now('UTC');
        $adminId =  1;

        try {
            // 1. Check if Module Exists
            $module = DB::table('modules')
                ->where('id', $id)
                ->whereNull('deleted_at_utc')
                ->first();

            if (!$module) {
                return response()->json(['error' => 'Module not found'], 404);
            }

            // 2. Validate Input
            $validated = $request->validate([
                'name_en' => 'nullable|string|max:100',
                'name_native' => 'nullable|string|max:100',
                'code' => 'nullable|string|max:50|unique:modules,code,' . $id,
                'description_en' => 'nullable|string',
                'description_native' => 'nullable|string',
                'icon' => 'nullable|string|max:50',
                'display_order' => 'nullable|integer',
                'is_active' => 'nullable|boolean',
                'status' => 'nullable|in:active,inactive,archived',
            ]);

            // 3. Prepare Update Data
            $updateData = [];
            foreach ($validated as $key => $value) {
                if ($value !== null) {
                    $updateData[$key] = $value;
                }
            }

            // Add timestamps and audit fields
            $updateData['updated_at_utc'] = $nowUtc;
            $updateData['updated_by'] = $adminId;

            // 4. Update Module
            DB::table('modules')->where('id', $id)->update($updateData);

            // 5. Fetch Updated Module
            $module = DB::table('modules')->where('id', $id)->first();

            // 6. Log Success
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Module Updated',
                'action_type' => 'update',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'record_id' => $id,
                'record_identifier' => $module->code,
                'old_values' => json_encode($module),
                'new_values' => json_encode($updateData),
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'user_agent' => $request->userAgent(),
                'request_url' => $request->fullUrl(),
                'request_method' => 'PUT',
                'response_code' => 200,
                'created_at_utc' => $nowUtc,
            ]);

            Log::info('Module updated', [
                'module_id' => $id,
                'code' => $module->code,
                'admin_id' => $adminId,
            ]);

            return response()->json([
                'message' => 'Module updated successfully',
                'data' => $module
            ], 200);

        } catch (\Illuminate\Validation\ValidationException $e) {
            Log::error('Module validation failed', ['errors' => $e->errors()]);
            return response()->json([
                'error' => 'validation_error',
                'message' => 'The given data was invalid.',
                'errors' => $e->errors()
            ], 422);

        } catch (\Exception $e) {
            Log::error('Module update failed', ['error' => $e->getMessage()]);
            return response()->json([
                'error' => 'server_error',
                'message' => 'Failed to update module'
            ], 500);
        }
    }

    /**
     * PATCH /api/modules/{id}/activate
     * Activate a module
     */
    public function activate(Request $request, int $id)
    {
        $nowUtc = Carbon::now('UTC');
        $adminId =  1;

        try {
            $module = DB::table('modules')
                ->where('id', $id)
                ->whereNull('deleted_at_utc')
                ->first();

            if (!$module) {
                return response()->json(['error' => 'Module not found'], 404);
            }

            if ($module->is_active) {
                return response()->json(['message' => 'Module is already active'], 200);
            }

            DB::table('modules')->where('id', $id)->update([
                'is_active' => true,
                'status' => 'active',
                'updated_at_utc' => $nowUtc,
                'updated_by' => $adminId,
            ]);

            // Log Success
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Module Activated',
                'action_type' => 'update',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'record_id' => $id,
                'record_identifier' => $module->code,
                'new_values' => json_encode(['is_active' => true, 'status' => 'active']),
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'request_method' => 'PATCH',
                'response_code' => 200,
                'created_at_utc' => $nowUtc,
            ]);

            Log::info('Module activated', ['module_id' => $id, 'admin_id' => $adminId]);

            return response()->json([
                'message' => 'Module activated successfully',
                'data' => DB::table('modules')->where('id', $id)->first()
            ], 200);

        } catch (\Exception $e) {
            Log::error('Module activation failed', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to activate module'], 500);
        }
    }

    /**
     * PATCH /api/modules/{id}/deactivate
     * Deactivate a module
     */
    public function deactivate(Request $request, int $id)
    {
        $nowUtc = Carbon::now('UTC');
        $adminId =  1;

        try {
            $module = DB::table('modules')
                ->where('id', $id)
                ->whereNull('deleted_at_utc')
                ->first();

            if (!$module) {
                return response()->json(['error' => 'Module not found'], 404);
            }

            if (!$module->is_active) {
                return response()->json(['message' => 'Module is already inactive'], 200);
            }

            DB::table('modules')->where('id', $id)->update([
                'is_active' => false,
                'status' => 'inactive',
                'updated_at_utc' => $nowUtc,
                'updated_by' => $adminId,
            ]);

            // Log Success
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Module Deactivated',
                'action_type' => 'update',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'record_id' => $id,
                'record_identifier' => $module->code,
                'new_values' => json_encode(['is_active' => false, 'status' => 'inactive']),
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'request_method' => 'PATCH',
                'response_code' => 200,
                'created_at_utc' => $nowUtc,
            ]);

            Log::info('Module deactivated', ['module_id' => $id, 'admin_id' => $adminId]);

            return response()->json([
                'message' => 'Module deactivated successfully',
                'data' => DB::table('modules')->where('id', $id)->first()
            ], 200);

        } catch (\Exception $e) {
            Log::error('Module deactivation failed', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to deactivate module'], 500);
        }
    }

    /**
     * DELETE /api/modules/{id}
     * Soft delete (archive) a module
     */
    public function destroy(Request $request, int $id)
    {
        $nowUtc = Carbon::now('UTC');
        $adminId =  1;

        try {
            $module = DB::table('modules')
                ->where('id', $id)
                ->whereNull('deleted_at_utc')
                ->first();

            if (!$module) {
                return response()->json(['error' => 'Module not found'], 404);
            }

            // Soft delete - set deleted_at_utc and deleted_by
            DB::table('modules')->where('id', $id)->update([
                'status' => 'archived',
                'deleted_at_utc' => $nowUtc,
                'deleted_by' => $adminId,
                'updated_at_utc' => $nowUtc,
                'updated_by' => $adminId,
            ]);

            // Log Success
            DB::table('audit_logs')->insert([
                'user_id' => $adminId,
                'action_en' => 'Module Deleted',
                'action_type' => 'delete',
                'module_en' => 'RBAC',
                'table_name' => 'modules',
                'record_id' => $id,
                'record_identifier' => $module->code,
                'old_values' => json_encode($module),
                'is_successful' => true,
                'ip_address' => $request->ip(),
                'request_url' => $request->fullUrl(),
                'request_method' => 'DELETE',
                'response_code' => 200,
                'created_at_utc' => $nowUtc,
            ]);

            Log::info('Module deleted', ['module_id' => $id, 'admin_id' => $adminId]);

            return response()->json([
                'message' => 'Module deleted successfully',
                'data' => ['id' => $id, 'code' => $module->code]
            ], 200);

        } catch (\Exception $e) {
            Log::error('Module deletion failed', ['error' => $e->getMessage()]);
            return response()->json(['error' => 'Failed to delete module'], 500);
        }
    }
}