<?php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;
use App\Services\XmlParserService;
use Illuminate\Support\Facades\Auth;

class LegalDocumentController extends Controller
{
    public function index(Request $request)
    {
        try {
            // Enforce maximum per_page limit to prevent abuse
            $perPage = min((int) $request->input('per_page', 10), 50);
            $page = (int) $request->input('page', 1);
            
            // Create cache key based on request parameters
            $cacheKey = 'legal_docs_' . md5(json_encode([
                'page' => $page,
                'per_page' => $perPage,
                'search' => $request->input('search'),
                'status' => $request->input('status'),
                'fileType' => $request->input('fileType'),
                'jurisdictionId' => $request->input('jurisdictionId'),
                'lawSubjectId' => $request->input('lawSubjectId'),
                'language' => $request->input('language'),
            ]));
            
            // Cache results for 5 minutes (300 seconds)
            $result = Cache::remember($cacheKey, 300, function () use ($request, $perPage) {
                $query = DB::table('legal_documents')
                    ->leftJoin('law_subjects', 'legal_documents.law_subject_id', '=', 'law_subjects.id')
                    ->leftJoin('jurisdictions', 'legal_documents.jurisdiction_id', '=', 'jurisdictions.id')
                    ->leftJoin('users', 'legal_documents.uploaded_by', '=', 'users.id')
                    ->select(
                        'legal_documents.*',
                        'law_subjects.display_name as law_subject_name',
                        'jurisdictions.display_name as jurisdiction_name',
                        'users.name as uploaded_by_name'
                    );

                // Apply search filter with full-text search optimization
                if ($request->filled('search')) {
                    $search = $request->input('search');
                    
                    // Use full-text search if available (better performance for searching)
                    // Falls back to LIKE search for partial matches
                    $query->where(function($q) use ($search) {
                        // Try full-text search first (much faster on indexed columns)
                        $searchTerm = $search . '*'; // Add wildcard for prefix matching
                        try {
                            $q->whereRaw('MATCH(legal_documents.act_name) AGAINST(? IN BOOLEAN MODE)', [$searchTerm]);
                        } catch (\Exception $e) {
                            // Fallback to LIKE if full-text search fails
                            $q->where('legal_documents.act_name', 'like', "%{$search}%")
                              ->orWhere('legal_documents.table_name', 'like', "%{$search}%");
                        }
                    });
                }

                // Apply other filters (these use existing indexes)
                if ($request->filled('status')) {
                    $query->where('legal_documents.status', $request->input('status'));
                }

                if ($request->filled('fileType')) {
                    $query->where('legal_documents.file_type', $request->input('fileType'));
                }

                if ($request->filled('jurisdictionId')) {
                    $query->where('legal_documents.jurisdiction_id', $request->input('jurisdictionId'));
                }

                if ($request->filled('lawSubjectId')) {
                    $query->where('legal_documents.law_subject_id', $request->input('lawSubjectId'));
                }

                if ($request->filled('language')) {
                    $query->where('legal_documents.language', $request->input('language'));
                }

                // Order by most recent first
                $query->orderBy('legal_documents.created_at', 'desc');

                // Use pagination for efficient data loading
                $paginator = $query->paginate($perPage);

                // Format the documents
                $formattedDocuments = $paginator->getCollection()->map(function($doc) {
                    return [
                        'id' => $doc->id,
                        'table_name' => $doc->table_name,
                        'act_name' => $doc->act_name,
                        'file_type' => $doc->file_type,
                        'file_path' => $doc->file_path,
                        'law_subject' => [
                            'id' => $doc->law_subject_id,
                            'display_name' => $doc->law_subject_name
                        ],
                        'jurisdiction' => [
                            'id' => $doc->jurisdiction_id,
                            'display_name' => $doc->jurisdiction_name
                        ],
                        'act_types' => json_decode($doc->act_type_ids, true),
                        'language' => $doc->language,
                        'immigration_pathway' => $doc->immigration_pathway,
                        'current_to_date' => $doc->current_to_date,
                        'upload_date' => $doc->created_at,
                        'uploaded_by' => $doc->uploaded_by_name,
                        'status' => $doc->status
                    ];
                });

                return [
                    'documents' => $formattedDocuments,
                    'current_page' => $paginator->currentPage(),
                    'last_page' => $paginator->lastPage(),
                    'per_page' => $paginator->perPage(),
                    'total' => $paginator->total(),
                    'from' => $paginator->firstItem(),
                    'to' => $paginator->lastItem(),
                ];
            });

            return response()->json(array_merge(['success' => true], $result));
            
        } catch (\Exception $e) {
            Log::error('Failed to fetch documents: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString(),
                'search' => $request->input('search'),
            ]);
            
            return response()->json([
                'success' => false,
                'message' => 'Failed to fetch documents',
                'error' => config('app.debug') ? $e->getMessage() : null
            ], 500);
        }
    }

    public function show($id)
    {
        try {
            $document = DB::table('legal_documents')
                ->leftJoin('law_subjects', 'legal_documents.law_subject_id', '=', 'law_subjects.id')
                ->leftJoin('jurisdictions', 'legal_documents.jurisdiction_id', '=', 'jurisdictions.id')
                ->leftJoin('users', 'legal_documents.uploaded_by', '=', 'users.id')
                ->where('legal_documents.id', $id)
                ->select(
                    'legal_documents.*',
                    'law_subjects.display_name as law_subject_name',
                    'jurisdictions.display_name as jurisdiction_name',
                    'users.name as uploaded_by_name'
                )
                ->first();

            if (!$document) {
                return response()->json([
                    'success' => false,
                    'message' => 'Document not found'
                ], 404);
            }

            return response()->json([
                'success' => true,
                'data' => [
                    'id' => $document->id,
                    'table_name' => $document->table_name,
                    'act_name' => $document->act_name,
                    'file_type' => $document->file_type,
                    'file_path' => $document->file_path,
                    'law_subject' => [
                        'id' => $document->law_subject_id,
                        'display_name' => $document->law_subject_name
                    ],
                    'jurisdiction' => [
                        'id' => $document->jurisdiction_id,
                        'display_name' => $document->jurisdiction_name
                    ],
                    'act_types' => json_decode($document->act_type_ids, true),
                    'language' => $document->language,
                    'immigration_pathway' => $document->immigration_pathway,
                    'current_to_date' => $document->current_to_date,
                    'upload_date' => $document->created_at,
                    'uploaded_by' => $document->uploaded_by_name,
                    'status' => $document->status
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('Failed to fetch document: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to fetch document'
            ], 500);
        }
    }

    public function uploadStandardXml(Request $request)
    {
        $request->validate([
            'file' => 'required|file|max:51200',
            'actName' => 'required|string|max:255',
            'lawSubjectId' => 'required|integer',
            'actTypeIds' => 'required|json',
            'jurisdictionId' => 'required|integer',
            'language' => 'required|string',
        ]);

        try {
            $file = $request->file('file');
            
            // Validate file extension manually since MIME types can vary
            if (!in_array(strtolower($file->getClientOriginalExtension()), ['xml'])) {
                return response()->json([
                    'success' => false,
                    'message' => 'File must be an XML file'
                ], 422);
            }
            
            $actTypeIds = json_decode($request->input('actTypeIds'), true);
            
            // Generate unique filename
            $filename = time() . '_' . str_replace(' ', '_', $file->getClientOriginalName());
            
            // Store file
            $path = $file->storeAs('legal-documents/xml/standard', $filename, 'public');
            
            // Generate table name
            $tableName = 'doc_' . strtolower(preg_replace('/[^A-Za-z0-9]/', '_', $request->input('actName'))) . '_' . time();
            
            // Save document metadata
            $documentId = DB::table('legal_documents')->insertGetId([
                'table_name' => $tableName,
                'act_name' => $request->input('actName'),
                'file_type' => 'standard-xml',
                'file_path' => $path,
                'law_subject_id' => $request->input('lawSubjectId'),
                'jurisdiction_id' => $request->input('jurisdictionId'),
                'act_type_ids' => json_encode($actTypeIds),
                'language' => $request->input('language'),
                'immigration_pathway' => $request->input('immigrationPathway'),
                'current_to_date' => $request->input('currentToDate'),
                'uploaded_by' => Auth::id(),
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now()
            ]);
            
            // Parse XML and store in database
            $xmlFilePath = storage_path('app/public/' . $path);
            $xmlParser = new XmlParserService();
            $parseResult = $xmlParser->parseAndStore($xmlFilePath, $documentId);
            
            if (!$parseResult['success']) {
                Log::warning('XML parsing failed but document was saved: ' . $parseResult['message']);
            }
            
            return response()->json([
                'success' => true,
                'message' => 'Document uploaded successfully' . ($parseResult['success'] ? ' and parsed into database' : ''),
                'data' => [
                    'id' => $documentId,
                    'filename' => $filename,
                    'path' => $path,
                    'size' => $file->getSize(),
                    'actName' => $request->input('actName'),
                    'actTypeIds' => $actTypeIds,
                    'parsed' => $parseResult['success']
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('Standard XML upload failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to upload document: ' . $e->getMessage()
            ], 500);
        }
    }

    public function uploadAlternativeXml(Request $request)
    {
        $request->validate([
            'file' => 'required|file|max:51200',
            'actName' => 'required|string|max:255',
            'lawSubjectId' => 'required|integer',
            'actTypeIds' => 'required|json',
            'jurisdictionId' => 'required|integer',
            'language' => 'required|string',
        ]);

        try {
            $file = $request->file('file');
            
            // Validate file extension manually since MIME types can vary
            if (!in_array(strtolower($file->getClientOriginalExtension()), ['xml'])) {
                return response()->json([
                    'success' => false,
                    'message' => 'File must be an XML file'
                ], 422);
            }
            
            $actTypeIds = json_decode($request->input('actTypeIds'), true);
            
            $filename = time() . '_' . str_replace(' ', '_', $file->getClientOriginalName());
            $path = $file->storeAs('legal-documents/xml/alternative', $filename, 'public');
            
            $tableName = 'doc_' . strtolower(preg_replace('/[^A-Za-z0-9]/', '_', $request->input('actName'))) . '_' . time();
            
            $documentId = DB::table('legal_documents')->insertGetId([
                'table_name' => $tableName,
                'act_name' => $request->input('actName'),
                'file_type' => 'alternative-xml',
                'file_path' => $path,
                'law_subject_id' => $request->input('lawSubjectId'),
                'jurisdiction_id' => $request->input('jurisdictionId'),
                'act_type_ids' => json_encode($actTypeIds),
                'language' => $request->input('language'),
                'immigration_pathway' => $request->input('immigrationPathway'),
                'current_to_date' => $request->input('currentToDate'),
                'uploaded_by' => Auth::id(),
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now()
            ]);
            
            // Parse XML and store in database
            $xmlFilePath = storage_path('app/public/' . $path);
            $xmlParser = new XmlParserService();
            $parseResult = $xmlParser->parseAndStore($xmlFilePath, $documentId);
            
            if (!$parseResult['success']) {
                Log::warning('XML parsing failed but document was saved: ' . $parseResult['message']);
            }
            
            return response()->json([
                'success' => true,
                'message' => 'Document uploaded successfully' . ($parseResult['success'] ? ' and parsed into database' : ''),
                'data' => [
                    'id' => $documentId,
                    'filename' => $filename,
                    'path' => $path,
                    'size' => $file->getSize(),
                    'actName' => $request->input('actName'),
                    'actTypeIds' => $actTypeIds,
                    'parsed' => $parseResult['success']
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('Alternative XML upload failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to upload document: ' . $e->getMessage()
            ], 500);
        }
    }

    public function uploadPdf(Request $request)
    {
        $request->validate([
            'file' => 'required|file|mimes:pdf|max:102400',
            'actName' => 'required|string|max:255',
            'lawSubjectId' => 'required|integer',
            'actTypeIds' => 'required|json',
            'jurisdictionId' => 'required|integer',
            'language' => 'required|string',
        ]);

        try {
            $file = $request->file('file');
            $actTypeIds = json_decode($request->input('actTypeIds'), true);
            
            $filename = time() . '_' . str_replace(' ', '_', $file->getClientOriginalName());
            $path = $file->storeAs('legal-documents/pdf', $filename, 'public');
            
            $tableName = 'doc_' . strtolower(preg_replace('/[^A-Za-z0-9]/', '_', $request->input('actName'))) . '_' . time();
            
            $documentId = DB::table('legal_documents')->insertGetId([
                'table_name' => $tableName,
                'act_name' => $request->input('actName'),
                'file_type' => 'pdf',
                'file_path' => $path,
                'law_subject_id' => $request->input('lawSubjectId'),
                'jurisdiction_id' => $request->input('jurisdictionId'),
                'act_type_ids' => json_encode($actTypeIds),
                'language' => $request->input('language'),
                'immigration_pathway' => $request->input('immigrationPathway'),
                'current_to_date' => $request->input('currentToDate'),
                'uploaded_by' => Auth::id(),
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now()
            ]);
            
            return response()->json([
                'success' => true,
                'message' => 'PDF uploaded successfully',
                'data' => [
                    'id' => $documentId,
                    'filename' => $filename,
                    'path' => $path,
                    'size' => $file->getSize(),
                    'actName' => $request->input('actName'),
                    'actTypeIds' => $actTypeIds
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('PDF upload failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to upload PDF: ' . $e->getMessage()
            ], 500);
        }
    }

    public function uploadHtml(Request $request)
    {
        $request->validate([
            'actName' => 'required|string|max:255',
            'lawSubjectId' => 'required|integer',
            'actTypeIds' => 'required|json',
            'jurisdictionId' => 'required|integer',
            'language' => 'required|string',
        ]);

        // Allow either file upload or HTML content paste
        if (!$request->hasFile('file') && !$request->filled('htmlContent')) {
            return response()->json([
                'success' => false,
                'message' => 'Please provide either a file or HTML content'
            ], 422);
        }

        try {
            $actTypeIds = json_decode($request->input('actTypeIds'), true);
            $filename = time() . '_' . str_replace(' ', '_', $request->input('actName')) . '.html';
            $path = '';

            if ($request->hasFile('file')) {
                $file = $request->file('file');
                $filename = time() . '_' . str_replace(' ', '_', $file->getClientOriginalName());
                $path = $file->storeAs('legal-documents/html', $filename, 'public');
            } elseif ($request->filled('htmlContent')) {
                $path = 'legal-documents/html/' . $filename;
                Storage::disk('public')->put($path, $request->input('htmlContent'));
            }
            
            $tableName = 'doc_' . strtolower(preg_replace('/[^A-Za-z0-9]/', '_', $request->input('actName'))) . '_' . time();
            
            $documentId = DB::table('legal_documents')->insertGetId([
                'table_name' => $tableName,
                'act_name' => $request->input('actName'),
                'file_type' => 'html',
                'file_path' => $path,
                'law_subject_id' => $request->input('lawSubjectId'),
                'jurisdiction_id' => $request->input('jurisdictionId'),
                'act_type_ids' => json_encode($actTypeIds),
                'language' => $request->input('language'),
                'immigration_pathway' => $request->input('immigrationPathway'),
                'current_to_date' => $request->input('currentToDate'),
                'uploaded_by' => Auth::id(),
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now()
            ]);
            
            return response()->json([
                'success' => true,
                'message' => 'HTML content uploaded successfully',
                'data' => [
                    'id' => $documentId,
                    'filename' => $filename,
                    'path' => $path,
                    'actName' => $request->input('actName'),
                    'actTypeIds' => $actTypeIds
                ]
            ]);
        } catch (\Exception $e) {
            Log::error('HTML upload failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to upload HTML: ' . $e->getMessage()
            ], 500);
        }
    }

    public function updateStatus(Request $request, $id)
    {
        $request->validate([
            'status' => 'required|in:active,inactive'
        ]);

        try {
            DB::table('legal_documents')
                ->where('id', $id)
                ->update([
                    'status' => $request->input('status'),
                    'updated_at' => now()
                ]);

            return response()->json([
                'success' => true,
                'message' => 'Document status updated successfully'
            ]);
        } catch (\Exception $e) {
            Log::error('Status update failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to update status'
            ], 500);
        }
    }

    public function destroy($id)
    {
        try {
            $document = DB::table('legal_documents')->where('id', $id)->first();
            
            if (!$document) {
                return response()->json([
                    'success' => false,
                    'message' => 'Document not found'
                ], 404);
            }

            // Delete file from storage
            if ($document->file_path && Storage::disk('public')->exists($document->file_path)) {
                Storage::disk('public')->delete($document->file_path);
            }

            // Delete document record
            DB::table('legal_documents')->where('id', $id)->delete();

            return response()->json([
                'success' => true,
                'message' => 'Document deleted successfully'
            ]);
        } catch (\Exception $e) {
            Log::error('Document deletion failed: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to delete document'
            ], 500);
        }
    }
}
