<?php

namespace App\Http\Controllers\Workflow;

use App\Http\Controllers\Controller;
use App\Models\Workflow;
use App\Models\WorkflowStep;
use App\Models\WorkflowTransition;
use App\Models\Document;
use App\Models\WorkflowInstance;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Notification;

class WorkflowDocumentController extends Controller
{
	public function store(Request $request)
	{

		$request->validate([
			'title' => 'required|string|max:255',
			'description' => 'nullable|string',
			'tags' => 'nullable|string',
			'file' => 'nullable|file',
			'workflow_select' => 'required|exists:workflows,id',
			'start_immediately' => 'nullable|accepted',
		]);

		// Save file if uploaded
		$filePath = null;
		$fileName = null;
		if ($request->hasFile('file')) {
			$file = $request->file('file');
			$fileName = $file->getClientOriginalName();
			try {
				$filePath = $file->store('uploads', 'public');
				\Log::info('File uploaded', ['fileName' => $fileName, 'filePath' => $filePath]);
			} catch (\Exception $e) {
				\Log::error('File upload failed', ['fileName' => $fileName, 'error' => $e->getMessage()]);
				return back()->withErrors(['error' => 'File upload failed: ' . $e->getMessage()]);
			}
		}

		// Save document
		// Prepare meta tags as array of tag=>value
		$metaTags = [];
		if ($request->meta_tags && $request->meta_values) {
			foreach ($request->meta_tags as $i => $tag) {
				$value = $request->meta_values[$i] ?? null;
				if ($tag === 'Custom' && !empty($request->custom_meta_tags[$i])) {
					$tag = $request->custom_meta_tags[$i];
				}
				if ($tag && $value) {
					$metaTags[$tag] = $value;
				}
			}
		}

		$workflow = Workflow::findOrFail($request->workflow_select);
		// Debug: Log document data before saving
		try {
			$document = Document::create([
				'title' => $request->title,
				'description' => $request->description,
				'file_path' => $filePath,
				'meta_tags' => $metaTags,
				'created_by' => Auth::id(),
				'workflow_id' => $workflow->id,
				'status' => $request->has('start_immediately') ? 'pending' : 'draft',
				'started_workflow' => $request->has('start_immediately'),
			]);
			if (!$document) {
				\Log::error('Document creation failed: Model returned null', [
					'request' => $request->all(),
					'meta_tags' => $metaTags,
				]);
				return back()->withErrors(['error' => 'Failed to create document. Please try again.']);
			}
			\Log::info('Document created', ['id' => $document->id]);
		} catch (\Exception $e) {
			\Log::error('Exception during document creation', [
				'message' => $e->getMessage(),
				'trace' => $e->getTraceAsString(),
				'request' => $request->all(),
				'meta_tags' => $metaTags,
			]);
			return back()->withErrors(['error' => 'Exception: ' . $e->getMessage()]);
		}


		// Link to workflow instance
		$instance = WorkflowInstance::create([
			'workflow_id' => $workflow->id,
			'document_id' => $document->id,
			'status' => $request->has('start_immediately') ? 'in_progress' : 'draft',
		]);

		// Automatically create a workflow task for the first transition
		$firstTransition = $workflow->transitions()->orderBy('id')->first();
		$initialStep = $workflow->steps()->orderBy('order')->first();
		if ($firstTransition) {
			$assignedRole = is_array($firstTransition->role_ids) && count($firstTransition->role_ids) > 0 ? $firstTransition->role_ids[0] : null;
			$assignedUser = is_array($firstTransition->user_ids) && count($firstTransition->user_ids) > 0 ? $firstTransition->user_ids[0] : null;
			// Guard against stale references (deleted user/role) that would violate the
			// foreign key and crash document creation.
			if ($assignedUser !== null && !\App\Models\User::whereKey($assignedUser)->exists()) {
				\Log::warning('First transition references a missing user; clearing assignment', ['assigned_user' => $assignedUser, 'transition_id' => $firstTransition->id]);
				$assignedUser = null;
			}
			if ($assignedRole !== null && !\Spatie\Permission\Models\Role::whereKey($assignedRole)->exists()) {
				\Log::warning('First transition references a missing role; clearing assignment', ['assigned_role' => $assignedRole, 'transition_id' => $firstTransition->id]);
				$assignedRole = null;
			}
			\App\Models\WorkflowTask::create([
				'instance_id' => $instance->id,
				'document_id' => $document->id,
				'assigned_role' => $assignedRole,
				'assigned_user' => $assignedUser,
				'workflow_id' => $workflow->id,
				'transition_id' => $firstTransition->id ?? null,
				'status' => $request->has('start_immediately') ? 'in_progress' : 'pending',
				'step_id' => $initialStep ? $initialStep->id : null,
			]);
		}

		// Start workflow immediately if checked
		if ($request->has('start_immediately')) {
			$firstTransition = $workflow->transitions()->orderBy('id')->first();
			if ($firstTransition) {
				$userIds = $firstTransition->user_ids ?? [];
				$roleIds = $firstTransition->role_ids ?? [];
				$users = User::whereIn('id', $userIds)->get();
				// Only send notification if class exists
				if (class_exists('App\\Notifications\\WorkflowAssigned')) {
					foreach ($users as $user) {
						$alreadyNotified = \DB::table('notifications')
							->where('notifiable_id', $user->id)
							->where('notifiable_type', 'App\\Models\\User')
							->where('type', 'App\\Notifications\\WorkflowAssigned')
							->whereJsonContains('data->workflow_id', $workflow->id)
							->whereNull('read_at')
							->exists();
						if (!$alreadyNotified) {
							$user->notify(new \App\Notifications\WorkflowAssigned($document, $workflow));
						}
					}
				}
			}
		}

		return redirect()->route('workflow.myworkflow')->with('message', 'Document and workflow started successfully.');
	}

	
	public function show($id)
	{
		$document = Document::with('creator', 'workflow')->findOrFail($id);
		return view('workflow.document-show', compact('document'));
	}

	/**
	 * Stream a workflow document's attached file inline from the public disk.
	 * Serving through the controller works on any host/URL without relying on a
	 * hardcoded domain or the storage symlink.
	 */
	public function viewFile($id)
	{
		$document = Document::findOrFail($id);

		if (!$document->file_path || !\Storage::disk('public')->exists($document->file_path)) {
			abort(404, 'File not found.');
		}

		return response()->file(\Storage::disk('public')->path($document->file_path));
	}
}

