<?php

namespace App\Http\Controllers\Api\V1\Lms;

use App\Http\Controllers\Controller;
use App\Models\LmsCourse;
use App\Models\LmsCourseSettings;
use App\Models\LmsCourseAccess;
use App\Models\LmsCourseCompetency;
use App\Services\RichTextSanitizer;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;

class CourseSettingsController extends Controller
{
    /**
     * Get course settings
     */
    public function getSettings(LmsCourse $course): JsonResponse
    {
        $settings = $course->settings;

        return response()->json([
            'status' => 'success',
            'data' => $settings,
        ]);
    }

    /**
     * Update course settings
     */
    public function updateSettings(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        $validated = $request->validate([
            'certificate_enabled' => 'boolean',
            'certificate_template' => 'in:classic,modern',
            'badge_enabled' => 'boolean',
            'retakes' => 'integer|min:1',
            'instructions' => 'nullable|string',
            'instructions_json' => 'nullable',
            'completion_message' => 'nullable|string',
            'completion_message_json' => 'nullable',
        ]);

        $instructionsJson = $this->parseJsonField($request, 'instructions_json');
        if ($instructionsJson !== null) {
            $validated['instructions_json'] = $instructionsJson;
        }

        $completionMessageJson = $this->parseJsonField($request, 'completion_message_json');
        if ($completionMessageJson !== null) {
            $validated['completion_message_json'] = $completionMessageJson;
        }

        if (array_key_exists('instructions', $validated)) {
            $validated['instructions'] = RichTextSanitizer::clean($validated['instructions']);
        }

        if (array_key_exists('completion_message', $validated)) {
            $validated['completion_message'] = RichTextSanitizer::clean($validated['completion_message']);
        }

        $course->settings()->updateOrCreate(
            ['course_id' => $course->id],
            $validated
        );

        return response()->json([
            'status' => 'success',
            'message' => 'Settings updated successfully',
            'data' => $course->settings,
        ]);
    }

    /**
     * Get course access settings
     */
    public function getAccess(LmsCourse $course): JsonResponse
    {
        $access = $course->access;

        return response()->json([
            'status' => 'success',
            'data' => $access,
        ]);
    }

    /**
     * Update course access settings
     */
    public function updateAccess(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        $validated = $request->validate([
            'is_free' => 'boolean',
            'price' => 'nullable|numeric|min:0',
            'sale_price' => 'nullable|numeric|min:0',
            'sale_until' => 'nullable|date',
            'member_access_types' => 'nullable|array',
            'member_access_types.*' => 'in:public,immigration,premium',
            'redeem_code' => 'nullable|string|unique:lms_course_access',
        ]);

        $course->access()->updateOrCreate(
            ['course_id' => $course->id],
            $validated
        );

        return response()->json([
            'status' => 'success',
            'message' => 'Access settings updated successfully',
            'data' => $course->access,
        ]);
    }

    /**
     * Get course competencies
     */
    public function getCompetencies(LmsCourse $course): JsonResponse
    {
        $competencies = $course->competencies()->orderBy('order')->get();

        return response()->json([
            'status' => 'success',
            'data' => $competencies,
        ]);
    }

    /**
     * Add a competency
     */
    public function storeCompetency(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        $validated = $request->validate([
            'competency' => 'required|string',
            'description' => 'nullable|string',
            'sub_competencies' => 'nullable',
        ]);

        $subCompetencies = $this->parseJsonField($request, 'sub_competencies');
        if ($subCompetencies !== null) {
            $validated['sub_competencies'] = $subCompetencies;
        }

        $validated['course_id'] = $course->id;
        $validated['order'] = $course->competencies()->max('order') + 1 ?? 0;

        $competency = LmsCourseCompetency::create($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Competency added successfully',
            'data' => $competency,
        ], 201);
    }

    /**
     * Update a competency
     */
    public function updateCompetency(Request $request, LmsCourseCompetency $competency): JsonResponse
    {
        $this->authorize('update', $competency->course);

        $validated = $request->validate([
            'competency' => 'sometimes|string',
            'description' => 'nullable|string',
            'sub_competencies' => 'nullable',
        ]);

        $subCompetencies = $this->parseJsonField($request, 'sub_competencies');
        if ($subCompetencies !== null) {
            $validated['sub_competencies'] = $subCompetencies;
        }

        $competency->update($validated);

        return response()->json([
            'status' => 'success',
            'message' => 'Competency updated successfully',
            'data' => $competency,
        ]);
    }

    /**
     * Delete a competency
     */
    public function destroyCompetency(LmsCourseCompetency $competency): JsonResponse
    {
        $this->authorize('update', $competency->course);

        $competency->delete();

        return response()->json([
            'status' => 'success',
            'message' => 'Competency deleted successfully',
        ]);
    }

    /**
     * Save all competencies (reorder + update)
     */
    public function saveCompetencies(Request $request, LmsCourse $course): JsonResponse
    {
        $this->authorize('update', $course);

        // Check if new format (selected_units, selected_competencies, selected_sub_competencies)
        if ($request->has('selected_units') || $request->has('selected_competencies') || $request->has('selected_sub_competencies')) {
            $validated = $request->validate([
                'selected_units' => 'nullable|array',
                'selected_units.*' => 'integer',
                'selected_competencies' => 'nullable|array',
                'selected_competencies.*' => 'integer',
                'selected_sub_competencies' => 'nullable|array',
                'selected_sub_competencies.*' => 'integer',
            ]);

            // Store the selections in the course
            $course->update([
                'selected_units' => $validated['selected_units'] ?? [],
                'selected_competencies' => $validated['selected_competencies'] ?? [],
                'selected_sub_competencies' => $validated['selected_sub_competencies'] ?? [],
            ]);

            return response()->json([
                'status' => 'success',
                'message' => 'Competencies saved successfully',
                'data' => [
                    'selected_units' => $course->selected_units ?? [],
                    'selected_competencies' => $course->selected_competencies ?? [],
                    'selected_sub_competencies' => $course->selected_sub_competencies ?? [],
                ],
            ]);
        }

        // Old format (competencies array) - keep for backward compatibility
        $validated = $request->validate([
            'competencies' => 'required|array',
            'competencies.*.id' => 'sometimes|integer|exists:lms_course_competencies,id',
            'competencies.*.competency' => 'required|string',
            'competencies.*.description' => 'nullable|string',
            'competencies.*.sub_competencies' => 'nullable',
        ]);

        collect($validated['competencies'])->each(function ($comp, $index) use ($course) {
            $compId = $comp['id'] ?? null;
            $isNewCompetency = !$compId || !is_numeric($compId) || $compId < 0;

            $subCompetencies = $this->parseJsonValue($comp['sub_competencies'] ?? null);
            if ($subCompetencies !== null) {
                $comp['sub_competencies'] = $subCompetencies;
            }

            LmsCourseCompetency::updateOrCreate(
                $isNewCompetency
                    ? ['course_id' => $course->id, 'competency' => $comp['competency']]
                    : ['id' => $compId],
                [
                    'course_id' => $course->id,
                    'competency' => $comp['competency'],
                    'description' => $comp['description'] ?? null,
                    'sub_competencies' => $comp['sub_competencies'] ?? null,
                    'order' => $index,
                ]
            );
        });

        return response()->json([
            'status' => 'success',
            'message' => 'Competencies saved successfully',
            'data' => $course->competencies()->orderBy('order')->get(),
        ]);
    }

    private function parseJsonField(Request $request, string $field): ?array
    {
        if (!$request->has($field)) {
            return null;
        }

        $value = $request->input($field);
        if (is_array($value)) {
            return $value;
        }

        if (is_string($value)) {
            $decoded = json_decode($value, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $decoded;
            }
        }

        return null;
    }

    private function parseJsonValue(mixed $value): ?array
    {
        if ($value === null) {
            return null;
        }

        if (is_array($value)) {
            return $value;
        }

        if (is_string($value)) {
            $decoded = json_decode($value, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                return $decoded;
            }
        }

        return null;
    }

    /**
     * Download CSV template for bulk competency upload
     */
    public function downloadCompetencyTemplate(): \Symfony\Component\HttpFoundation\StreamedResponse
    {
        $headers = [
            'Content-Type' => 'text/csv',
            'Content-Disposition' => 'attachment; filename="competency_template.csv"',
        ];

        $callback = function() {
            $file = fopen('php://output', 'w');
            
            // CSV headers
            fputcsv($file, [
                'unit_title',
                'competency_code',
                'competency_description',
                'designation',
                'sub_competency_code',
                'sub_competency_description',
                'sub_designation'
            ]);
            
            // Example rows - prefix codes with = to force text format in Excel
            fputcsv($file, [
                'Foundational Knowledge',
                '="1.1"',
                'Demonstrates knowledge of the Canadian legal system.',
                'RCIC',
                '="1.1.1"',
                'Summarizes the Canadian justice system and the authority and scope of each division.',
                'RCIC'
            ]);
            
            fputcsv($file, [
                'Foundational Knowledge',
                '="1.1"',
                'Demonstrates knowledge of the Canadian legal system.',
                'RCIC',
                '="1.1.2"',
                'Outlines the historical development of Canadian immigration and citizenship laws.',
                'RCIC'
            ]);
            
            fputcsv($file, [
                'Foundational Knowledge',
                '="1.2"',
                'Knowledge of immigration regulations.',
                'RISIA',
                '',
                '',
                ''
            ]);
            
            fclose($file);
        };

        return response()->stream($callback, 200, $headers);
    }

    /**
     * Bulk upload competencies from CSV
     */
    public function bulkUploadCompetencies(Request $request): JsonResponse
    {
        $request->validate([
            'file' => 'required|file|mimes:csv,txt|max:5120', // 5MB max
        ]);

        $file = $request->file('file');
        $successCount = 0;
        $failedCount = 0;
        $errors = [];
        $unitsCache = [];
        $competenciesCache = [];

        DB::beginTransaction();

        try {
            $csv = array_map('str_getcsv', file($file->getPathname()));
            $headers = array_shift($csv); // Remove header row

            // Validate headers
            $expectedHeaders = [
                'unit_title',
                'competency_code',
                'competency_description',
                'designation',
                'sub_competency_code',
                'sub_competency_description',
                'sub_designation'
            ];

            if ($headers !== $expectedHeaders) {
                throw new \Exception('Invalid CSV format. Please use the template.');
            }

            $order = 0;

            foreach ($csv as $rowIndex => $row) {
                $rowNumber = $rowIndex + 2; // +2 because we removed header and arrays are 0-indexed

                try {
                    // Skip empty rows
                    if (empty(array_filter($row))) {
                        continue;
                    }

                    [$unitTitle, $compCode, $compDesc, $designation, $subCode, $subDesc, $subDesignation] = $row;

                    // Validate required fields
                    if (empty($unitTitle) || empty($compCode) || empty($compDesc) || empty($designation)) {
                        throw new \Exception("Missing required fields");
                    }

                    // Validate designation
                    if (!in_array($designation, ['RCIC', 'RISIA', 'BOTH'])) {
                        throw new \Exception("Invalid designation: {$designation}. Must be RCIC, RISIA, or BOTH");
                    }

                    // Get or create unit
                    $unitKey = strtolower(trim($unitTitle));
                    if (!isset($unitsCache[$unitKey])) {
                        $unit = DB::table('competency_units')
                            ->where('title', $unitTitle)
                            ->first();

                        if (!$unit) {
                            $unitId = DB::table('competency_units')->insertGetId([
                                'title' => $unitTitle,
                                'order' => count($unitsCache),
                                'created_at' => now(),
                                'updated_at' => now(),
                            ]);
                            $unitsCache[$unitKey] = $unitId;
                        } else {
                            $unitsCache[$unitKey] = $unit->id;
                        }
                    }
                    $unitId = $unitsCache[$unitKey];

                    // Get or create main competency
                    $compKey = strtolower(trim($compCode));
                    if (!isset($competenciesCache[$compKey])) {
                        $existingComp = DB::table('competencies')
                            ->where('code', $compCode)
                            ->where('unit_id', $unitId)
                            ->whereNull('parent_id')
                            ->first();

                        if (!$existingComp) {
                            $compId = DB::table('competencies')->insertGetId([
                                'unit_id' => $unitId,
                                'parent_id' => null,
                                'code' => $compCode,
                                'description' => $compDesc,
                                'designation' => $designation,
                                'order' => $order++,
                                'created_at' => now(),
                                'updated_at' => now(),
                            ]);
                            $competenciesCache[$compKey] = $compId;
                        } else {
                            $competenciesCache[$compKey] = $existingComp->id;
                            // Skip - competency already exists
                        }
                    }
                    $compId = $competenciesCache[$compKey];

                    // Create sub-competency if provided
                    if (!empty($subCode) && !empty($subDesc)) {
                        if (empty($subDesignation)) {
                            throw new \Exception("Sub-competency designation is required when sub-competency is provided");
                        }

                        if (!in_array($subDesignation, ['RCIC', 'RISIA', 'BOTH'])) {
                            throw new \Exception("Invalid sub-designation: {$subDesignation}");
                        }

                        // Check if sub-competency already exists
                        $existingSub = DB::table('competencies')
                            ->where('code', $subCode)
                            ->where('parent_id', $compId)
                            ->first();

                        if (!$existingSub) {
                            DB::table('competencies')->insert([
                                'unit_id' => $unitId,
                                'parent_id' => $compId,
                                'code' => $subCode,
                                'description' => $subDesc,
                                'designation' => $subDesignation,
                                'order' => $order++,
                                'created_at' => now(),
                                'updated_at' => now(),
                            ]);
                        }
                        // Skip if exists
                    }

                    $successCount++;

                } catch (\Exception $e) {
                    $failedCount++;
                    $errors[] = [
                        'row' => $rowNumber,
                        'message' => $e->getMessage(),
                    ];
                }
            }

            DB::commit();

            return response()->json([
                'status' => 'success',
                'data' => [
                    'processed' => $successCount + $failedCount,
                    'success' => $successCount,
                    'failed' => $failedCount,
                    'errors' => $errors,
                ],
            ]);

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

            return response()->json([
                'status' => 'error',
                'message' => $e->getMessage(),
            ], 400);
        }
    }
}
